CVS difference for ai12s/ai12-0190-1.txt

Differences between 1.9 and version 1.10
Log of other versions for file ai12s/ai12-0190-1.txt

--- ai12s/ai12-0190-1.txt	2018/12/14 08:20:20	1.9
+++ ai12s/ai12-0190-1.txt	2019/01/09 04:12:05	1.10
@@ -1,4 +1,4 @@
-!standard 4.4(7/3)                                  18-12-11  AI12-0190-1/05
+!standard 4.4(7/3)                                  18-12-13  AI12-0190-1/06
 !standard 4.5.9(0)
 !class Amendment 16-06-02
 !status Amendment 1-2012 18-12-10
@@ -37,24 +37,24 @@
 
 !proposal
 
-A function_expression can be used in a context where the expected type is a
+An anonymous_function can be used in a context where the expected type is a
 single access-to-function type (or as the actual parameter for a formal
 function). It is roughly equivalent to using the name'Access (or simply
 name) of an expression function which is declared at the point of use,
 with parameter types, modes, etc. taken from that of the expected
 access-to-function type (or the formal function). Only the formal
-parameter names come from the function_expression.
+parameter names come from the anonymous_function.
 
-    primary ::= function_expression
+    primary ::= anonymous_function
 
-    function_expression ::=
+    anonymous_function ::=
       ( FUNCTION [ function_formal_parameter_list ] RETURN expression )
 
     function_formal_parameter_list ::=
       ( identifier { , identifier } ) | formal_part
 
 We allow only a single expression as the body of the
-function_expression.  Given that we now have "if" expressions and "case"
+anonymous_function.  Given that we now have "if" expressions and "case"
 expressions, this is not a serious limitation.  (The possible addition
 of "declare expressions" would be a welcome enhancement.)
 
@@ -62,12 +62,12 @@
 
 Replace 4.4(7/3) with:
 
-  primary ::= 
+  primary ::=
      numeric_literal | null | string_literal | aggregate
    | name | allocator | (expression)
    | (conditional_expression) | (quantified_expression)
-   | function_expression
-   
+   | anonymous_function
+
 Add section after 4.5.8:
 
   4.5.9 Function Expressions
@@ -76,23 +76,23 @@
   where an access-to-function type is the expected type, or in a generic
   instantiation as an actual parameter corresponding to a formal subprogram
   parameter.
-  
+
               Syntax
-              
-    function_expression ::=
+
+    anonymous_function ::=
       (FUNCTION [function_formal_parameter_list] RETURN expression)
 
     function_formal_parameter_list ::=
       formal_part | (identifier {, identifier})
 
              Name Resolution Rules
-             
+
   In a context where there is an expected type rather than an expected
-  profile for a function_expression, the expected type shall be a single
-  access-to-function type, and the profile of this type is considered
-  the expected profile for the function_expression.  The result type of
-  the expected profile of the function_expression is the expected type
-  for the expression of the function_expression. If there is no
+  profile for an anonymous_function, the expected type shall be a single
+  anonymous access-to-function type, and the profile of this type is considered
+  the expected profile for the anonymous_function.  The result type of
+  the expected profile of the anonymous_function is the expected type
+  for the expression of the anonymous_function. If there is no
   function_formal_parameter_list, the expected profile shall have no
   parameters.  If the function_formal_parameter_list is a formal_part,
   then it shall be subtype conformant to the expected profile if there
@@ -100,24 +100,37 @@
   function_formal_parameter_list is a sequence of identifiers, the
   number of identifiers in the sequence shall be the same as the number
   of formal parameters in the expected profile.
-  
+
+           Legality Rules
+
+  When used in a context where there is an expected type, the
+  anonymous_function shall be an actual parameter in a call, or a
+  parameter default for a callable entity.
+
            Static Semantics
 
-  A function_expression used in a context where there is an expected
-  type is equivalent to a local expression_function_declaration (see
-  6.8), with the function_expression replaced by an Access
+  An anonymous_function used in a context where there is an expected
+  type is equivalent to an expression_function_declaration (see
+  6.8) declared within the innermost declarative region, with the
+  anonymous_function replaced by an Access
   attribute_reference of this locally defined function; otherwise, the
-  function_expression is equivalent to such a local declaration with the
-  function_expression replaced by a name denoting this locally defined
+  anonymous_function is equivalent to such a local declaration with the
+  anonymous_function replaced by a name denoting this locally defined
   function.  The profile of this locally defined function has a result
   type determined by the expected profile, and a formal part determined
-  by the formal_part, if provided in the function_expression, or by the
+  by the formal_part, if provided in the anonymous_function, or by the
   formal part of the expected profile otherwise, but with the name of
   each formal parameter of the expected profile replaced by the
   corresponding identifier in the sequence of identifiers.  The expression
   of this locally defined expression function is that of the
-  function_expression. 
+  anonymous_function.
+
+  AARM To Be Honest: Depending on the nature of the innermost enclosing
+  declarative region, this equivalence might violate the normal syntax rules
+  which would not permit such an expression_function_declaration in such a
+  region.
 
+
 !discussion
 
 We are using the reserved words FUNCTION and RETURN rather than defining
@@ -125,25 +138,24 @@
 parameter list, as that is their normal place in the syntax for declaring a
 named function.
 
-We considered other names such as "lambda functions," "function
-literals," and "anonymous functions."  We ultimately went with "function
-expression" as it seemed analogous to "if expression" and "case
-expression," though there is admittedly some discomfort in having both
-"expression functions" and "function expressions."
+We considered other names such as "lambda expressions," "function
+literals," and "function expressions."  We ultimately went with
+"anonymous functions" to avoid confusion between "expression functions"
+and "function expressions."
 
 We allow, but do not require, a full formal part as part of the
-function_expression. Requiring a full formal part seems unnecessary and
+anonymous_function. Requiring a full formal part seems unnecessary and
 verbose, since the parameter (and result) types are always provided by the
 profile of the formal access-to-function parameter.
 
 We are only supporting defining anonymous functions using this proposed
-"function_expression" construct.  Anonymous procedures are nicely
+"anonymous_function" construct.  Anonymous procedures are nicely
 handled with the loop-body proposal (AI12-0189).  In any case, mixing
 statements inside expressions seems like a bad idea.  Also, we don't
 have "expression procedures" so it doesn't seem so bad that we don't
 have "procedure expressions" ;-).
 
