allow handling allocation failures in the builtins append() and
insert() using the new builtin type "nomem". alloc() is also changed
to return a tagged union with this type, and no longer allows
handling allocation failures using nullable pointer types.
i also moved the sentence that explains how the length is set to
the more relevant places in both insert and append. for the spec
and also the programmer, it is not important that the length is set
before calling rt::ensure. this makes it more readable imo.
finally, while here, i did some re-phrasing of some rather confusing
sentences (at least for a non-native speaker). namely, i've changed
the order in sentences that describe how type hints are provided,
to also match the rest of the spec.
Signed-off-by: Lorenz (xha) <me@xha.li>
---
the harec and stdlib patches will follow soon, but as always, i
would appreciate some help with this patch because natrual language
stuff is not my strength, thanks :)
language/expressions.tex | 161 +++++++++++++++++++++------------------language/keywords.tex | 1 +language/types.tex | 14 ++++
3 files changed, 101 insertions(+), 75 deletions(-)
diff --git a/language/expressions.tex b/language/expressions.tex
index 5dc410b..cdc0462 100644
--- a/language/expressions.tex+++ b/language/expressions.tex
@@ -29,6 +29,7 @@ refine their behavior.
\nonterminal{tuple-literal} \\
\terminal{true} \\
\terminal{false} \\
+ \terminal{nomem} \\ \terminal{null} \\
\terminal{void} \\
\terminal{done} \\
@@ -43,9 +44,9 @@ The keywords \terminal{true} and \terminal{false} respectively represent
the values of the \terminal{bool} type.
\specsubsubitem
-The \terminal{null}, \terminal{void}, \terminal{done} keywords represent the-value of the \terminal{null}, \terminal{void}, \terminal{done} types-respectively.+The \terminal{nomem}, \terminal{null}, \terminal{void}, \terminal{done} keywords+represent the value of the \terminal{nomem}, \terminal{null}, \terminal{void},+\terminal{done} types respectively.\specsubsection{Floating literals}
@@ -510,36 +511,38 @@ programmer to overcome undesirable associativity between operators.
\specsubsubitem
An \terminal{alloc} expression allocates an object at runtime and initializes
its value to the first \nonterminal{expression} (the \textit{initializer}). The
-result type of the \textit{initializer} provides the allocation's-\textit{object type}.--\specsubsubitem-The first form is the object allocation form. In this form, if a pointer type is-provided as a type hint, the secondary type of this pointer type shall be-provided to the initializer as its type hint. If a slice type is provided as a-type hint, the slice type shall be provided to the initializer as its type hint.-The execution environment will allocate sufficient storage for the object type-and initialize its value using the initializer expression, then set its result-to a pointer to the new object. The object type must have a defined size which-is greater than zero.--\specsubsubitem-The second form is the copy allocation form. In this form, if a slice type is-provided as a type hint, the slice type shall be provided to the initializer as-its type hint. The initializer will provide an object type which is either a-slice or array type (or an alias thereof). The execution environment will-allocate storage sufficient to store an array equal in length to the-initializer, then copy the initializer's slice or array items into this array.-The result value shall be set to a slice object whose secondary type is equal to-the secondary type of the initializer's result type, whose data field refers to-the new array, and whose length and capacity fields are set to the length of the-array.--\specsubsubitem-The third form is the slice allocation form. In this form, if a slice type is-provided as a type hint, the slice type shall be provided to the initializer as-its type hint. The initializer will provide an object type which is either a-slice or array type (or an alias thereof), and the second+result type of the initializer provides the allocation's \textit{object type}.+The result of an \nonterminal{allocation-expression} is a tagged union whose+member types are the \textit{allocation result} type and \terminal{nomem}.++\specsubsubitem+If the type hint is provided, and is a tagged union, that has two member types,+one being the \terminal{nomem} type, the other type shall be provided to the+initializer as a type hint. Alternatively, if the type hint is a slice or+pointer type, it shall also be provided to the initializer as a type hint. If+the type hint is a pointer type, the secondary type of this pointer type shall+be provided as a type hint instead.++\specsubsubitem+The first form is the \textit{object allocation form}. The execution environment+will allocate sufficient storage for the object type and initialize its value+using the initializer expression, then set the allocation result to a pointer to+the new object. The object type must have a defined size which is greater than+zero.++\specsubsubitem+The second form is the \textit{copy allocation form}. The initializer shall+provide an object type which is either a slice or array type. The execution+environment will allocate storage sufficient to store an array equal in length+to the initializer, then copy the initializer's slice or array items into this+array. The allocation result shall be a slice object whose secondary type is+equal to the secondary type of the initializer's result type, whose data field+refers to the new array, and whose length and capacity fields are set to the+length of the array.++\specsubsubitem+The third form is the \textit{slice allocation form}. The initializer shall+provide an object type which is either a slice or array type, and the second\nonterminal{expression} shall be assignable to the \terminal{size} type, which
shall be provided to it as a type hint.
@@ -550,30 +553,27 @@ array type, the second \nonterminal{expression} provides the desired
capacity equal to or greater than this term, then provision an array of that
length and set each $N$th value to the $N$th value of the initializer, for each
value of $N$ between $0$ (inclusive) and the length of the initializer
-(exclusive). The result of the \nonterminal{allocation-expression} shall be a-slice whose data field refers to this array, whose length is equal to the length-of the initializer, and whose capacity is set to the selected capacity.+(exclusive). The allocation result shall be a slice whose data field refers to+this array, whose length is equal to the length of the initializer, and whose+capacity is set to the selected capacity.\specsubsubitem
In the slice allocation form, if the array specified by the initializer is
expandable, the second expression shall provide the \textit{length} of the
slice. The execution environment shall choose a capacity equal to or greater
than this value, then for each $N$th value of the allocated array from the
-length of the initializer ($L$, inclusive) to the specified \textit{length}+length of the initializer ($L$, inclusive) to the specified length($L'$) shall be initialized to the value at $L-1$ in the initializer. The length
-field of the resulting slice value shall be set to the $L'$.+field of the resulting slice value shall be set to $L'$.\informative{The following allocates a slice of length 10 with all values set to zero:}
-\code{let x: []int = alloc([0...], 10)}+\code{let x: []int = alloc([0...], 10)!}\specsubsubitem
-When \terminal{alloc} is used, if the execution environment is unable to-allocate sufficient storage for the requested type, the execution environment-shall print a diagnostic message and abort. If the type hint is a nullable-pointer type, the result type of the allocation expression shall also be-nullable, and \terminal{null} shall be returned instead of aborting if-sufficient storage cannot be provided.+When \terminal{alloc} is used and the execution environment is unable to+allocate sufficient storage for the requested type, the \terminal{nomem} type+shall be returned.\specsubsubitem
A \terminal{free} expression shall discard previously allocated resources,
@@ -945,10 +945,11 @@ An \nonterminal{append-expression} shall append some number of values to the
slice object specified by the first term, which shall not be provided a type
hint. Valid result types for \nonterminal{object-selector} shall either be a
slice type whose secondary type has a definite size, or a non-nullable pointer
-to a valid result type. The selected object shall be mutable and non-const. The-member type of this slice shall be the \nonterminal{append-expression}'s+to a valid result type. The selected object shall be mutable and non-const. The+secondary type of this slice shall be the \nonterminal{append-expression}'s\textit{member type}. The result type of an \nonterminal{append-expression}
-shall be \terminal{void}.+shall be a tagged union with \terminal{nomem} and \terminal{void} types as its+member types.\specsubsubitem
In the first form, the type of the second term shall be assignable to the member
@@ -958,22 +959,22 @@ type, which shall be provided to it as a type hint.
In the second form, the type of the second term shall be a non-expandable
bounded array, a pointer to a non-expandable bounded array, or a slice. In all
cases, the secondary type of the array or slice type shall be the
-\nonterminal{append-expression}'s member type. The second term shall be provided-the object type as a type hint.+\nonterminal{append-expression}'s member type. The object type shall be provided+to the second term as a type hint.\specsubsubitem
-In the third form, the second term shall be an expandable array whose member+In the third form, the second term shall be an expandable array whose secondarytype is the \nonterminal{append-expression}'s member type, and the third term
-shall be assignable to \terminal{size}. The second term shall be provided the-object type as a type hint, and the third term shall be provided \terminal{size}-as a type hint. The length of the expandable array shall be given by the third-term.+shall be assignable to \terminal{size}. The object type shall be provided to+the second term as a type hint, and the third term shall be provided+\terminal{size} as a type hint. The length of the expandable array shall be+given by the third term.\specsubsubitem
The second term of an \terminal{append} expression is used to obtain the
\textit{append values}, of which there may be none. In the first form, the
value of the second term shall be used as the sole append value. In the second
-and third forms, the data of the array or slice given in the second term shall+and third forms, the values of the array or slice given in the second term shallbe used as the append values.
\specsubsubitem
@@ -988,20 +989,24 @@ obtained, the append values shall not change as a result of any side-effects.
After the append values are obtained, the execution environment shall ensure
that the capacity of the object is at least $N \geq L_1 + L_2$, where $L_1$ is
the object length and $L_2$ is the number of append values, reallocating the
-underlying storage if necessary. If sufficient storage cannot be allocated, the-execution environment shall print a diagnostic message and abort. The-\code{length} field of the slice object shall be set to $L_1 + L_2$.+underlying storage if necessary. If sufficient storage cannot be allocated, the+\terminal{nomem} type shall be returned and the object shall not be modified.\specsubsubitem
After ensuring sufficient space is available for the new items, the execution
environment shall assign values of the slice object from index $N = L_1$
(inclusive) to $N = L_1 + L_2$ (exclusive) from each consecutive append value.
+The \code{length} field of the slice object shall be set to $L_1 + L_2$.\specsubsubitem
The \terminal{static} forms shall be equivalent to the non-static forms except
that they shall never cause the underlying slice to be reallocated. If the
operation would require more space than the capacity of the slice provides, the
-execution environment shall print a diagnostic message and abort.+\terminal{nomem} type shall be returned and the slice shall not be modified.++\specsubsubitem+After successfully appending the values to the slice object, the+\nonterminal{void} type shall be returned.\specsubsection{Inserting}
@@ -1024,7 +1029,8 @@ an index at which the new values shall be inserted (the \textit{insertion
index}). The selected object shall be mutable and non-const, and shall not have
an array type. The secondary type of this slice shall be the expression's
\textit{member type}. The member type shall have a definite size. The result
-type of an \nonterminal{insert-expression} shall be \terminal{void}.+type of an \nonterminal{insert-expression} shall be a tagged union with+\terminal{nomem} and \terminal{void} types as its member types.\specsubsubitem
The bounds test described in \subsecref{Indexing} shall be performed on the
@@ -1038,14 +1044,14 @@ type, which shall be provided to it as a type hint.
In the second form, the type of the second term shall be a non-expandable
bounded array, a pointer to a non-expandable bounded array, or a slice. In all
cases, the secondary type of the array or slice type shall be the
-\nonterminal{insert-expression}'s member type. The second term shall be provided-the object type as a type hint.+\nonterminal{insert-expression}'s member type. The object type shall be provided+to the second term as a type hint.\specsubsubitem
-In the third form, the second term shall be an expandable array whose member+In the third form, the second term shall be an expandable array whose secondarytype is the \nonterminal{insert-expression}'s member type, and the third term
-shall be assignable to \terminal{size}. The second term shall be provided the-object type as a type hint, and the third term shall be provided \terminal{size}+shall be assignable to \terminal{size}. The object type shall be provided to the+second term as a type hint, and the third term shall be provided \terminal{size}as a type hint. The length of the expandable array shall be given by the third
term.
@@ -1053,7 +1059,7 @@ term.
The second term of an \nonterminal{insert-expression} is used to obtain the
\textit{insert values}, of which there may be none. In the first form, the
value of the second term shall be used as the sole insert value. In the second
-and third forms, the data of the array or slice given in the second term shall+and third forms, the values of the array or slice given in the second term shallbe used as the insert values.
\specsubsubitem
@@ -1069,14 +1075,14 @@ After the insert values are obtained, the execution environment shall ensure
that the capacity of the object is at least $N \geq L_1 + L_2$, where $L_1$ is
the object length and $L_2$ is the number of insert values, reallocating the
underlying storage if necessary. If sufficient storage cannot be allocated, the
-execution environment shall print a diagnostic message and abort. The-\code{length} field of the slice object shall be set to $L_1 + L_2$.+\terminal{nomem} type shall be returned and the object shall not be modified.\specsubsubitem
After ensuring sufficient space is available for the new items, the execution
-environment shall copy or move each item $N$ such that from $N=I$ (inclusive)-to $N=I+L_2$ (exclusive), where $I$ is the insertion index, each item is placed-at $N+L_2$.+environment shall copy or move each item $N$ such that from $N=I$ (inclusive) to+$N=I+L_2$ (exclusive), where $I$ is the insertion index, each item is placed at+$N+L_2$. The \code{length} field of the slice object shall be set to+$L_1 + L_2$.\specsubsubitem
The execution environment shall then assign values of the object slice from
@@ -1087,7 +1093,11 @@ insert value.
The \terminal{static} forms shall be equivalent to the non-static forms except
that they shall never cause the underlying slice to be reallocated. If the
operation would require more space than the capacity of the slice provides, the
-execution environment shall print a diagnostic message and abort.+\terminal{nomem} type shall be returned and the slice shall not be modified.++\specsubsubitem+After successfully inserting the values into the slice object, the+\nonterminal{void} type shall be returned.\specsubsection{Deleting}
@@ -1182,6 +1192,7 @@ shall be provided to its \nonterminal{postfix-expression}.
\nonterminal{indexing-expression} \\
\nonterminal{slicing-expression} \\
\nonterminal{error-checking-expression} \\
+ \nonterminal{builtin-expression} \\\nonterminaldef{object-selector} \\
\nonterminal{identifier} \\
@@ -1273,7 +1284,6 @@ expression is \terminal{void}.
\nonterminal{assertion-expression} \\
\nonterminal{measurement-expression} \\
\nonterminal{slice-mutation-expression} \\
- \nonterminal{postfix-expression} \\ \nonterminal{static-assertion-expression} \\
\nonterminal{variadic-expression} \\
\end{grammar}
@@ -1282,7 +1292,7 @@ expression is \terminal{void}.
\begin{grammar}
\nonterminaldef{unary-expression} \\
- \nonterminal{builtin-expression} \\+ \nonterminal{postfix-expression} \\ \nonterminal{compound-expression} \\
\nonterminal{match-expression} \\
\nonterminal{switch-expression} \\
@@ -2700,6 +2710,7 @@ The following expressions are included:
\item \nonterminal{measurement-expression}
\item \nonterminal{nested-expression}
\item \nonterminal{plain-expression}
+\item \nonterminal{builtin-expression}\end{itemize}
\end{multicols}
\end{minipage}
diff --git a/language/keywords.tex b/language/keywords.tex
index c44ff82..e2d746a 100644
--- a/language/keywords.tex+++ b/language/keywords.tex
@@ -38,6 +38,7 @@
\terminal{let}
\terminal{match}
\terminal{never}
+\terminal{nomem}\terminal{null}
\terminal{nullable}
\terminal{offset}
diff --git a/language/types.tex b/language/types.tex
index 5d32329..9f2a2cb 100644
--- a/language/types.tex+++ b/language/types.tex
@@ -22,6 +22,7 @@
\terminal{bool} \\
\terminal{done} \\
\terminal{never} \\
+ \terminal{nomem} \\ \terminal{opaque} \\
\terminal{rune} \\
\terminal{str} \\
@@ -306,6 +307,19 @@ behavior is undefined.
as incorrect external function implementations and invalid function pointer
casts can cause this to occur.}
+\textbf{The nomem type}++\specsubsubitem+The \terminal{nomem} type represents an object that indicates a failure to+allocate storage. Only one value with this type exists (the \textit{nomem}+value); this value is also the default value.++\specsubsubitem+The size and alignment of \terminal{nomem} shall be zero.++\specsubsubitem+The \terminal{nomem} type shall always have its error flag set.+\textbf{The null type}
\informative{The null type is not representable within the grammar. It is for
--
2.46.0
The new behavior of type hints in error checking expressions also needs
to be specified.
On Sun Sep 1, 2024 at 1:33 AM EDT, Lorenz (xha) wrote:
> \specsubsubitem> -The \terminal{null}, \terminal{void}, \terminal{done} keywords represent the> -value of the \terminal{null}, \terminal{void}, \terminal{done} types> -respectively.> +The \terminal{nomem}, \terminal{null}, \terminal{void}, \terminal{done} keywords> +represent the value of the \terminal{nomem}, \terminal{null}, \terminal{void},> +\terminal{done} types respectively.
Looks like this was already an issue previously, but there should be an
"and" before both "\terminal{done}"s.
> -\specsubsubitem> -The third form is the slice allocation form. In this form, if a slice type is> -provided as a type hint, the slice type shall be provided to the initializer as> -its type hint. The initializer will provide an object type which is either a> -slice or array type (or an alias thereof), and the second> +result type of the initializer provides the allocation's \textit{object type}.> +The result of an \nonterminal{allocation-expression} is a tagged union whose
*result type
> +member types are the \textit{allocation result} type and \terminal{nomem}.
"allocation result" should be changed to "allocation type" everywhere
it's used. You could also go with "allocation result type", but I think
"allocation type" is better.
Also, allocation-expression includes free expressions, which return
void, so what you have isn't correct. It might make sense to split this
into two sections (alloc and free), similarly to how append, insert, and
delete are separate. This makes sense since append and insert also
allocate, but yet aren't considered an allocation-expression.
> +\specsubsubitem> +If the type hint is provided, and is a tagged union, that has two member types,> +one being the \terminal{nomem} type, the other type shall be provided to the> +initializer as a type hint. Alternatively, if the type hint is a slice or> +pointer type, it shall also be provided to the initializer as a type hint. If> +the type hint is a pointer type, the secondary type of this pointer type shall> +be provided as a type hint instead.
In moving the type hint stuff to one location, you've changed its
behavior: now, a pointer type hint can be used with the copy and slice
allocation forms as well. harec doesn't currently behave like this; does
your nomem patch change this? It may be for the best to change it; take
for example:
alloc([1, 2, 3]...)!: *[*]u8
This currently doesn't compile, but if harec were changed to reflect the
changes in this patch, then it would compile (and behave as expected). I
think that's reasonable, but I'll leave it up to you.
Tangentially, harec currently errors out if the type hint in the copy
allocation form isn't a slice type (that's the reason the example above
refuses to compile rather than silently behaving incorrectly). This
isn't the case with any other allocation form, and it isn't specified,
neither with nor without this patch. I think the best course of action
(for now) is to remove this behavior from harec, especially since it's
not even currently implemented correctly (tagged union type hints are
allowed, even if the tagged union doesn't have any slice members). git
blame on this points back to me lol, whoops
Besides that, this is confusingly worded, since the last sentence in the
paragraph contradicts what was previously said. I think a better
approach is to say that a type hint of (T | nomem) behaves exactly like
a type hint of T, and then have separate semantics for pointer and slice
type hints. This slightly changes the behavior from what you have
written, which says that the member which isn't nomem is *always*
provided as a type hint to the initializer, even if it isn't a pointer
or slice type, but I think limiting this to pointer and slice types
makes sense?
I would go with something like this:
"If the \nonterminal{allocation-expression} is provided a type hint
which is a tagged union type with exactly two member types, one of which
being \terminal{nomem}, the behavior shall be exactly as though the
provided type hint were the member type which isn't \terminal{nomem}.
Otherwise, if the \nonterminal{allocation-expression} is provided a type
hint which is a pointer type, the pointer type's secondary type shall be
provided to the initializer as a type hint. Otherwise, if the
\nonterminal{allocation-expression} is provided a type hint which is a
slice type, the slice type shall be provided to the initializer as a
type hint."
This still doesn't account for type aliases, but that's a bigger problem
which shows up pretty much everywhere in the spec, so for now this is
fine. The wording is verbose (every sentence says "if the
\nonterminal{allocation-expression} is provided a type hint", because
otherwise it could be misinterpreted. In the last two sentences, if I
didn't specify what the type hint applies to, they could be interpreted
as applying to the initializer, which isn't right.
Actually, speaking of type aliases, what does your harec patch do if
alloc is provided a type hint which is an alias of (T | nomem)? If it's
always dealiased, then when we go through the spec to better specify
aliases, we'll need to make sure to not miss this part: consider
`alloc(x): (T | nomem)`, where T is an alias of `(int | nomem)`. Is the
initializer provided a type hint of `int`, `(int | nomem)`, or `T`?
> \specsubsubitem> -When \terminal{alloc} is used, if the execution environment is unable to> -allocate sufficient storage for the requested type, the execution environment> -shall print a diagnostic message and abort. If the type hint is a nullable> -pointer type, the result type of the allocation expression shall also be> -nullable, and \terminal{null} shall be returned instead of aborting if> -sufficient storage cannot be provided.> +When \terminal{alloc} is used and the execution environment is unable to> +allocate sufficient storage for the requested type, the \terminal{nomem} type> +shall be returned.
Replace "the \terminal{nomem} type shall be returned" with "the
expression's result value shall be \terminal{nomem}." Ditto with append
and insert.
> -to a valid result type. The selected object shall be mutable and non-const. The> -member type of this slice shall be the \nonterminal{append-expression}'s> +to a valid result type. The selected object shall be mutable and non-const. The> +secondary type of this slice shall be the \nonterminal{append-expression}'s
You accidentally added a space :)
> \textit{member type}. The result type of an \nonterminal{append-expression}> -shall be \terminal{void}.> +shall be a tagged union with \terminal{nomem} and \terminal{void} types as its> +member types.
This can just say the result type is "\code{(void | nomem)}".
> \specsubsubitem> -In the third form, the second term shall be an expandable array whose member> +In the third form, the second term shall be an expandable array whose secondary> type is the \nonterminal{append-expression}'s member type, and the third term> -shall be assignable to \terminal{size}. The second term shall be provided the> -object type as a type hint, and the third term shall be provided \terminal{size}> -as a type hint. The length of the expandable array shall be given by the third> -term.> +shall be assignable to \terminal{size}. The object type shall be provided to> +the second term as a type hint, and the third term shall be provided> +\terminal{size} as a type hint. The length of the expandable array shall be> +given by the third term.
If you're gonna make these changes, then "the third term shall be
provided \terminal{size} as a type hint" should also be changed to
"\terminal{size} shall be provided to the third term as a type hint" for
consistency.
> \specsubsubitem> The second term of an \terminal{append} expression is used to obtain the> \textit{append values}, of which there may be none. In the first form, the> value of the second term shall be used as the sole append value. In the second> -and third forms, the data of the array or slice given in the second term shall> +and third forms, the values of the array or slice given in the second term shall> be used as the append values.
NACK, "data" is fine here
> \specsubsubitem> @@ -988,20 +989,24 @@ obtained, the append values shall not change as a result of any side-effects.> After the append values are obtained, the execution environment shall ensure> that the capacity of the object is at least $N \geq L_1 + L_2$, where $L_1$ is> the object length and $L_2$ is the number of append values, reallocating the> -underlying storage if necessary. If sufficient storage cannot be allocated, the> -execution environment shall print a diagnostic message and abort. The> -\code{length} field of the slice object shall be set to $L_1 + L_2$.> +underlying storage if necessary. If sufficient storage cannot be allocated, the> +\terminal{nomem} type shall be returned and the object shall not be modified.
Another accidental space
> \specsubsection{Inserting}
Same stuff with append also applies to insert
> @@ -1182,6 +1192,7 @@ shall be provided to its \nonterminal{postfix-expression}.> \nonterminal{indexing-expression} \\> \nonterminal{slicing-expression} \\> \nonterminal{error-checking-expression} \\> + \nonterminal{builtin-expression} \\> > \nonterminaldef{object-selector} \\> \nonterminal{identifier} \\> @@ -1273,7 +1284,6 @@ expression is \terminal{void}.> \nonterminal{assertion-expression} \\> \nonterminal{measurement-expression} \\> \nonterminal{slice-mutation-expression} \\> - \nonterminal{postfix-expression} \\> \nonterminal{static-assertion-expression} \\> \nonterminal{variadic-expression} \\> \end{grammar}> @@ -1282,7 +1292,7 @@ expression is \terminal{void}.> > \begin{grammar}> \nonterminaldef{unary-expression} \\> - \nonterminal{builtin-expression} \\> + \nonterminal{postfix-expression} \\> \nonterminal{compound-expression} \\> \nonterminal{match-expression} \\> \nonterminal{switch-expression} \\
NACK, unless you have a justification for this change which I'm missing.
> @@ -2700,6 +2710,7 @@ The following expressions are included:> \item \nonterminal{measurement-expression}> \item \nonterminal{nested-expression}> \item \nonterminal{plain-expression}> +\item \nonterminal{builtin-expression}> \end{itemize}> \end{multicols}> \end{minipage}
This isn't right. Most builtin expressions aren't translation
compatible, and the ones which are are already listed, so adding
builtin-expression is both redundant and incorrect.
Is there some expression missing from this list?
thanks for the review. some comments inline
On Sun, Sep 01, 2024 at 10:31:07PM -0400, Sebastian wrote:
> The new behavior of type hints in error checking expressions also needs> to be specified.
i actually did not change anything with regards to error checking
expressions, i.e. type hints? it still just passes type hint as-is
to the "inside expression".
> > +member types are the \textit{allocation result} type and \terminal{nomem}.> > "allocation result" should be changed to "allocation type" everywhere> it's used. You could also go with "allocation result type", but I think> "allocation type" is better.
i agree, that's better.
> Also, allocation-expression includes free expressions, which return> void, so what you have isn't correct. It might make sense to split this> into two sections (alloc and free), similarly to how append, insert, and> delete are separate. This makes sense since append and insert also> allocate, but yet aren't considered an allocation-expression.
i've seperated free into its own class, free-expression.
> > +\specsubsubitem> > +If the type hint is provided, and is a tagged union, that has two member types,> > +one being the \terminal{nomem} type, the other type shall be provided to the> > +initializer as a type hint. Alternatively, if the type hint is a slice or> > +pointer type, it shall also be provided to the initializer as a type hint. If> > +the type hint is a pointer type, the secondary type of this pointer type shall> > +be provided as a type hint instead.> > In moving the type hint stuff to one location, you've changed its> behavior: now, a pointer type hint can be used with the copy and slice> allocation forms as well. harec doesn't currently behave like this; does> your nomem patch change this? It may be for the best to change it; take> for example:> > alloc([1, 2, 3]...)!: *[*]u8> > This currently doesn't compile, but if harec were changed to reflect the> changes in this patch, then it would compile (and behave as expected). I> think that's reasonable, but I'll leave it up to you.> > Tangentially, harec currently errors out if the type hint in the copy> allocation form isn't a slice type (that's the reason the example above> refuses to compile rather than silently behaving incorrectly). This> isn't the case with any other allocation form, and it isn't specified,> neither with nor without this patch. I think the best course of action> (for now) is to remove this behavior from harec, especially since it's> not even currently implemented correctly (tagged union type hints are> allowed, even if the tagged union doesn't have any slice members). git> blame on this points back to me lol, whoops
yeah, i've changed this behavior, for the same reasons that you've
mentioned. it's in the other forms aswell, and well, we have to find a
better solution anyways.
> Besides that, this is confusingly worded, since the last sentence in the> paragraph contradicts what was previously said. I think a better> approach is to say that a type hint of (T | nomem) behaves exactly like> a type hint of T, and then have separate semantics for pointer and slice> type hints. This slightly changes the behavior from what you have> written, which says that the member which isn't nomem is *always*> provided as a type hint to the initializer, even if it isn't a pointer> or slice type, but I think limiting this to pointer and slice types> makes sense?> > I would go with something like this:> > "If the \nonterminal{allocation-expression} is provided a type hint> which is a tagged union type with exactly two member types, one of which> being \terminal{nomem}, the behavior shall be exactly as though the> provided type hint were the member type which isn't \terminal{nomem}.> Otherwise, if the \nonterminal{allocation-expression} is provided a type> hint which is a pointer type, the pointer type's secondary type shall be> provided to the initializer as a type hint. Otherwise, if the> \nonterminal{allocation-expression} is provided a type hint which is a> slice type, the slice type shall be provided to the initializer as a> type hint."
sounds good. i've changed it.
> Actually, speaking of type aliases, what does your harec patch do if> alloc is provided a type hint which is an alias of (T | nomem)? If it's> always dealiased, then when we go through the spec to better specify> aliases, we'll need to make sure to not miss this part: consider> `alloc(x): (T | nomem)`, where T is an alias of `(int | nomem)`. Is the> initializer provided a type hint of `int`, `(int | nomem)`, or `T`?
i suppose you mean that T is an alias to int? in this case, the
initializer is not provided a type hint at all, because it is
invalid: it dealiases T and figures out that it is not a pointer
or slice.
in the case that T is an alias to *int, the intialializer would be
provided int as a type hint.
> > @@ -1182,6 +1192,7 @@ shall be provided to its \nonterminal{postfix-expression}.> > \nonterminal{indexing-expression} \\> > \nonterminal{slicing-expression} \\> > \nonterminal{error-checking-expression} \\> > + \nonterminal{builtin-expression} \\> > > > \nonterminaldef{object-selector} \\> > \nonterminal{identifier} \\> > @@ -1273,7 +1284,6 @@ expression is \terminal{void}.> > \nonterminal{assertion-expression} \\> > \nonterminal{measurement-expression} \\> > \nonterminal{slice-mutation-expression} \\> > - \nonterminal{postfix-expression} \\> > \nonterminal{static-assertion-expression} \\> > \nonterminal{variadic-expression} \\> > \end{grammar}> > @@ -1282,7 +1292,7 @@ expression is \terminal{void}.> > > > \begin{grammar}> > \nonterminaldef{unary-expression} \\> > - \nonterminal{builtin-expression} \\> > + \nonterminal{postfix-expression} \\> > \nonterminal{compound-expression} \\> > \nonterminal{match-expression} \\> > \nonterminal{switch-expression} \\> > NACK, unless you have a justification for this change which I'm missing.
yeah, otherwise it is not possible to use a postfix-expression such as ? or !
with the builtins. so the builtins have to be contained in the
postfix-expression class.
> > @@ -2700,6 +2710,7 @@ The following expressions are included:> > \item \nonterminal{measurement-expression}> > \item \nonterminal{nested-expression}> > \item \nonterminal{plain-expression}> > +\item \nonterminal{builtin-expression}> > \end{itemize}> > \end{multicols}> > \end{minipage}> > This isn't right. Most builtin expressions aren't translation> compatible, and the ones which are are already listed, so adding> builtin-expression is both redundant and incorrect.> > Is there some expression missing from this list?
nah, that was just a mistake, thanks for catching it. i was struggling
a bit to understand the way that these expressions are contained in
one and another, and that is how i temporarily wanted to solve this.
On Fri Sep 6, 2024 at 11:49 PM EDT, Lorenz (xha) wrote:
> On Sun, Sep 01, 2024 at 10:31:07PM -0400, Sebastian wrote:> > The new behavior of type hints in error checking expressions also needs> > to be specified.>> i actually did not change anything with regards to error checking> expressions, i.e. type hints? it still just passes type hint as-is> to the "inside expression".
Ah, I missed that this was already a thing.
> > Actually, speaking of type aliases, what does your harec patch do if> > alloc is provided a type hint which is an alias of (T | nomem)? If it's> > always dealiased, then when we go through the spec to better specify> > aliases, we'll need to make sure to not miss this part: consider> > `alloc(x): (T | nomem)`, where T is an alias of `(int | nomem)`. Is the> > initializer provided a type hint of `int`, `(int | nomem)`, or `T`?>> i suppose you mean that T is an alias to int? in this case, the> initializer is not provided a type hint at all, because it is> invalid: it dealiases T and figures out that it is not a pointer> or slice.>> in the case that T is an alias to *int, the intialializer would be> provided int as a type hint.
Ah, right, oops. What I meant to say was, what if T is an alias of
(*int | nomem), and the type hint is (T | nomem)? Does it supply a type
hint of int, or does it see the tagged union and conclude it isn't a
pointer and not supply any type hint? The current wording suggests that
the former behavior should be followed, since it would recursively check
if it's a tagged union containing nomem (this is only possible with
aliases, since otherwise the nomem members are deduplicated), but the
latter behavior would also make sense. Point is, when specifying aliases
in more detail, we'll need to make sure we get the behavior correct
here.
> > > @@ -1182,6 +1192,7 @@ shall be provided to its \nonterminal{postfix-expression}.> > > \nonterminal{indexing-expression} \\> > > \nonterminal{slicing-expression} \\> > > \nonterminal{error-checking-expression} \\> > > + \nonterminal{builtin-expression} \\> > > > > > \nonterminaldef{object-selector} \\> > > \nonterminal{identifier} \\> > > @@ -1273,7 +1284,6 @@ expression is \terminal{void}.> > > \nonterminal{assertion-expression} \\> > > \nonterminal{measurement-expression} \\> > > \nonterminal{slice-mutation-expression} \\> > > - \nonterminal{postfix-expression} \\> > > \nonterminal{static-assertion-expression} \\> > > \nonterminal{variadic-expression} \\> > > \end{grammar}> > > @@ -1282,7 +1292,7 @@ expression is \terminal{void}.> > > > > > \begin{grammar}> > > \nonterminaldef{unary-expression} \\> > > - \nonterminal{builtin-expression} \\> > > + \nonterminal{postfix-expression} \\> > > \nonterminal{compound-expression} \\> > > \nonterminal{match-expression} \\> > > \nonterminal{switch-expression} \\> > > > NACK, unless you have a justification for this change which I'm missing.>> yeah, otherwise it is not possible to use a postfix-expression such as ? or !> with the builtins. so the builtins have to be contained in the> postfix-expression class.
Idk how I missed that lol. Makes sense.
On Sat, Sep 07, 2024 at 05:07:38PM -0400, Sebastian wrote:
> On Fri Sep 6, 2024 at 11:49 PM EDT, Lorenz (xha) wrote:> > i suppose you mean that T is an alias to int? in this case, the> > initializer is not provided a type hint at all, because it is> > invalid: it dealiases T and figures out that it is not a pointer> > or slice.> >> > in the case that T is an alias to *int, the intialializer would be> > provided int as a type hint.> > Ah, right, oops. What I meant to say was, what if T is an alias of> (*int | nomem), and the type hint is (T | nomem)? Does it supply a type> hint of int, or does it see the tagged union and conclude it isn't a> pointer and not supply any type hint? The current wording suggests that> the former behavior should be followed, since it would recursively check> if it's a tagged union containing nomem (this is only possible with> aliases, since otherwise the nomem members are deduplicated), but the> latter behavior would also make sense. Point is, when specifying aliases> in more detail, we'll need to make sure we get the behavior correct> here.
it would not supply a type hint because it is not a pointer or slice. i think
this is the better behavior because otherwise we can go look into every corner
case and figure out how to handle that, for basically nothing at all lol
i think your wording is fine and makes it clear how implementations are
supposed to handle this:
+\specsubsubitem
+If the \nonterminal{allocation-expression} is provided a type hint which is a
+tagged union type with exactly two member types, one of which being
+\terminal{nomem}, the behavior shall be exactly as though the provided type hint
+were the member type which isn't \terminal{nomem}. Otherwise, if the
+\nonterminal{allocation-expression} is provided a type hint which is a pointer
+type, the pointer type's secondary type shall be provided to the initializer as
+a type hint. Otherwise, if the \nonterminal{allocation-expression} is provided a
+type hint which is a slice type, the slice type shall be provided to the
+initializer as a type hint.
i don't think we have to worry about it beeing misinterpreted.