-One place where it might be nice to allow a "procedure expression" would
+One place where it might be nice to allow a "anonymous procedure" would
 be when you want to pass in a do-nothing procedure, which is not
 uncommon when instantiating a generic with a formal procedure.  We allow
 using "null" as the default for a formal procedure, as well as when
@@ -151,6 +163,12 @@
 "null" as the actual parameter for a formal procedure, meaning a
 "do-nothing" procedure.
 
+We limit this to cases of anonymous access-to-subprogram types used
+as function parameters.  Other cases, like access discriminants and
+stand-alone access objects seemed like more trouble that they are worth,
+since those generally occur in contexts where declaring a local subprogram
+is not a burden.
+
 !example
 
     --  Replace control chars with '?'
@@ -168,6 +186,10 @@
     Plot_Graph (Fun => (function (Z) return Z**2),
                 Start => 1.0, Stop => 20.0);
 
+!comment The following were for the version approved and then recended in
+!comment December 2018, except to replace "function_expression" with
+!comment "anonymous_function" globally.
+
 !corrigendum 4.4(7/3)
 
 @drepl
@@ -180,7 +202,7 @@
    @fa<numeric_literal | >@ft<@b<null>>@fa< | string_literal | aggregate>
  @fa<| name | allocator | (expression)>
  @fa<| (conditional_expression) | (quantified_expression)>
- @fa<| function_expression>>
+ @fa<| anonymous_function>>
 
 !corrigendum 4.5.9(0)
 
@@ -190,23 +212,23 @@
 where an access-to-function type is the expected type, or in a generic
 instantiation as an actual parameter corresponding to a formal subprogram
 parameter.
-  
+
 @s8<@i<Syntax>>
-              
-@xcode<@fa<function_expression ::=>
+
+@xcode<@fa<anonymous_function ::=>
    @fa<(>@ft<@b<function>>@fa< [function_formal_parameter_list] >@ft<@b<return>>@fa< expression)>>
 
 @xcode<@fa<function_formal_parameter_list ::=>
    @fa<formal_part | (identifier {, identifier})>>
 
 @s8<@i<Name Resolution Rules>>
-             
+
 In a context where there is an expected type rather than an expected
-profile for a @fa<function_expression>, the expected type shall be a single
+profile for a @fa<anonymous_function>, the expected type shall be a single
 access-to-function type, and the profile of this type is considered
-the expected profile for the @fa<function_expression>. The result type of
-the expected profile of the @fa<function_expression> is the expected type
-for the expression of the @fa<function_expression>. If there is no
+the expected profile for the @fa<anonymous_function>. The result type of
+the expected profile of the @fa<anonymous_function> is the expected type
+for the expression of the @fa<anonymous_function>. If there is no
 @fa<function_formal_parameter_list>, the expected profile shall have no
 parameters. If the @fa<function_formal_parameter_list> is a @fa<formal_part>,
 then it shall be subtype conformant to the expected profile if there
@@ -214,23 +236,23 @@
 @fa<function_formal_parameter_list> is a sequence of identifiers, the
 number of identifiers in the sequence shall be the same as the number
 of formal parameters in the expected profile.
-  
+
 @s8<@i<Static Semantics>>
 
-A @fa<function_expression> used in a context where there is an expected
+A @fa<anonymous_function> used in a context where there is an expected
 type is equivalent to a local @fa<expression_function_declaration> (see
-6.8), with the @fa<function_expression> replaced by an Access
+6.8), with the @fa<anonymous_function> replaced by an Access
 @fa<attribute_reference> of this locally defined function; otherwise, the
-@fa<function_expression> is equivalent to such a local declaration with the
-@fa<function_expression> replaced by a @fa<name> denoting this locally defined
+@fa<anonymous_function> is equivalent to such a local declaration with the
+@fa<anonymous_function> replaced by a @fa<name> denoting this locally defined
 function. The profile of this locally defined function has a result
 type determined by the expected profile, and a formal part determined
-by the @fa<formal_part>, if provided in the @fa<function_expression>, or by the
+by the @fa<formal_part>, if provided in the @fa<anonymous_function>, or by the
 formal part of the expected profile otherwise, but with the name of
 each formal parameter of the expected profile replaced by the
 corresponding identifier in the sequence of identifiers. The @fa<expression>
 of this locally defined expression function is that of the
-@fa<function_expression>. 
+@fa<anonymous_function>.
 
 !ASIS
 
@@ -1886,8 +1908,8 @@
 I like the idea of function expressions overall. I have just a couple of
 comments.
 
->> We are only supporting defining anonymous functions using this 
->> proposed "function_expression" construct.  Anonymous procedures are 
+>> We are only supporting defining anonymous functions using this
+>> proposed "function_expression" construct.  Anonymous procedures are
 >> nicely handled with the loop-body proposal (AI12-0189).
 
 Not really. The loop-body proposal only applies to a limited subset of cases
@@ -1902,35 +1924,35 @@
 
 It might be nice to write a combiner function as a function expression in some
 cases, for instance, which I presume would be allowed by the AI, (for
-combiners that are functions). Similarly, I presume one could use function 
-expressions for generic actuals when instantiating a generic. 
+combiners that are functions). Similarly, I presume one could use function
+expressions for generic actuals when instantiating a generic.
 
 eg. See below
 
 >> In any case, mixing
->> statements inside expressions seems like a bad idea.  Also, we don't 
->> have "expression procedures" so it doesn't seem so bad that we don't 
+>> statements inside expressions seems like a bad idea.  Also, we don't
+>> have "expression procedures" so it doesn't seem so bad that we don't
 >> have "procedure expressions" ;-).
 
 This seems like the better argument.
 
 >> !example
->> 
+>>
 >>    --  Replace control chars with '?'
 >>    Ada.Strings.Fixed.Translate
 >>      (Str, (function (C) return (if C < ' ' then '?' else C)));
->> 
+>>
 >>    --  Procedure for plotting a function
 >>    procedure Plot_Graph
 >>      (Fun : access function (X : Float) return Float;
 >>       Start, Stop : Float);
->> 
+>>
 >>    ...
->> 
+>>
 >>    --  Plot a graph of X-squared from 1 to 20
 >>    Plot_Graph (Fun => (function (Z) return Z**2),
 >>                Start => 1.0, Stop => 20.0);
->> 
+>>
 
 I have another example for consideration.
 
@@ -1942,3 +1964,1040 @@
                                          "="          => (function (L, R) return (L mod 360 = R mod 360)));
 
 ****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, December 12, 2018  6:08 PM
+
+I put AI12-0190-1 into the draft RM last night, which rekindled all of my real
+objections to that proposal, and contrasted it against the FUD that was used to
+kill the much more valuable (IMHO) generic type defaults. [There is absolutely
+nothing new in the implementation of generic type defaults, all of the potential
+issues already exist in a similar form in existing generic
+declarations/instantiations. Obviously, anything can be an issue for a specific
+implementation (especially if a hack was used to implement something), but
+AI12-0205-1 is among the least likely to have such an issue. OTOH, the
+implementation of function expressions has several new things which potentially
+cause issues - it is a much more reasonable candidate to worry about
+implementation cost. And, it mainly is a writing aid, at best, readability is a
+wash, where one has traded the declaration of an extra name for a nested
+construct (which necessarily makes the outer construct harder to read) and Lots
+of Irritating Stupid Parentheses :-).]
+
+Anyway, that's settled but I'll keep griping about it for years. :-)
+
+However, in thinking about the implementation problems, I started wondering how
+it is supposed to work when it appears in any sort of default expression. In
+particular, consider:
+
+   package Pack is
+      function Ugh (P : Natural := Foo ((function (A) return A*2), 2)) return Natural;
+   end Pack;
+
+   package body Pack is
+      function Ugh (P : Natural := Foo ((function (A) return A*2), 2)) return Natural is ...
+   end Pack;
+
+   with Pack;
+   procedure Main is
+      V : Natural := Pack.Ugh;
+   begin
+      Put (V'Image);
+   end Main;
+
+Questions:
+   (1) Do we have rules to deal with function expressions in conformance? In
+      particular, don't we need rules about the conformance of the formal parts?
+      (Two paragraphs of semantics for this feature is clearly too good to be
+      true. :-(  )
+   In particular, we wouldn't want the body to differ. But which of these differ (or should differ) and why?
+      [A] function Ugh (P : Natural := Foo ((function (B) return B*2), 2)) return Natural is ...
+      [B] function Ugh (P : Natural := Foo ((function (A : Natural) return A*2), 2)) return Natural is ...
+      [C] function Ugh (P : Natural := Foo ((function (A) return B*3), 2)) return Natural is ...
+   Clearly [C] had better fail conformance, but what about the others?
+
+   (2) The rule about evaluating a function expression says that a function
+       expression "... is equivalent to a local expression_function_declaration
+       ...". But local where?
+      [A] The first occurrence (the specification of Pack);
+      [B] Both occurrences (both the specification and body of Pack -- this would imply that they never conform).
+      [C1] At the point of use (in the body of Main), with names resolved at the first point of occurrence;
+      [C2] At the point of use (in the body of Main), with names resolved at the point of use.
+    Default expressions can also occur in record declarations and generic in
+    parameters, so even saying that these never conform does not eliminate the
+    question.
+
+    The wording is mainly "Static Semantics", which would imply [B], but that of
+    course would require doing some code generation for default expressions at
+    the point of declaration [I know the Janus/Ada can't do that as currently
+    designed]. And it also would prevent any conformance (since there'd be two
+    separate functions declared by the two declarations, which could never be
+    allowed).
+
+Thoughts?
+
+P.S. I found and fixed a place in the AI where "expression_function" was used
+instead of "function_expression". Luckily the former isn't actually a thing
+(that's "expression_function_declaration"), so I got a formatting error and
+caught it. This naming will drive us nuts. Grump.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, December 12, 2018  7:09 PM
+
+> Do we have rules to deal with function expressions in conformance? In
+> particular, don't we need rules about the conformance of the formal parts?
+
+We've got the conformance rule that was added in AI12-0050, motivated by
+quantified expressions:
+
+    each [blah] in one denotes the same
+    declaration as the corresponding [blah] in the other,
+    or they denote corresponding declarations
+    occurring within the two expressions; and
+
+So I think all that is needed here is a friendly (but not unreasonably so)
+reading of the word "corresponding".
+
+I don't think any RM wording changes are needed to deal with this issue.
+
+If the two versions differ syntactically (e.g., your completion [B], which
+explicitly names the parameter subtype when the first default expression did
+not), then they don't conform. I think that follows from 6.3.1(20)'s "same
+syntactic category" wording.
+
+>
+>    (2) The rule about evaluating a function expression says that a
+> function expression "... is equivalent to a local
+> expression_function_declaration ...". But local where?
+
+That's a good question and it looks to me like we do need some wording here (but
+I didn't review the AI carefully with this question in mind - if Bob explains
+that there is really no problem here and this is already handled very nicely, I
+won't be surprised).
+
+I think that, roughly speaking, we'd like something along the lines of
+    first, find the nearest enclosing statement or declaration.
+    if it is a declaration, then the implicit subprogram declaration goes
+    immediately ahead of that declaration.
+    if it is a statement, then wrap an implicit block statement around
+    that statement and put the implicit declaration in the declarative
+    part of that block statement.
+
+I think this is the model we want for dynamic semantics and for static
+accessibility checking, although hopefully expressed with better wording than
+the above. And this approach may need to be extended to handle cases like a
+generic formal subprogram default which contains references to earlier generic
+formal parameters.
+
+The key idea is that there should be a (hopefully straightforward) equivalence
+rule for defining this new construct in terms of old code that does not contain
+this new construct.
+
+But can one of these guys reference, for example, the identifier of a quantified
+expression (or the defining identifier of an iterated component association, or
+...)?
+
+     (for all Idx in Vec'Range =>
+        Foo ((function (J) return J <= Idx), 2))
+         --  Is the use of Idx legal?
+
+If so, then the model I sketched out breaks down and things are more
+complicated.
+
+I don't think we want to allow this case, but that's just my opinion.
+
+It does sound like some more discussion of this (approved) AI is needed.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, December 12, 2018  9:04 PM
+
+> ...
+>    (for all Idx in Vec'Range =>
+>       Foo ((function (J) return J <= Idx), 2))
+>        --  Is the use of Idx legal?
+>
+> If so, then the model I sketched out breaks down and things are more
+> complicated.
+>
+> I don't think we want to allow this case, but that's just my opinion.
+
+I am not sure.  This seems to be a fairly natural use of this feature.  I would
+be reluctant to start adding complicated restrictions in what names can be
+mentioned in the expression without a good reason.
+
+I am not sure we need to provide too prescriptive a definition of the
+implementation approach.  I would hope that the expression's name resolution
+should have visibility on the innermost declarative region, independent of
+whether that is a declare block, a loop, or an iterator.  That is pretty much
+how names work in most cases, and I don't think we should change that for these.
+Carving holes into the enclosing visibility seems like bad news in many ways.
+
+As far as accessibility, if a function expression is used as a generic actual or
+in a rename, "local" is quite well defined.  For a parameter of a function call,
+the master that evaluated the construct can provide a well-defined accessibility
+level for such a "local" function, meaning that it would be fine for an
+anonymously-typed access-to-subprogram parameter, but would never match a
+parameter of a named access-to-subprogram type.
+
+> It does sound like some more discussion of this (approved) AI is needed.
+
+It sounds like we might need a mild tweak to the conformance rules. But I am
+reluctant to try to spell out the implementation model in great detail.  All
+names visible at the point of the construct should be usable, and maybe the
+simplest thing to do about accessibility is to only allow these to match the
+anonymous access type of a function parameter, and steer clear of all named
+access types or anonymous access types in other contexts.
+
+Accordingly, here are some adjustments to AI12-0190-1, using our usual [...] and
+{...}:
+
+             Name Resolution
+
+  In a context where there is an expected type rather than an expected
+  profile for a function_expression, the expected type shall be a single
+  {anonymous} access-to-function type, and the profile of this type is considered
+  the expected profile for the function_expression.  The result type of
+  the expected profile of the function_expression is the expected type
+  for the expression of the function_expression. If there is no
+  function_formal_parameter_list, the expected profile shall have no
+  parameters.  If the function_formal_parameter_list is a formal_part,
+  then it shall be subtype conformant to the expected profile if there
+  is an expected type, or merely mode conformant otherwise.  If the
+  function_formal_parameter_list is a sequence of identifiers, the
+  number of identifiers in the sequence shall be the same as the number
+  of formal parameters in the expected profile.
+
+{           Legality Rules
+
+When used in a context where there is an expected type, the function_expression
+shall be an actual parameter in a call, or a parameter default for a callable
+entity, where the corresponding formal is of an anonymous access-to-subprogram
+type.}
+
+           Static Semantics
+
+  A function_expression used in a context where there is an expected
+  type is equivalent to [a local] {an} expression_function_declaration
+  (see 6.8) {declared within the innermost enclosing declarative region},
+  with the function_expression replaced by an Access
+  attribute_reference of this locally defined function; otherwise, the
+  function_expression is equivalent to such a local declaration with the
+  function_expression replaced by a name denoting this locally defined
+  function.  The profile of this locally defined function has a result
+  type determined by the expected profile, and a formal part determined
+  by the formal_part, if provided in the expression_function, or by the
+  formal part of the expected profile otherwise, but with the name of
+  each formal parameter of the expected profile replaced by the
+  corresponding identifier in the sequence of identifiers.  The expression
+  of this locally defined expression function is that of the
+  function_expression.
+
+ {AARM To Be Honest: Depending on the nature of the innermost enclosing
+  declarative region, this equivalence might violate the normal syntax rules
+  which would not permit such an expression_function_declaration in such a
+  region.}
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, December 13, 2018  11:41 AM
+
+>    (1) Do we have rules to deal with function expressions in
+>    conformance?
+
+I agree with Steve that the current wording is good enough.
+Feel free to add some examples to the AARM to clarify.
+
+> ... In
+> particular, don't we need rules about the conformance of the formal parts?
+> (Two paragraphs of semantics for this feature is clearly too good to
+> be true. :-(  )
+>    In particular, we wouldn't want the body to differ. But which of
+> these differ (or should differ) and why?
+>       [A] function Ugh (P : Natural := Foo ((function (B) return B*2), 2)) return Natural is ...
+>       [B] function Ugh (P : Natural := Foo ((function (A : Natural) return A*2), 2)) return Natural is ...
+>       [C] function Ugh (P : Natural := Foo ((function (A) return B*3), 2)) return Natural is ...
+>    Clearly [C] had better fail conformance, but what about the others?
+
+A and B should not conform, IMHO.  And of course I agree about C.
+
+>    (2) The rule about evaluating a function expression says that a
+> function expression "... is equivalent to a local
+> expression_function_declaration ...". But local where?
+
+It bothers me that if you instantiate a generic package in a package spec, the
+instance body occurs in the package spec, even though that's syntactically
+illegal.  But we've lived with that for decades.
+
+This case doesn't bother me any more than that, so I can live with it.  Tucker's
+wording seems OK.
+
+>       [A] The first occurrence (the specification of Pack);
+
+Yes.
+
+>       [B] Both occurrences (both the specification and body of Pack --
+> this would imply that they never conform).
+
+That would be unfortunate -- default values are a fairly natural place to use this feature.
+
+>       [C1] At the point of use (in the body of Main), with names
+> resolved at the first point of occurrence;
+
+No.
+
+>       [C2] At the point of use (in the body of Main), with names
+> resolved at the point of use.
+
+No, NO, NO!  ;-)
+
+>     Default expressions can also occur in record declarations and
+> generic in parameters, so even saying that these never conform does
+> not eliminate the question.
+
+Right.  And I don't like the "never conform" option anyway.
+
+>     The wording is mainly "Static Semantics", which would imply [B],
+> but that of course would require doing some code generation for
+> default expressions at the point of declaration [I know the Janus/Ada
+> can't do that as currently designed]. And it also would prevent any
+> conformance (since there'd be two separate functions declared by the
+> two declarations, which could never be allowed).
+
+It seems to me you can generate code whereever/whenever you like, regardless of
+what the RM says.
+
+> Thoughts?
+>
+> P.S. I found and fixed a place in the AI where "expression_function"
+> was used instead of "function_expression". Luckily the former isn't
+> actually a thing (that's "expression_function_declaration"), so I got
+> a formatting error and caught it. This naming will drive us nuts. Grump.
+
+I agree -- having "expression function" and "function_expression" mean two
+different things is intolerable.  I think we had better change the name.  (We
+don't have "expression_function", but we do have "expression function").
+
+Ideas: function_literal, literal_function, lambda, lambda_function.
+
+It's probably too late to do it the other way around (e.g. change
+"expression_function_declaration" to "shorthand_function_declaration".
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, December 13, 2018  11:41 AM
+
+> I think that, roughly speaking, we'd like something along the lines of
+>     first, find the nearest enclosing statement or declaration.
+>     if it is a declaration, then the implicit subprogram declaration goes
+>     immediately ahead of that declaration.
+>     if it is a statement, then wrap an implicit block statement around
+>     that statement and put the implicit declaration in the declarative
+>     part of that block statement.
+
+I don't think we want something like that in the RM.  I find the wording in the
+AI, or perhaps Tuckers wording, preferable.
+
+It's appalling that 6.3.1 has grown from 6 clear paragraphs in Ada 83 (not
+counting NOTES) to 37 impenetrable paragraphs in Ada 2012. Let's not continue on
+that path.  ;-)
+
+> But can one of these guys reference, for example, the identifier of a
+> quantified expression (or the defining identifier of an iterated
+> component association, or ...)?
+>
+>      (for all Idx in Vec'Range =>
+>         Foo ((function (J) return J <= Idx), 2))
+>          --  Is the use of Idx legal?
+
+I think it should be.
+
+But it's worse than you imply, because what if there's another Idx declared
+outside this?  We certainly don't want Idx to denote that outer thing.  That
+would introduce something like the infamous "with statement" language design
+flaw that exists in Pascal.
+
+I could (barely) tolerate making these things illegal inside "for all", but as
+Tuck said, it's a pretty natural thing to want to do.
+
+> It does sound like some more discussion of this (approved) AI is needed.
+
+Sigh.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, December 13, 2018  12:29 PM
+
+>              Name Resolution
+>
+>   In a context where there is an expected type rather than an expected
+>   profile for a function_expression, the expected type shall be a single
+>   {anonymous} access-to-function type
+> ...
+> {           Legality Rules
+>
+> When used in a context where there is an expected type, the
+> function_expression shall be an actual parameter in a call, or a
+> parameter default for a callable entity, where the corresponding
+> formal is of an anonymous access-to-subprogram type.}
+
+Isn't the part starting ", where" redundant with the Name Res rule?
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, December 13, 2018  1:20 PM
+
+Yes, good point.  When I wrote it I thought there was something still not
+implied by the Name Res rules, but now I agree with you, the phrase can be
+dropped.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, December 13, 2018  1:45 PM
+
+>  I think we had better change the
+> name.  (We don't have "expression_function", but we do have
+> "expression function").
+>
+> Ideas: function_literal, literal_function, lambda, lambda_function.
+
+I like "function_literal," analogous to string_literal.
+
+I could see "lambda_expression" though the word "lambda" kind of comes out of
+thin air for the reader who doesn't recognize the term.
+
+Here is WikiPedia's entry on this concept:
+
+"In computer programming, an anonymous function (function literal, lambda
+abstraction, or lambda expression) is a function definition that is not bound to
+an identifier. Anonymous functions are often arguments being passed to
+higher-order functions, ..."
+
+It seems worth picking one from their list, if we decide to go away from
+"function_expression" (which I think is still OK, FWIW), rather than inventing
+yet another Ada-specific term.
+
+So "function_literal," "anonymous_function," and "lambda_expression" all seem
+reasonable alternatives to "function_expression.
+
+****************************************************************
+
+From: Gary Dismukes
+Sent: Thursday, December 13, 2018  2:29 PM
+
+> I like "function_literal," analogous to string_literal.
+
+That one doesn't appeal to me.  In Ada, literals are single tokens.
+
+> I could see "lambda_expression" though the word "lambda" kind of comes out
+>of thin air for the reader who doesn't recognize the term.
+>
+> Here is WikiPedia's entry on this concept:
+>
+> "In computer programming, an anonymous function (function literal, lambda
+> abstraction, or lambda expression) is a function definition that is not
+> bound to an identifier. Anonymous functions are often arguments being
+> passed to higher-order functions, ..."
+>
+> It seems worth picking one from their list, if we decide to go away from
+> "function_expression" (which I think is still OK, FWIW), rather than
+> inventing yet another Ada-specific term.
+>
+> So "function_literal," "anonymous_function," and "lambda_expression" all
+> seem reasonable alternatives to "function_expression.
+
+Anonymous_function seems reasonable.  I could live with function_expression, but
+it does potentially create confusion with expression functions, so I think we
+should change it if we can agree on another name.
+
+****************************************************************
+
+From: Tullio Vardanega
+Sent: Thursday, December 13, 2018  2:37 PM
+
+What about "a lambda expression, that is, is a function definition that is not
+bound to an identifier"?
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, December 13, 2018  3:00 PM
+
+> I could see "lambda_expression" though the word "lambda" kind of comes
+> out of thin air for the reader who doesn't recognize the term.
+
+Doesn't every programmer learn at least a small amount of Lisp in their
+"Comparative Programming Languages" course?
+
+> Here is WikiPedia's entry on this concept:
+>
+> "In computer programming, an anonymous function (function literal,
+> lambda abstraction, or lambda expression) is a function definition
+> that is not bound to an identifier. Anonymous functions are often
+> arguments being passed to higher-order functions, ..."
+>
+> It seems worth picking one from their list, if we decide to go away
+> from "function_expression" (which I think is still OK, FWIW), rather
+> than inventing yet another Ada-specific term.
+
+Good point.  I hate when languages get creative with their terms when everybody
+else already has a perfectly good term.
+
+Or three.  ;-)
+
+> So "function_literal," "anonymous_function," and "lambda_expression"
+> all seem reasonable alternatives to "function_expression.
+
+I'm happy with all three of those.  My favorite is "anonymous_function".
+
+I really think having both "expression function" and "function_expression" is
+confusing -- embarrassingly so.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, December 13, 2018  3:07 PM
+
+The term "anonymous" is already used in several contexts in Ada, so using it for
+these sorts of functions seems pretty appropriate and consistent.  I like
+"lambda expression" except for the fact it introduces the term "lambda" into the
+language and a chapter called "Lambda Expressions" would be pretty mysterious to
+programmers who have not taken that "Comparative Programming Languages" course
+(alas, I suspect that is many "programmers" these days).  It would be easy for
+any Ada user to guess what is going on in a chapter called "Anonymous
+Functions."
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, December 13, 2018  3:56 PM
+
+...
+> It does sound like some more discussion of this (approved) AI is
+> needed.
+
+This seems like a "reopen" rather than a "fix-up" situation, because (A) there
+is a lot of issues that were not resolved - including the name of the thing, (B)
+resolving those issues might cause people to change their vote on the feature as
+a whole (that is, it originally looked very simple, but it is not looking so
+simple now), and (C) it might take more time than we have to resolve these
+issues. (Admittedly, (C) probably won't be the case, but fixing this AI could
+take time from more important things below it on the agenda [for example,
+Bignums].)
+
+Does anyone second reopening this AI?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, December 13, 2018  4:05 PM
+
+> > I don't think we want to allow this case, but that's just
+> my opinion.
+>
+> I am not sure.  This seems to be a fairly natural use of this feature.
+> I would be reluctant to start adding complicated restrictions in what
+> names can be mentioned in the expression without a good reason.
+
+Well, a natural implementation of this quantified expression puts Idx into a
+register temporary. External code, like this function here, would have no way to
+access such an Idx, as it would have no access to how the register temporary
+ends up getting mapped by the code generator (to a hardware register, to a spill
+location, or some combination).
+
+So the implementation would to recognize this special case and allocate a real
+memory location for it. (You would not want to do that in general, as you want
+the loop parameter to be stored in a register rather than memory if possible.
+Using a register temporary eliminates the need for the code generator to keep
+the memory location up-to-date.) Moreover, that location would be dead in the
+function body, since the memory location would be given the lifetime of the
+expression (and presumably reused elsewhere). So there would need to be some
+special mechanism to "re-animate" the memory location in the function body.
+
+I'm sure that some solution can be found, but it would be a significant
+complication to the implementation.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, December 13, 2018  4:15 PM
+
+> > I think that, roughly speaking, we'd like something along the lines of
+> >     first, find the nearest enclosing statement or declaration.
+> >     if it is a declaration, then the implicit subprogram declaration goes
+> >     immediately ahead of that declaration.
+> >     if it is a statement, then wrap an implicit block statement around
+> >     that statement and put the implicit declaration in the declarative
+> >     part of that block statement.
+>
+> I don't think we want something like that in the RM.  I find the
+> wording in the AI, or perhaps Tuckers wording, preferable.
+
+It might be preferable, but it makes it hard or impossible to answer questions
+about details of the function. If we have to answer those one-by-one as someone
+thinks of them, the entire thing gets tiresome (and we *still* end up with a
+bunch of wording).
+
+For instance, the contracts that apply to this function depend on where it is
+declared (since they can't be given explicitly -- and if someone proposes that
+we allow that, then this proposal has definitely jumped the shark). Consider:
+
+   package Pack
+      with Nonblocking => False is
+
+      function Foo (A : access function (B : Natural) return Natural) return Natural
+         with Nonblocking => True;
+
+      function Ugh (P : Natural := Foo ((function (A) return A*2), 2)) return Natural
+         with Nonblocking => True;
+
+   end Pack;
+
+Is this default expression legal? (This is roughly the structure of Text_IO,
+lest someone find it unlikely.)
+
+That depends on where the anonymous function is declared. If it outside of Ugh,
+then it has Nonblocking => False, and the 'Access is illegal (a potentially
+blocking subprogram can't be designed by a nonblocking access type for obvious
+reasons).
+
+I suppose we could adopt a special rule for this case, but then there is a
+similar case for Global. (At least, there better be, I haven't look carefully at
+the rules. But an access type that promises no access to globals have better not
+designate a subprogram that accesses globals.) So yet another rule would needed
+to deal with that. And are those the only such cases? Hard to know.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, December 13, 2018  4:48 PM
+
+> Does anyone second reopening this AI?
+
+I second the motion.
+
+Who is in charge of this AI?
+I'm willing to do a rewrite, if we can agree on "anonymous_function", and if
+whoever is in charge doesn't want to do it.
+
+Re: (B) above: I never thought this feature was simple in terms of
+implementation.  It's pretty simple conceptually, though.
+
+I note that the subject is:
+
+!subject Anonymous functions
+
+And it says:
+
+    We considered other names such as "lambda functions," "function
+    literals," and "anonymous functions."  We ultimately went with "function
+    expression" as it seemed analogous to "if expression" and "case
+    expression," though there is admittedly some discomfort in having both
+    "expression functions" and "function expressions."
+
+This is exactly the Ada-centric thinking that Tucker and I expressed dislike
+for:
+
+>> It seems worth picking one from their list ...rather than inventing
+>> yet another Ada-specific term.
+>
+> Good point.  I hate when languages get creative with their terms when
+> everybody else already has a perfectly good term.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, December 13, 2018  4:51 PM
+
+> ...
+> For instance, the contracts that apply to this function depend on
+> where it is declared (since they can't be given explicitly -- and if
+> someone proposes that we allow that, then this proposal has definitely jumped
+> the shark).
+
+The wording fix I proposed replaced "local" with "within the innermost
+declarative region." That seems to answer this question unambiguously.
+
+> Consider:
+>
+>   package Pack
+>      with Nonblocking => False is
+>
+>      function Foo (A : access function (B : Natural) return Natural) return Natural
+>         with Nonblocking => True;
+>
+>      function Ugh (P : Natural := Foo ((function (A) return A*2), 2)) return Natural
+>         with Nonblocking => True;
+>
+>   end Pack;
+>
+> Is this default expression legal? (This is roughly the structure of
+> Text_IO, lest someone find it unlikely.)
+>
+> That depends on where the anonymous function is declared. If it
+> outside of Ugh, then it has Nonblocking => False, and the 'Access is
+> illegal (a potentially blocking subprogram can't be designed by a
+> nonblocking access type for obvious reasons).
+
+The wording as amended proposes the innermost declarative region, which in this
+case is Ugh.  The TBH makes it clear that this innermost declarative region need
+not be something that normally would allow such declarations.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, December 13, 2018  4:52 PM
+
+> Who is in charge of this AI?
+> I'm willing to do a rewrite, if we can agree on "anonymous_function",
+> and if whoever is in charge doesn't want to do it.
+
+I am the author, and am happy to update it.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, December 13, 2018  5:05 PM
+
+...
+> >    (2) The rule about evaluating a function expression says that a
+> > function expression "... is equivalent to a local
+> > expression_function_declaration ...". But local where?
+>
+> It bothers me that if you instantiate a generic package in a package
+> spec, the instance body occurs in the package spec, even though that's
+> syntactically illegal.  But we've lived with that for decades.
+
+You mean that you've thought of a generic instantiation incorrectly for decades.
+;-) If you have a shared generic, clearly the body doesn't live there (only a
+call to elaborate it). That indeed was one of the reasons that we thought early
+on that Ada (83) was designed with the intent of generic sharing. (The others
+being the contract model and the inadvisability of compilation dependences --
+especially back then, in the days of 5 minute compilations per unit.)
+
+> This case doesn't bother me any more than that, so I can live with it.
+> Tucker's wording seems OK.
+
+That wasn't my point. My point was that the location of the declaration
+determines some of its properties (accessibility, contracts, probably more), so
+we need to know where it is. *Especially* in which compilation unit it exists.
+Ada goes to substantial lengths to say where operators and other implicit things
+are declared. It would be very unusual for this declaration to be essentially
+declared anywhere that you feel like it. (Probably the only such thing in Ada.)
+
+Note that the point of the declaration and the point of the body don't have to
+be the same. The point of the declaration has to be nailed down, IMHO. The
+location of the body could possibly be left up to the implementation.
+
+> >       [A] The first occurrence (the specification of Pack);
+>
+> Yes.
+>>       [B] Both occurrences (both the specification and body of Pack
+>> -- this would imply that they never conform).
+>
+>That would be unfortunate -- default values are a fairly natural place
+>to use this feature.
+...
+> >     The wording is mainly "Static Semantics", which would imply [B], ...
+
+[A] would be different than every other feature in a subprogram specification.
+Anonymous access types are different (and then there are matching rules);
+quantified expression (and soon declare expressions) objects are different (and
+then there are matching rules), and so on.
+
+Either you would have to come up with a newly invented semantics where the
+function *isn't* duplicated even though there are two distinct expressions, or
+we need an additional conformance rule to allow this case. Either way, we need
+an additional rule.
+
+> > but that of course would require doing some code generation for
+> > default expressions at the point of declaration [I know the
+> > Janus/Ada can't do that as currently designed]. And it also would
+> > prevent any conformance (since there'd be two separate functions
+> > declared by the two declarations, which could never be allowed).
+>
+> It seems to me you can generate code whereever/whenever you like,
+> regardless of what the RM says.
+
+Well, maybe your compiler can. I realize arguments from implementation
+difficulty are weak, but after a very valuable proposal (AI12-0205-1) got
+scuttled because of FUD from an implementer, please bear with me. :-)
+
+Janus/Ada is primarily a syntax-directed translator in the form of the (green,
+original) dragon book. That's in part because it started in a class where that
+organization was required. Regardless, it still remains primarily implemented
+with action routines tied to reductions of syntax productions. We had to move to
+trees for expression analysis, but almost everything else remains implemented
+syntactically, in particular all declarations, including subprograms, types,
+packages, etc.
+
+The Janus/Ada intermediate code was also designed around the needs of Ada
+(originally Ada 83), as well as the needs of optimization, interpretation, and
+code generation. It rarely allows things that aren't needed by Ada (in
+particular, it doesn't allow function calls that need to copy back parameters, a
+long-standing problem for interfacing and now "in out" parameters). Relevant to
+this case, it does not allow declarations unless they're at the outer level of
+the intermediate code (dubbed "prairie points" because there cannot be any trees
+- not my doing). So many "natural" points of code generation cannot declare a
+subprogram (or many other things). (And honestly, I can't see how that would
+work in anyone's intermediate form -- splitting an expression in half would make
+it hard/impossible to optimize.)
+
+For a long time, I tried to allow code generation at freezing points. But there
+always was another case where code was getting generated somewhere it couldn't
+be. I eventually gave up and delayed all of that until the end of the
+declarative part when everything is frozen anyway. (Since most of that code is
+thunk bodies, where they are generated is essentially irrelevant. But it does
+lead to a large gob of undifferentiated code at the foot of every package, which
+is hell to look at when something goes wrong.)
+
+Anyway, delaying the generation of something is not particularly hard, but
+generating or even declaring it early is impossible in Janus/Ada. There probably
+is some solution involving generating the declaration in one place and the body
+much later, but that will require an entirely new mechanism in the compiler and
+potentially extra tree passes as well (or general changes to some existing tree
+pass to deal with this unusual case). The implementation will be quite expensive
+- even if we don't have to deal with quantified expression loop parameters.
+
+Aside: Robert once complained that this organization is "very inflexible". He's
+right, but that was a huge advantage for us in the early days. Back when most of
+Janus/Ada was built, we were undisciplined straight-out-of-university
+know-it-alls (what person in their early 20s isn't that???). Had we had a blank
+page organization, hardly anything would have worked. Even now, the tree-based
+stuff is much harder to work on than the syntax-directed parts. (And the tree
+based stuff wasn't even built until we'd learned various lessons about
+organization the hard way.)
+
+****************************************************************
+
+From: Bob Duff
+Sent: Thursday, December 13, 2018  5:08 PM
+
+> I am the author, and am happy to update it.
+
+OK, thanks!
+
+Anybody object to "anonymous function"?
+Speak now or forever hold your peace.  ;-)
+
+Some AARM examples might help clarify things.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, December 13, 2018  5:08 PM
+
+...
+> > Does anyone second reopening this AI?
+>
+> I second the motion.
+>
+> Who is in charge of this AI?
+
+Tucker was the author.
+
+> I'm willing to do a rewrite, if we can agree on "anonymous_function",
+> and if whoever is in charge doesn't want to do it.
+
+Tucker has plenty else to do -- he took all of the homework from our last
+meeting.
+
+> Re: (B) above: I never thought this feature was simple in terms of
+> implementation.  It's pretty simple conceptually, though.
+>
+> I note that the subject is:
+>
+> !subject Anonymous functions
+>
+> And it says:
+>
+>     We considered other names such as "lambda functions," "function
+>     literals," and "anonymous functions."  We ultimately went with "function
+>     expression" as it seemed analogous to "if expression" and "case
+>     expression," though there is admittedly some discomfort in having both
+>     "expression functions" and "function expressions."
+>
+> This is exactly the Ada-centric thinking that Tucker and I expressed
+> dislike for:
+>
+> >> It seems worth picking one from their list ...rather than inventing
+> >> yet another Ada-specific term.
+> >
+> > Good point.  I hate when languages get creative with their terms
+> > when everybody else already has a perfectly good term.
+
+This must have been Tucker version 2. Tucker version 1 was the author of the
+AI and clearly of the paragraph you read above. I'm soooo confused. :-)
+
+****************************************************************
+
+From: Gary Dismukes
+Sent: Thursday, December 13, 2018  5:11 PM
+
+> The term "anonymous" is already used in several contexts in Ada, so using it
+> for these sorts of functions seems pretty appropriate and consistent.  I
+> like "lambda expression" except for the fact it introduces the term "lambda"
+> into the language and a chapter called "Lambda Expressions" would be pretty
+> mysterious to programmers who have not taken that "Comparative Programming
+> Languages" course (alas, I suspect that is many "programmers" these days).
+> It would be easy for any Ada user to guess what is going on in a chapter
+> called "Anonymous Functions."
+
+Strongly agreed.  I much prefer "anonymous functions" over "lambda expressions".
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, December 13, 2018  5:32 PM
+
+...
+>>And it says:
+>>
+>>   We considered other names such as "lambda functions," "function
+>>   literals," and "anonymous functions."  We ultimately went with "function
+>>   expression" as it seemed analogous to "if expression" and "case
+>>   expression," though there is admittedly some discomfort in having both
+>>   "expression functions" and "function expressions."
+
+>> This is exactly the Ada-centric thinking that Tucker and I
+>> expressed dislike for:
+
+Guilty as charged.
+
+>>>It seems worth picking one from their list ...rather than inventing
+>>>yet another Ada-specific term.
+>>
+>>Good point.  I hate when languages get creative with their terms when
+>>everybody else already has a perfectly good term.
+>
+>This must have been Tucker version 2. Tucker version 1 was the author of the
+>AI and clearly of the paragraph you read above. I'm soooo confused. :-)
+
+Makes me remember fondly good old Norm Cohen prime and double-prime ... ;-)
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, December 13, 2018  5:47 PM
+
+> > ...
+> > For instance, the contracts that apply to this function depend on
+> > where it is declared (since they can't be given explicitly -- and if
+> > someone proposes that we allow that, then this proposal has
+> > definitely jumped the shark).
+>
+> The wording fix I proposed replaced "local" with "within the innermost
+> declarative region." That seems to answer this question unambiguously.
+
+Sorry, I didn't see that proposal. I only saw a proposed Legality Rule to
+disallow these matching named access types (which only fixes a small corner of
+the proposal).
+
+...
+> The wording as amended proposes the innermost declarative region,
+> which in this case is Ugh.  The TBH makes it clear that this innermost
+> declarative region need not be something that normally would allow
+> such declarations.
+
+Ugh! :-) That means that invariants throughout the compiler will fail seemingly
+at random when compiling these things. Another substantial implementation
+expense.
+
+Mildly related: I recently spent more than a day fixing several dozen invariant
+failures caused by allowing anonymous access-to-subprogram types in parameters.
+Originally, those were rejected as soon as they appeared syntactically as being
+unimplemented ("feature not implemented", or FNI). But that caused them to be
+replaced by "Integer" (the default correction for bad types) and that caused a
+lot of error cascades. I thought that if I declared the type and then FNIed any
+uses there would be fewer cascades. I also thought that would be easy (famous
+last words).
+
+However, declaring the type required a TYP node (it would have been called
+"TYPE" but declaring an enumeration literal with that name doesn't work for some
+reason :-) in the symboltable in order to be an anchor for the parameter list of
+the anonymous access-to-subprogram (otherwise, the parameter lists would have
+gotten co-mingled, and that clearly wouldn't have worked). And it turned out
+that pretty much every piece of code that walked a parameter list (and there
+were many) had been written to our style guide and looked something like:
+   while Param_Ptr /= null loop
+      case Param_Ptr.Selector is
+         when PARAM => ... -- Do whatever good things.
+         when others =>
+              Internal_Error ("Not a parameter in a parameter list!");
+      end case;
+      Param_Ptr := Param_Ptr.Next;
+   end loop;
+
+I had to add
+    when TYP => -- Probably an anonymous-access-to-subprogram parameter is next.
+        null; -- Skip this.
+to every one of those loops (and I've probably missed some until I compile the
+right example).
+
+This sounds like that problem all over again.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, December 13, 2018  5:47 PM
+
+Here is an update incorporating some of these discussions. [This is version /06
+of the AI - Editor.]
+
+****************************************************************
+
+
+From: Brad Moore
+Sent: Thursday, December 13, 2018  11:32 PM
+
+****************************************************************
+
+
+From: Brad Moore
+Sent: Thursday, December 13, 2018  11:32 PM
+
+****************************************************************
+
+
+From: Brad Moore
+Sent: Thursday, December 13, 2018  11:32 PM
+
+****************************************************************
+
+
+From: Brad Moore
+Sent: Thursday, December 13, 2018  11:32 PM
+
+****************************************************************
+
+
+From: Brad Moore
+Sent: Thursday, December 13, 2018  11:32 PM
+
+****************************************************************
+
+
+From: Brad Moore
+Sent: Thursday, December 13, 2018  11:32 PM
+
+****************************************************************
+
+
+From: Brad Moore
+Sent: Thursday, December 13, 2018  11:32 PM
+
+****************************************************************
+
+
+From: Brad Moore
+Sent: Thursday, December 13, 2018  11:32 PM
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent