In the previous chapter we presented an informal overview of Typed Lua.
We showed that programmers can use Typed Lua to combine static and dynamic
typing in the same code, and it allows them to incrementally migrate from
dynamic to static typing.
This is a benefit to programmers that use dynamically typed languages
to build large applications, as static types detect many bugs
during the development phase, and also provide better documentation.

In this chapter we present the abstract syntax of Typed Lua types,
the subtyping rules, and the most interesting typing rules.
Besides its practical contributions, Typed Lua also has some interesting
contributions to the field of optional type systems for scripting
languages.
They are novel type system features that let Typed Lua cover several Lua idioms
and features, such as refinement of tables, multiple assignment, and multiple return values.

\section{Types}
\label{sec:types}

Typed Lua includes types that can appear in annotations and some
special types that cannot appear in annotations, though they
play special role in type checking some Lua idioms and handling flow typing.
Special types cannot appear in annotations because they do not have
a corresponding concrete syntax, so we also isolated them in the
formalization to make the implementation easier.
First we present the types that compose the type language of our
type system, and then we present the special types, indicating
why they are necessary.

\begin{figure*}[!ht]
\textbf{Type Language}\\
\dstart
$$
\begin{array}{rlr}
F ::= & & \textsc{first-level types:}\\
& \;\; L & \textit{literal types}\\
& | \; B & \textit{base types}\\
& | \; \Nil & \textit{nil type}\\
& | \; \Value & \textit{top type}\\
& | \; \Any & \textit{dynamic type}\\
& | \; \Self & \textit{self type}\\
& | \; F_{1} \cup F_{2} & \textit{union types}\\
& | \; S_{1} \rightarrow S_{2} & \textit{function types}\\
& | \; \{\overline{F{:}V}\}_{unique|open|fixed|closed} & \textit{table types}\\
& |\; x & \textit{type variables}\\
& | \; \mu x.F & \textit{recursive types}\\
%\multicolumn{3}{c}{}\\
L ::= & & \textsc{{\small literal types:}}\\
& \;\; \False \; | \; \True \; | \; {\it int} \; | \; {\it float} \; | \; {\it string} &\\
%\multicolumn{3}{c}{}\\
B ::= & & \textsc{{\small base types:}}\\
& \;\; \Boolean \; | \; \Integer \; | \; \Number \; | \; \String &\\
%\multicolumn{3}{c}{}\\
V ::= & & \textsc{{\small value types:}}\\
& \;\; F \; | \; \Const \; F &\\
%\multicolumn{3}{c}{}\\
S ::= & & \textsc{second-level types:}\\
& \;\; P & \textit{tuple types}\\
& | \; S_{1} \sqcup S_{2} & \textit{unions of tuple types}\\
%\multicolumn{3}{c}{}\\
P ::= & & \textsc{{\small tuple types:}}\\
& \;\; F{*} & \textit{variadic types}\\
& | \; F \times P & \textit{pair types}
\end{array}
$$
\dend
\caption{The abstract syntax of Typed Lua types}
\label{fig:typelang}
\end{figure*}

Figure \ref{fig:typelang} presents the abstract syntax of
Typed Lua types.
Typed Lua splits types into two categories:
\emph{first-level types} and \emph{second-level types}.
First-level types represent first-class Lua values and
second-level types represent tuples of values that appear in the
input and output of functions.
First-level types include literal types, base types, the type $\Nil$,
the top type $\Value$, the dynamic type $\Any$, the type $\Self$,
union types, function types, table types, and recursive types.
Second-level types include tuple types and unions of tuple types.
Tuple types include variadic types and pair types.
Types are ordered by a subtype relationship that we introduce
in Section \ref{sec:subtyping}, so Lua values may belong to
several distinct types.

Literal types represent the type of literal values.
They can be the boolean values $\False$ and $\True$,
an integer value, a floating point value, or a string value.
We will see that literal types are important in our treatment of
table types as records.

Typed Lua includes four base types: $\Boolean$, $\Integer$, $\Number$, and $\String$.
The base types $\Boolean$ and $\String$ represent the values that
Lua tags as \texttt{boolean} and \texttt{string} during run-time.
Lua 5.3 introduced two internal representations to the tag \texttt{number}:
\texttt{integer} for integer numbers and \texttt{float} for real numbers.
Lua does automatic promotion of \texttt{integer} values to \texttt{float}
values as needed.
We introduced the base type $\Number$ to represent \texttt{float} values,
and the base type $\Integer$ to represent \texttt{integer} values.
In the next section we will show that $\Integer$ is a subtype of $\Number$.
This allows programmers to keep using \texttt{integer} values where
\texttt{float} values are expected.

The type $\Nil$ is the type of \texttt{nil}, the value that Lua uses for
undefined variables, missing parameters, and missing table keys.

The type $\Value$ is the top type, which represents any Lua value.
In Section \ref{sec:rules} we will show that this type,
along with variadic types, helps the type system to drop extra values
on assignments and function calls, thus preserving the
semantics of Lua in these cases.

Typed Lua includes the dynamic type $\Any$ for allowing programmers
to mix static and dynamic typing.

Typed Lua uses the type $\Self$ to represent the \emph{receiver}
in object-oriented method definitions and method calls.
As we mentioned in Section \ref{sec:oop}, we need the type
$\Self$ to prevent programs from indexing a method without
calling it with the correct receiver.

Union types $F_{1} \cup F_{2}$ represent data types that can hold a value
of two different types.

Function types have the form $S_{1} \rightarrow S_{2}$ and represent Lua functions,
where $S$ is a second-level type.

Second-level types are either tuple types or unions of tuple types.
Tuple types are tuples of first-level types that end with a variadic type.
Typed Lua needs second-level types because tuples are not first-class
values in Lua, only appearing on argument passing, multiple returns,
and multiple assignments.
A variadic type $F{*}$ represents a sequence of values of type $F \cup \Nil$;
it is the type of a vararg expression.
Second-level types include unions of tuples because Lua programs
usually overload the return type of functions to denote error,
as we mentioned in Section \ref{sec:statistics}.
For clarity, we use the symbol $\sqcup$ to represent the union between
two different tuple types.
Note that $\cup$ represents the union between two first-level types,
while $\sqcup$ represents the union between two tuple types.

Back to first-level types, table types represent the various forms
that Lua tables can take.
The syntactical form of table types is $\{\overline{F{:}V}\}_{unique|open|fixed|closed}$,
where the notation $\overline{F{:}V}$ denotes the list $F_{1}{:}V_{1}, ..., F_{n}{:}V_{n}$.
Each $V_{i}$ represents the type of the value that table keys of type $F_{i}$ map to.
Value types represent mutable fields by default, but we can use the
$\Const$ type to make them represent immutable fields.
Making a field $\Const$ does not guarantee that its value cannot change,
as the table may have aliases with a non-$\Const$ type for that field.
Typed Lua needs immutable fields to enable depth subtyping between table types.

\label{def:tabletype}
We also use the tags \emph{unique}, \emph{open}, \emph{fixed}, and \emph{closed}
to classify table types.
The tag \emph{closed} represents table types that do not provide
any guarantees about keys with types not listed in the table type.
In particular, in the concrete syntax, type annotations, interface
declarations, and userdata declarations always describe \emph{closed} table types.
The tags \emph{unique}, \emph{open}, and \emph{fixed} represent
tables with no keys that do not inhabit one of the table's key types,
but with different guarantees about the reference to a value of
that type.
A reference to an \emph{unique} table is guaranteed to point
to a table that has no other references to it.
In particular, the type of the table constructor has this tag,
as it allows greater flexibility in reinterpreting its type.
A reference to an \emph{open} table is guaranteed to have only
\emph{closed} references pointing to the same table,
a guarantee that still lets the type system reinterpret the type
of a reference, but with more restrictions.
A reference to a \emph{fixed} table can have any number of
\emph{fixed} or \emph{closed} references point to it,
so its type cannot change anymore.
In particular, the type of a class has this tag in our type system.

A \emph{fixed} table type guarantees that there are
no keys with a type that is not one of its key types.
Even though this guarantee allows type-safe iteration on
\emph{fixed} table types, it forbids width subtyping that
is necessary for object-oriented programming, so \emph{closed}
table types remove this guarantee to allow width subytping
between other table types and \emph{closed} table types.
This means that objects have \emph{closed} table types,
while their classes have \emph{fixed} table types.

Any table type has to be \emph{well-formed}.
Informally, a table type is well-formed if key types do not overlap.
In Section \ref{sec:rules} we formalize the definition of well-formed table types.
We delay the proper formalization of well-formed table types because we use
consistent-subtyping in this formalization.

Recursive types have the form $\mu x.F$,
where $F$ is a first-level type that $x$ represents.
For instance, $\mu x.\{``info":\Integer, ``next":x \;\cup\; \Nil\}_{closed}$
is a type for singly-linked lists of integers.
In Section \ref{sec:alias} we mentioned that we can use the following
interface declaration as an alias to this type:
\begin{verbatim}
    local interface Element
      info:integer
      next:Element?
    end
\end{verbatim}

With recursive types we finish the discussion about Typed Lua types,
and we begin the discussion about special types.

\begin{figure*}[!ht]
\textbf{Special Types}\\
\dstart
$$
\begin{array}{rlr}
T ::= & & \textsc{expression types:}\\
& \;\; F & \textit{first-level types}\\
& | \; \phi(F_{1},F_{2}) & \textit{filter types}\\
& | \; \pi_{i}^{x} & \textit{projection types}\\
%\multicolumn{3}{c}{}\\
E ::= & & \textsc{expression list types:}\\
& \;\; T{*} & \textit{variadic types}\\
& | \; T \times E & \textit{pair types}\\
%\multicolumn{3}{c}{}\\
R ::= & & \textsc{filter result types:}\\
& \;\; \mathbf{void} & \textit{void type}\\
& |\; F & \textit{first-level types}
\end{array}
$$
\dend
\caption{The special types used by Typed Lua}
\label{fig:specialtypes}
\end{figure*}

Figure \ref{fig:specialtypes} presents the special types that
Typed Lua includes for typing some Lua idioms and flow typing.
Typed Lua splits special types into three categories:
\emph{expression types}, \emph{expression list types}, and
\emph{filter result types}.
Expression types represent the type of expressions in the type system,
which can be any first-level type, a filter type, or a projection type.
Expression list types represent the type of lists of expressions,
which are tuples of expression types that end with a variadic type.
Filter result types are either the type $\Void$ or a first-level type.
In Section \ref{sec:fap} we will show that Typed Lua uses filter types
in flow typing, being the type $\Void$ a type with no values, used by the
type system as a way to detect branches that are unreachable due to flow typing.

\label{def:filtertype}
Typed Lua includes filter types as a way to discriminate the type of local
variables inside conditions.
Our type system uses filter types to formalize the \texttt{type} predicates
that we mentioned in Section \ref{sec:unions}.
This means that \texttt{type} predicates use filter types of the form
$\phi(F_{1},F_{2})$ to discriminate local variables that are bound to
union types.
In a filter type $\phi(F_{1},T_{2})$, $F_{1}$ is the original type and
$F_{2}$ is the discriminated type.

\label{def:projectiontype}
Typed Lua includes projection types as a way to project
unions of tuple types into unions of first-level types.
In Section \ref{sec:fap} we will show in more detail how our type system
uses them as a mechanism for handling unions of tuple types,
when they appear in the right-hand side of the declaration of local variables,
as we mentioned in Section \ref{sec:unions}.
We also show how this feature allows our type system to constrain
the type of a local variable that depends on the type of another local variable.

\section{Subtyping}
\label{sec:subtyping}

Our type system uses subtyping \cite{cardelli1984smi,abadi1996to} to order
types and consistent-subtyping \cite{siek2007objects,siek2013mutable}
to allow the interaction between statically and dynamically typed code.
We explain the subtyping and consistent-subtyping rules throughout this section.
However, we focus the discussion on the definition of subtyping because,
as we mentioned in Section \ref{sec:gradual}, we can combine the
consistency and subtyping relations to achieve consistent-subtyping.
The differences between subtyping and consistent-subtyping are the way
they handle the dynamic type, and the fact that subtyping is transitive,
but consistent-subtyping is not.

We present the subtyping rules as a deduction system for the
subtyping relation $\senv \vdash T_{1} \subtype T_{2}$,
where $T_{1}$ and $T_{2}$ are two types of the same kind.
The variable $\senv$ is a set of pairs of recursion variables.
We need this set to record the hypotheses that we assume when checking
recursive types.

The subtyping rules for literal types and base types include the rules
for defining that literal types are subtypes of their respective base types,
and that $\Integer$ is a subtype of $\Number$:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{S-FALSE}\\
\senv \vdash \False \subtype \Boolean
\end{array}
\;
\begin{array}{c}
\mylabel{S-TRUE}\\
\senv \vdash \True \subtype \Boolean
\end{array}
\;
\begin{array}{c}
\mylabel{S-STRING}\\
\senv \vdash {\it string} \subtype \String
\end{array}
\\ \\
\begin{array}{c}
\mylabel{S-INT1}\\
\senv \vdash {\it int} \subtype \Integer
\end{array}
\;
\begin{array}{c}
\mylabel{S-INT2}\\
\senv \vdash {\it int} \subtype \Number
\end{array}
\;
\begin{array}{c}
\mylabel{S-FLOAT}\\
\senv \vdash {\it float} \subtype \Number
\end{array}
\\ \\
\begin{array}{c}
\mylabel{S-INTEGER}\\
\senv \vdash \Integer \subtype \Number
\end{array}
\end{array}
\]

Subtyping is reflexive and transitive;
therefore, we could have omitted the rule \textsc{S-INT2}.
More precisely, we could have defined a transitive rule for first-level
types instead of defining specific rules for transitive cases.
For instance, a transitive rule would allow us to derive that
\[
\dfrac{\senv \vdash 1 \subtype \Integer \;\;\;
       \senv \vdash \Integer \subtype \Number}
      {\senv \vdash 1 \subtype \Number}
\]

However, we are using the subtyping rules as the template for defining
the consistent-subtyping rules, and consistent-subtyping is not
transitive.
More precisely, we want the subtyping and consistent-subtyping rules
to differ only in the way they handle the dynamic type.
Thus, we define the subtyping rules using an algorithmic approach
that is close to the implementation, as this approach allows us to use
subtyping to easily formalize consistent-subtyping.

Our type system includes the top type $\Value$,
so any first-level type is a subtype of $\Value$:
\[
\begin{array}{c}
\mylabel{S-VALUE}\\
\senv \vdash F \subtype \Value
\end{array}
\]

Many programming languages include a bottom type to represent
an empty value that programmers can use as a default expression,
and we could have used the type $\Nil$ for this role.
However, making $\Nil$ the bottom type would lead to several expressions
that would pass the type checker, but that would fail during run-time
in the presence of a \texttt{nil} value.
Thus, our type system does not have a bottom type, and $\Nil$ is a
subtype only of itself and of $\Value$.

Another type that is only a subtype of itself and of the type $\Value$
is the type $\Self$.

The subtyping rules for union types are standard:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{S-UNION1}\\
\dfrac{\senv \vdash F_{1} \subtype F \;\;\;
       \senv \vdash F_{2} \subtype F}
      {\senv \vdash F_{1} \cup F_{2} \subtype F}
\end{array}
\;
\begin{array}{c}
\mylabel{S-UNION2}\\
\dfrac{\senv \vdash F \subtype F_{1}}
      {\senv \vdash F \subtype F_{1} \cup F_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{S-UNION3}\\
\dfrac{\senv \vdash F \subtype F_{2}}
      {\senv \vdash F \subtype F_{1} \cup F_{2}}
\end{array}
\end{array}
\]

The first rule shows that a union type $F_{1} \cup F_{2}$
is a subtype of $F$ if both $F_{1}$ and $F_{2}$ are subtypes
of $F$;
and the other rules show that a type $F$ is a subtype
of a union type $F_{1} \cup F_{2}$ if $F$ is a subtype of
either $F_{1}$ or $F_{2}$.

The subtyping rule for function types is also standard:
\[
\begin{array}{c}
\mylabel{S-FUNCTION}\\
\dfrac{\senv \vdash S_{3} \subtype S_{1} \;\;\;
       \senv \vdash S_{2} \subtype S_{4}}
      {\senv \vdash S_{1} \rightarrow S_{2} \subtype S_{3} \rightarrow S_{4}}
\end{array}
\]

The rule \textsc{S-FUNCTION} shows that subtyping between
function types is contravariant on the type of the parameter list
and covariant on the return type.
In the previous section we explained why our type system uses
second-level types to represent the type of the parameter list
and the return type.
Now, we explain their subtyping rules.

The subtyping rule for pair types is the standard covariant rule:
\[
\begin{array}{c}
\mylabel{S-PAIR1}\\
\dfrac{\senv \vdash F_{1} \subtype F_{2} \;\;\;
       \senv \vdash P_{1} \subtype P_{2}}
      {\senv \vdash F_{1} \times P_{1} \subtype F_{2} \times P_{2}}
\end{array}
\]

The subtyping rules for variadic types are not so obvious.
We need three different subtyping rules for variadic types
to handle all the cases where they can appear.

The rule \textsc{S-VARARG1} handles subtyping between two
variadic types:
\[
\begin{array}{c}
\mylabel{S-VARARG1}\\
\dfrac{\senv \vdash F_{1} \cup \Nil \subtype F_{2} \cup \Nil}
      {\senv \vdash F_{1}{*} \subtype F_{2}{*}}
\end{array}
\]

This rule shows that $F_{1}{*}$ is a subtype of $F_{2}{*}$
if $F_{1} \cup \Nil$ is a subtype of $F_{2} \cup \Nil$.
It explicitly includes $\Nil$ in both sides because otherwise
$\Nil{*}$ would not be a subtype of several other variadic types.
For instance, $\Nil{*}$ would not be a subtype of $\Number{*}$,
as $\Nil \not\subtype \Number$.

The other rules handle subtyping between a varidic type and a pair type:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{S-VARARG2}\\
\dfrac{\senv \vdash F_{1} \cup \Nil \subtype F_{2} \;\;\;
       \senv \vdash F_{1}{*} \subtype P_{2}}
      {\senv \vdash F_{1}{*} \subtype F_{2} \times P_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{S-VARARG3}\\
\dfrac{\senv \vdash F_{1} \subtype F_{2} \cup \Nil \;\;\;
       \senv \vdash P_{1} \subtype F_{2}{*}}
      {\senv \vdash F_{1} \times P_{1} \subtype F_{2}{*}}
\end{array}
\end{array}
\]

These rules state the conditions when tuple types of different
length are compatible.
In the next section we will show that we use the subtyping rules for variadic types,
along with the types $\Value$ and $\Nil$, to make our type system reflect
the semantics of Lua on discarding extra parameters and
replacing missing parameters.

The subtyping rules for unions of tuple types are similar to the
subtyping rules for unions of first-level types:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{S-UNION4}\\
\dfrac{\senv \vdash S_{1} \subtype S \;\;\;
       \senv \vdash S_{2} \subtype S}
      {\senv \vdash S_{1} \sqcup S_{2} \subtype S}
\end{array}
\;
\begin{array}{c}
\mylabel{S-UNION5}\\
\dfrac{\senv \vdash S \subtype S_{1}}
      {\senv \vdash S \subtype S_{1} \sqcup S_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{S-UNION6}\\
\dfrac{\senv \vdash S \subtype S_{2}}
      {\senv \vdash S \subtype S_{1} \sqcup S_{2}}
\end{array}
\end{array}
\]

Back to the subtyping rules between first-level types,
the subtyping rule among a \emph{fixed} or \emph{closed}
table type and another \emph{closed} table type resembles the
standard subtyping rule between records:
\[
\begin{array}{c}
\mylabel{S-TABLE1}\\
\dfrac{\forall i \; \exists j \;\;\;
       \senv \vdash F_{j} \subtype F_{i}' \;\;\;
       \senv \vdash F_{i}' \subtype F_{j} \;\;\;
       \senv \vdash V_{j} \subtype_{c} V_{i}'}
      {\senv \vdash \{\overline{F{:}V}\}_{fixed|closed} \subtype
                    \{\overline{F'{:}V'}\}_{closed}}
\end{array}
\]

The rule \textsc{S-TABLE1} allows width subtyping and introduces the
auxiliary relation $\subtype_{c}$ to handle depth subtyping on the
type of the values stored in the table fields.
We need an auxiliary relation because the subtyping of the
type of the values stored in the table fields changes according to
the tags of the table types.
We define the relation $\subtype_{c}$ as follows:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{S-FIELD1}\\
\dfrac{\senv \vdash F_{1} \subtype F_{2} \;\;\;
       \senv \vdash F_{2} \subtype F_{1}}
      {\senv \vdash F_{1} \subtype_{c} F_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{S-FIELD2}\\
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash \Const \; F_{1} \subtype_{c} \Const \; F_{2}}
\end{array}
\\ \\
\begin{array}{c}
\mylabel{S-FIELD3}\\
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash F_{1} \subtype_{c} \Const \; F_{2}}
\end{array}
\end{array}
\]

These rules allow depth subtyping on $\Const$ fields.
The rule \textsc{S-FIELD1} defines that mutable fields are invariant,
while the rule \textsc{S-FIELD2} defines that immutable fields are covariant.
The rule \textsc{S-FIELD3} defines that it is safe to promote fields
from mutable to immutable.
We do not include a rule that allows promoting fields from immutable
to mutable because this would be unsafe due to variance.

There is a limitation on \emph{closed} table types that led us to
introduce \emph{open} and \emph{unique} table types.
If the table constructor had a \emph{closed} table type, then
programmers would not be able to use it to initialize a variable with
a table type that describes a more general type.
For instance,
\begin{verbatim}
    local t:{"x":integer, "y":integer?} = { x = 1, y = 2 }
\end{verbatim}
would not type check, as the type of the table constructor would not
be a subtype of the type in the annotation.
More precisely,
\[
\{``x":1, ``y":2\}_{closed} \not\subtype
\{``x":\Integer, ``y":\Integer \cup \Nil\}_{closed}
\]

Simply promoting the type of each table value to its supertype would
not overcome this limitation, as it still would give to the table constructor
a \emph{closed} table type without covariant mutable fields.
Thus, programmers would not be able to use the table constructor to
initialize a variable with a table type that includes an optional field.
Using the previous example,
\begin{align*}
& \{``x":\Integer, ``y":\Integer\}_{closed} \not\subtype \\
& \{``x":\Integer, ``y":\Integer \cup \Nil\}_{closed}
\end{align*}

We introduced \emph{unique} table types to avoid this limitation,
as they represent the type of tables with no keys that do not
inhabit one of the table's key types, and with no alias.
In particular, this is the case of the table constructor.
The following subtyping rule defines the subtyping relation among
\emph{unique} table types and \emph{closed} table types:
\[
\begin{array}{c}
\mylabel{S-TABLE2}\\
\dfrac{\begin{array}{c}
       \forall i \; \forall j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash V_{i} \subtype_{u} V_{j}'\\
       \forall j \; \nexists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash \Nil \subtype_{o} V_{j}'
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{unique} \subtype
                    \{\overline{F'{:}V'}\}_{closed}}
\end{array}
\]

The rule \textsc{S-TABLE2} allows width subtyping and covariant keys.
It allows covariant keys because we also want to use \emph{unique}
table types as a way to join table fields that inhabit \emph{closed} table types.
For instance, we want to use the table constructor to initialize
a variable with a table type that describes a hash.
More precisely, this rule states that it is safe to recast the table type
$\{``x":\Integer, ``y":\Integer, ``z":\Integer\}_{unique}$ to
$\{\String:\Integer \cup \Nil\}_{closed}$, as long as the
new type becomes inaccessible with the original type.

The rule \textsc{S-TABLE2} introduced the auxiliary relations
$\subtype_{u}$ and $\subtype_{o}$.
The first allows depth subtyping on all fields,
while the second allows the omission of optional fields.
We define them as follows:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{S-FIELD4}\\
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash F_{1} \subtype_{u} F_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{S-FIELD5}\\
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash \Const \; F_{1} \subtype_{u} \Const \; F_{2}}
\end{array}
\\ \\
\begin{array}{c}
\mylabel{S-FIELD6}\\
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash \Const \; F_{1} \subtype_{u} F_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{S-FIELD7}\\
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash F_{1} \subtype_{u} \Const \; F_{2}}
\end{array}
\\ \\
\begin{array}{c}
\mylabel{S-FIELD8}\\
\dfrac{\senv \vdash \Nil \subtype F}
      {\senv \vdash \Nil \subtype_{o} F}
\end{array}
\;
\begin{array}{c}
\mylabel{S-FIELD9}\\
\dfrac{\senv \vdash \Nil \subtype F}
      {\senv \vdash \Nil \subtype_{o} \Const \; F}
\end{array}
\end{array}
\]

Using \emph{unique} table types to represent the type of the table
constructor allows our type system to type check the previous example.
More precisely,
\[
\{``x":1, ``y":2\}_{unique} \subtype
\{``x":\Integer, ``y":\Integer \cup \Nil\}_{closed}
\]

Even though we allow width subtyping between \emph{unique} and \emph{closed}
table types, we do not allow it among \emph{unique} and other table types
because it would violate our definition of these other table types:
\[
\begin{array}{c}
\mylabel{S-TABLE3}\\
\dfrac{\begin{array}{c}
       \forall i \; \exists j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \land \senv \vdash V_{i} \subtype_{u} V_{j}' \\
       \forall j \; \nexists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash \Nil \subtype_{o} V_{j}'
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{unique} \subtype
                    \{\overline{F'{:}V'}\}_{unique|open|fixed}}
\end{array}
\]

The rule that handles subtyping between \emph{open} and \emph{closed} table
types allows width subtyping:
\[
\begin{array}{c}
\mylabel{S-TABLE4}\\
\dfrac{\begin{array}{c}
       \forall i \; \forall j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash V_{i} \subtype_{c} V_{j}' \\
       \forall j \; \nexists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash \Nil \subtype_{o} V_{j}'
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{open} \subtype
                    \{\overline{F'{:}V'}\}_{closed}}
\end{array}
\]

However, the rule that handles subtyping among \emph{open} and
\emph{open} or \emph{fixed} table types does not allow width subtyping:
\[
\begin{array}{c}
\mylabel{S-TABLE5}\\
\dfrac{\begin{array}{c}
       \forall i \; \exists j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \land \senv \vdash V_{i} \subtype_{c} V_{j}' \\
       \forall j \; \nexists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash \Nil \subtype_{o} V_{j}'
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{open} \subtype
                    \{\overline{F'{:}V'}\}_{open|fixed}}
\end{array}
\]

The rules \textsc{S-TABLE4} and \textsc{S-TABLE5} allow joining fields
plus omitting optional fields.
Both rules use $\subtype_{c}$ to allow depth subtyping on $\Const$ fields only.

We introduced \emph{fixed} table types because we needed a safe way
to represent the type of classes that can allow single inheritance
through the refinement of table types.
The rule that handles subtyping between \emph{fixed} table types
does not allow width subtyping, joining fields, and omitting fields,
but it allows depth subtyping on $\Const$ fields:
\[
\begin{array}{c}
\mylabel{S-TABLE6}\\
\dfrac{\begin{array}{c}
       \forall i \; \exists j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \;\;\;
       \senv \vdash F_{j}' \subtype F_{i} \;\;\;
       \senv \vdash V_{i} \subtype_{c} V_{j}' \\
       \forall j \; \exists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \;\;\;
       \senv \vdash F_{j}' \subtype F_{i} \;\;\;
       \senv \vdash V_{i} \subtype_{c} V_{j}' \\
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{fixed} \subtype
                    \{\overline{F'{:}V'}\}_{fixed}}
\end{array}
\]

In the next section we will show in more detail how our type system
uses these tags to handle the refinement of table types.

We use the \emph{Amber rule} \cite{cardelli1986amber} to define
subtyping between recursive types:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{S-AMBER}\\
\dfrac{\senv[x_{1} \subtype x_{2}] \vdash F_{1} \subtype F_{2}}
      {\senv \vdash \mu x_{1}.F_{1} \subtype \mu x_{2}.F_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{S-ASSUMPTION}\\
\dfrac{x_{1} \subtype x_{2} \in \senv}
      {\senv \vdash x_{1} \subtype x_{2}}
\end{array}
\end{array}
\]

The rule \textsc{S-AMBER} also uses the rule \textsc{S-ASSUMPTION}
to check whether $\mu x_{1}.F_{1} \subtype \mu x_{2}.F_{2}$.
Both rules use the set of assumptions $\senv$,
where each assumption is a pair of recursion variables.
The rule \textsc{S-AMBER} extends $\senv$ with the assumption
$x_{1} \subtype x_{2}$ to check whether $F_{1} \subtype F_{2}$.
The rule \textsc{S-ASSUMPTION} allows the rule \textsc{S-AMBER}
to check whether an assumption is valid.

A recursive type may appear inside a first-level type, and our
type system includes subtyping rules to handle subtyping between
recursive types and other first-level types:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{S-UNFOLDR}\\
\dfrac{\senv \vdash F_{1} \subtype [x \mapsto \mu x.F_{2}]F_{2}}
      {\senv \vdash F_{1} \subtype \mu x.F_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{S-UNFOLDL}\\
\dfrac{\senv \vdash [x \mapsto \mu x.F_{1}]F_{1} \subtype F_{2}}
      {\senv \vdash \mu x.F_{1} \subtype F_{2}}
\end{array}
\end{array}
\]

As an example, the rule \textsc{S-UNFOLDR} allows our type system to
type check the function \texttt{insert} from Section \ref{sec:alias}:
\begin{verbatim}
    local function insert (e:Element?, v:integer):Element
      return { info = v, next = e }
    end
\end{verbatim}
that is, the type checker uses the rule \textsc{S-UNFOLDR} to verify whether
the type of the table constructor is a subtype of \texttt{Element}:
\begin{align*}
\{ & ``info":\Integer, \\
   & ``next":\mu x.\{``info":\Integer,
                     ``next":x \;\cup\; \Nil\}_{closed} \cup \Nil \}_{unique} \subtype \\
& \mu x.\{``info":\Integer, ``next":x \;\cup\; \Nil\}_{closed}
\end{align*}

Filter types are subtypes only of themselves.
More precisely, a filter type $\phi(F_{1},F_{2})$ is a subtype of
the same filter type $\phi(F_{1},F_{2})$, which shares the same
types $F_{1}$ and $F_{2}$.

Projection types are subtypes only of themselves.
More precisely, a projection type $\pi_{i}^{x}$ is a subtype of the
same projection type $\pi_{i}^{x}$, which shares the same union of
tuples $x$ and the same index $i$.

The subtyping rules for expression list types are similar to the
subtyping rules for tuple types.

The dynamic type $\Any$ is neither the bottom nor the top type,
but a separate type that is subtype only of itself and of $\Value$.

Even though the dynamic type $\Any$ does not interact with subtyping,
it does interact with consistent-subtyping.
We present the consistent-subtyping rules as a deduction system for
the consistent-subtyping relation $\senv \vdash T_{1} \lesssim T_{2}$,
where $T_{1}$ and $T_{2}$ are two types of the same kind.
As in the subtyping relation, $\senv$ is also a set of pairs of
recursion variables.
We define the consistent-subtyping rules for the dynamic type $\Any$
as follows:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{C-ANY1}\\
\senv \vdash F \lesssim \Any
\end{array}
\;
\begin{array}{c}
\mylabel{C-ANY2}\\
\senv \vdash \Any \lesssim F
\end{array}
\end{array}
\]

If we had set the type $\Any$ as both bottom and top types of our
subtyping relation, then any type $F_{1}$ would be a subtype of
any other type $F_{2}$.
The consequence of this is that all programs would type check without errors.
This would happen due to the transitivity of subtyping, that is,
we would be able to down-cast any type $F_{1}$ to $\Any$ and then up-cast
$\Any$ to any other type $F_{2}$.
The rules \textsc{C-ANY1} and \textsc{C-ANY2} are the rules that
allow the dynamic type to interact with other first-level types,
and thus allow dynamically typed code to coexist with statically
typed code.
Because of these two rules, consistent-subtyping cannot be transitive.
These two rules are the only rules that differ between
subtyping and consistent-subtyping, if we implement the subtyping rules
as we do in this section.

In the implementation of Typed Lua we also use consistent-subtyping to
normalize and simplify union types, though we let union types free in
the formalization.
For instance, the union type \texttt{boolean|any} results in the
type \texttt{any}, because \texttt{boolean} is consistent-subtype
of \texttt{any}.
Another example is the union type \texttt{number|nil|1} that
results in the union type \texttt{number|nil}, because
\texttt{1} is consistent-subtype of \texttt{number}.

\section{Type checking}
\label{sec:rules}

In this section we use a reduced core of Typed Lua to present the
most interesting rules of our type system.
These rules type check multiple assignment, table refinement,
and overloading on the return type of functions.
Appendix \ref{app:rules} presents the full set of typing rules.

Our core limits control flow to if and while statements;
it has explicit type annotations, explicit scope for variables,
explicit method declarations, and explicit method calls.
Here is a list of features that are not present in our reduced core:
\begin{itemize}
\item labels and goto statements (they are difficult to handle along
with our simplified form of \emph{flow typing}, and they are out of
scope for now);
\item explicit blocks (we are already using explicit scope for variables);
\item other loop structures such as repeat-until, numeric for,
and generic for (we can use while to express them);
\item table fields other than $[e_{1}] = e_{2}$
(we can use this form to express the missing forms);
\item arithmetic operators other than $+$
(other arithmetic operators have similar typing rules);
\item relational operators other than $==$ and $<$
(inequality has similar typing rules to $==$ and
other relational operators have similar typing rules to $<$);
\item bitwise operators other than $\&$
(other bitwise operators have similar typing rules).
\end{itemize}

Our reduced core does not lose much expressiveness, as it can express
any Lua program except those that use labels and goto statements.

\begin{figure}[!ht]
\textbf{Abstract Syntax}\\
\dstart
$$
\begin{array}{rlr}
s ::= & & \textsc{statements:}\\
& \;\; \mathbf{skip} & \textit{skip}\\
& | \; s_{1} \; ; \; s_{2} & \textit{sequence}\\
& | \; \overline{l} = el & \textit{multiple assignment}\\
& | \; \mathbf{while} \; e \; \mathbf{do} \; s \;
| \; \mathbf{if} \; e \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2} & \textit{control flow}\\
& | \; \mathbf{local} \; \overline{id{:}F} = el \; \mathbf{in} \; s & \textit{variable declaration}\\
& | \; \mathbf{local} \; \overline{id} = el \; \mathbf{in} \; s & \textit{variable declaration}\\
& | \; \mathbf{rec} \; id{:}F = e \; \mathbf{in} \; s & \textit{recursive declaration} \\
& | \; \mathbf{return} \; el & \textit{return} \\
& | \; \lfloor a \rfloor_{0} & \textit{application with no results}\\
& | \; \mathbf{fun} \; id_{1}{:}id_{2} \; (pl){:}S \; s \;;\; \mathbf{return} \; el & \textit{method declaration}\\
e ::= & & \textsc{expressions:}\\
& \;\; \mathbf{nil} & \textit{nil}\\
& | \; k & \textit{other literals}\\
& | \; id & \textit{variable access}\\
& | \; e_{1}[e_{2}] & \textit{table access}\\
& | \; {<}F{>} \; id & \textit{type coercion}\\
& | \; f & \textit{function declaration}\\
& | \; \{ \; \overline{[e_{1}] = e_{2}} \; \} \;
| \; \{ \; \overline{[e_{1}] = e_{2}},me \; \} & \textit{table constructor}\\
& | \; e_{1} + e_{2} \;
| \; e_{1} \; {..} \; e_{2} \;
| \; e_{1} == e_{2} \;
| \; e_{1} < e_{2} & \textit{binary operations}\\
& | \; e_{1} \;\&\; e_{2} \;
| \; e_{1} \; \mathbf{and} \; e_{2} \;
| \; e_{1} \; \mathbf{or} \; e_{2} & \textit{binary operations}\\
& | \; \mathbf{not} \; e \;
| \; \# \; e & \textit{unary operations} \\
& | \; \lfloor me \rfloor_{1} & \textit{expressions with one result}\\
l ::= & & \textsc{left-hand values:}\\
& \;\; id_{l} & \textit{variable assignment}\\
& | \; e_{1}[e_{2}]_{l} & \textit{table assignment}\\
& | \; id[e] \; {<}V{>} & \textit{type coercion}\\
k ::= & & \textsc{literal constants:}\\
& \;\; \mathbf{false} \; | \;
\mathbf{true} \; | \;
{\it int} \; | \;
{\it float} \; | \;
{\it string} & \\
el ::= & & \textsc{expression lists:}\\
& \;\; \overline{e} \; | \;
\overline{e}, me & \\
me ::= & & \textsc{multiple results:}\\
& \;\; a & \textit{application}\\
& | \; {...} & \textit{vararg expression}\\
a ::= & & \textsc{applications:}\\
& \;\; e(el) & \textit{function application}\\
& | \; e{:}n(el) & \textit{method application}\\
f ::= & & \textsc{function declarations:}\\
& \;\; \mathbf{fun} \; (pl){:}S \; s \;;\; \mathbf{return} \; el & \\
pl ::= & & \textsc{parameter lists:}\\
& \;\; \overline{id{:}F} \; | \;
\overline{id{:}F},{...}{:}F & \\
\end{array}
$$
\dend
\caption{The abstract syntax of Typed Lua}
\label{fig:syntax}
\end{figure}

Figure \ref{fig:syntax} presents the abstract syntax of core Typed Lua.
It splits the syntactic categories as follows:
$s$ are statements, $e$ are expressions, $l$ are left-hand values,
$k$ are literal constants, $el$ are expression lists,
$me$ are expressions with multiple results, $a$ are function and method applications,
$f$ are function declarations, $pl$ are parameter lists,
$id$ are variable names, $F$ are first-level types, and $S$ are second-level types.
The notation $\overline{id{:}F}$ denotes the list $id_{1}{:}F_{1}, ..., id_{n}{:}F_{n}$.

Our reduced core includes two statements for declaring local variables,
one with and another without type annotations.
While we use the former to formalize how our type system handles the declaration
of annotated variables, we use the latter to formalize how our type system
handles the declaration of unannotated variables through local type inference
and also the introduction of projection types.

Our reduced core also includes a truncation operator $\lfloor \rfloor$ for
function applications, method applications, and the vararg expression.
We use $\lfloor a \rfloor_{0}$ to denote function and method applications
that produce no value, because they appear as statements.
We use $\lfloor me \rfloor_{1}$ to denote function applications,
method applications, and vararg expressions that produce only one value,
even if they return multiple values.

We also include two kinds of type coercions in our core language:
the left-hand value $id[e] \; {<}V{>}$ and the expression ${<}F{>} \;id$.
Both allow the refinement of table types.
We also split variable names into two categories to have safe aliasing
of tables in the presence of refinement.
We use $id$ when variable names appear as expressions and $id_{l}$ when
variable names appear as left-hand values.

Even though we can assign only first-level types to variables,
functions and methods can return unions of second-level types,
and our type system should be able to project these unions of
second-level types into unions of first-level types.
We use two different environments to handle this feature.
The first environment is the type environment $\env$ that maps
variables to expression types, as the type of an expression can
be a first-level type, a filter type, or a projection type.
We use $\env_{1}[id \mapsto T]$ to extend the environment $\env_{1}$
with the variable $id$ that maps to type $T$.
The second environment is the projection environment $\penv$ that
maps projection variables to second-level types.
We use $\penv[x \mapsto S]$ to extend the environment $\penv$
with the projection variable $x$ that maps to type $S$.
In Section \ref{sec:fap} we will show how our type system uses the
projection environment $\penv$ for handling projection types,
and also for projecting unions of second-level types into
unions of first-level types.

We present the typing rules as a deduction system for two typing relations,
one for typing statements and another for typing expressions.

We use the relation $\env_{1}, \penv \vdash s, \env_{2}$ for typing statements.
This relation means that given a type environment $\env_{1}$
and a projection environment $\penv$, we can check that a statement $s$
produces a new type environment $\env_{2}$.

We use the relation $\env_{1}, \penv \vdash e : T, \env_{2}$ for typing expressions.
This relation means that given a type environment $\env_{1}$
and a projection environment $\penv$, we can check that an expression $e$ has
type $T$ and produces a new type environment $\env_{2}$.

\subsection*{Assignment and function application}
\label{sec:assignment}

Lua has multiple assignment, and our type system uses three
different kinds of typing rules to type check this feature.
It uses typing rules that type check the different forms
of expression lists that can appear in the right-hand side,
a typing rule that type checks a list of left-hand values,
and a general rule that uses consistent-subtyping to check
whether the type of the right-hand side is consistent with
the type of the left-hand side.

As an example, lets assume that $x$ and $y$ are variables in the
environment with types $\Integer$ and $\String$.
Let us see how our type system type checks the following assignment:
\[
x, y = 1, ``foo"
\]

First, our type system type checks the expression list in the right-hand
side of the assignment.
In our example, the right-hand side of the assignment has type
$1 \times ``foo" \times \Nil{*}$.
Note that our type system includes the type $\Nil{*}$ to replace
missing values.
The rules that type check expression lists introduce the type
$\Nil{*}$ to let the right-hand side produce fewer values than
expected in the left-hand side.
Our example uses the rule \textsc{T-EXPLIST1} to type check
the right-hand side of the assignment.
The rule \textsc{T-EXPLIST1} is the rule that type checks an
expression list where all expressions can only produce a single value:
\[
\begin{array}{c}
\mylabel{T-EXPLIST1}\\
\dfrac{\env_{1}, \penv \vdash e_{i}:F_{i}, \env_{i+1} \;\;\;
       \env_{f} = merge(\env_{1}, ..., \env_{n+1}) \;\;\;
       n = |\;\overline{e}\;|}
      {\env_{1}, \penv \vdash \overline{e}:F_{1} \times ... \times F_{n} \times \Nil{*}, \env_{f}}
\end{array}
\]

Later, in this section we will show that table refinement can
change the type environment while typing an expression or a left-hand value.
Thus, the rules that type check lists of expressions and lists of
left-hand values use a partial auxiliary function \emph{merge} to collect
all environment changes in a new environment $\env_{f}$, if there are no conflicts.
We will also show that we can only change the
environment to add new table fields in a table type, and we cannot change the
type of a variable or a table field which is already present in a table type.

After type checking the right-hand side, our type system type checks the list
of left-hand values.
In our example, the left-hand side of the assignment has type
$\Integer \times \String \times \Value{*}$.
Note that our type system uses the type $\Value{*}$ to discard extra values.
The rule that type checks lists of left-hand values introduces the type
$\Value{*}$ to let the right-hand side produce more values than
expected in the left-hand side.
Our example uses the rule \textsc{T-LHSLIST} to type
check a list of left-hand values:
\[
\begin{array}{c}
\mylabel{T-LHSLIST}\\
\dfrac{\env_{1}, \penv \vdash l_{i}:F_{i}, \env_{i+1} \;\;\;
       \env_{f} = merge(\env_{1}, ..., \env_{n+1}) \;\;\;
       n = |\;\overline{l}\;|}
      {\env_{1}, \penv \vdash \overline{l}:F_{1} \times ... \times F_{n} \times \Value{*}, \env_{f}}
\end{array}
\]

After type checking the right-hand side and the left-hand side of an assignment,
our type system checks whether their types are consistent.
The rule \textsc{T-ASSIGNMENT} is the general rule that expresses this idea:
\[
\begin{array}{c}
\mylabel{T-ASSIGNMENT}\\
\dfrac{\env_{1}, \penv \vdash el:S_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash \overline{l}:S_{2}, \env_{3} \;\;\;
       S_{1} \lesssim S_{2}}
      {\env_{1}, \penv \vdash \overline{l} = el,\env_{3}}
\end{array}
\]

Back to our example, it type checks through rule \textsc{T-ASSIGNMENT} because
\[
1 \times ``foo" \times \Nil{*} \lesssim \Integer \times \String \times \Value{*}
\]

As another example, lets assume that $x$, $y$, and $z$ are variables in
the environment with types $\Integer$, $\String$, and $\String \cup \Nil$.
The assignment
\[
x, y, z = 1, ``foo"
\]
type checks because
\[
1 \times ``foo" \times \Nil{*} \lesssim \Integer \times \String \times (\String \cup \Nil) \times \Value{*}
\]

Note how $\Nil{*}$ replaces any missing values.
This example type checks because $\Nil{*}$ produces as many $\Nil$
values as we need, and $\Nil$ is consistent with $\String \cup \Nil$,
which is the type of $z$.

Conversely, the assignment
\[
x = 1, ``foo"
\]
type checks because
\[
1 \times ``foo" \times \Nil{*} \lesssim \Integer \times \Value{*}
\]

Note how $\Value{*}$ discards extra values.
This example type checks because $\Value{*}$ discards as many extra
values as we need, and $``foo"$ is consistent with $\Value$.

Rules for function applications are similar to the rule for multiple assignment.
The rule \textsc{T-APPLY1} handles the case where function applications
are expressions that produce multiple values:
\[
\begin{array}{c}
\mylabel{T-APPLY1}\\
\dfrac{\env_{1}, \penv \vdash e:S_{1} \rightarrow S_{2}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash el:S_{3}, \env_{3} \;\;\;
       S_{3} \lesssim S_{1}}
      {\env_{1}, \penv \vdash e(el):S_{2}, \env_{3}}
\end{array}
\]

We also use the rule \textsc{T-APPLY1} as the base case for the rules
that handle the cases where function applications are either statements
that produce no value or expressions that produce only one value.
The rule \textsc{T-STMAPPLY1} discards the produced values,
while the rule \textsc{T-EXPAPPLY1} uses the auxiliary function
\emph{proj} to ensure that only the first value is produced:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{T-STMAPPLY1}\\
\dfrac{\env_{1}, \penv \vdash e(el):S, \env_{2}}
      {\env_{1}, \penv \vdash \lfloor e(el) \rfloor_{0},\env_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{T-EXPAPPLY1}\\
\dfrac{\env_{1}, \penv \vdash e(el):S, \env_{2}}
      {\env_{1}, \penv \vdash \lfloor e(el) \rfloor_{1}:proj(S,1), \env_{2}}
\end{array}
\end{array}
\]

We can define \emph{proj} inductively as follows:
\begin{align*}
proj(S_1 \sqcup S_2, i) & = proj(S_1, i) \cup proj(S_2, i) \\
proj(F{*}, i) & = nil(F) \\
proj(F \times P, 1) & = F \\
proj(F \times P, i) & = proj(P, i-1)\\
proj(E{*}, i) & = nil(E) \\
proj(T \times E, 1) & = T \\
proj(T \times E, i) & = proj(E, i-1) \\
nil(T) & = \left\{
\begin{array}{ll}
T & \text{if $\Nil \lesssim T$} \\
T \cup \Nil & \text{otherwise}
\end{array} \right.
\end{align*}

As an example, let us assume that $f$ is a local function in the environment,
and that $f$ has type $\String \times (\Integer \cup \Nil) \times (\Integer \cup \Nil) \times \Value{*} \rightarrow \Integer{*}$.
The function call
\[
f(``foo")
\]
type checks through the rule \textsc{T-APPLY1}, because
\[
``foo" \times \Nil{*} \lesssim \String \times (\Integer \cup \Nil) \times (\Integer \cup \Nil) \times \Value{*}
\]
and the function call
\[
f(``foo",1,2,3)
\]
also type checks through the rule \textsc{T-APPLY1}, because
\[
``foo" \times 1 \times 2 \times 3 \times \Nil{*} \lesssim \String \times (\Integer \cup \Nil) \times (\Integer \cup \Nil) \times \Value{*}
\]

Our type system also catches arity mismatch.
To do that, we end the input type of a function with type $\Nil{*}$
instead of $\Value{*}$.
For instance, let us assume that $f$ has type
$\String \times (\Integer \cup \Nil) \times (\Integer \cup \Nil) \times \Nil{*} \rightarrow \Integer{*}$.
The function call
\[
f(``foo")
\]
type checks through the rule \textsc{T-APPLY1}, because
\[
``foo" \times \Nil{*} \lesssim \String \times (\Integer \cup \Nil) \times (\Integer \cup \Nil) \times \Nil{*}
\]
but the function call
\[
f(``foo",1,2,3)
\]
does not type check through the rule \textsc{T-APPLY1}, because
\[
``foo" \times 1 \times 2 \times 3 \times \Nil{*} \not\lesssim \String \times (\Integer \cup \Nil) \times (\Integer \cup \Nil) \times \Nil{*}
\]

We just mentioned that when our type system type checks an expression list,
it always includes $\Nil{*}$ in the end of the type of this expression list
if its type does not end in a variadic type.
This behavior preserves the semantics of Lua on replacing missing values,
and it is necessary when we omit optional parameters in a function call,
like the previous example showed.

Using $\Nil{*}$ in the end of the type of expression lists also allows
our type system to catch arity mismatch in function calls without optional parameters.
For instance, let us assume that $f$ has type
$\Integer \times \Integer \times \Nil{*} \rightarrow \Integer \times \Nil{*}$.
The function call
\[
f(1)
\]
does not type check through the rule \textsc{T-APPLY1}, because
\[
1 \times \Nil{*} \not\lesssim \Integer \times \Integer \times \Nil{*}
\]
and the function call
\[
f(1,2,3)
\]
also does not type check through the rule \textsc{T-APPLY1}, because
\[
1 \times 2 \times 3 \times \Nil{*} \not\lesssim \Integer \times \Integer \times \Nil{*}
\]

\subsection*{Tables and refinement}
\label{sec:refinement}

Our abstract syntax reduces the syntactic forms of the table constructor
into two forms: $\{\;\overline{[e_{1}] = e_{2}}\;\}$ and
$\{\;\overline{[e_{1}] = e_{2}},me\;\}$.
The first uses a list of table fields $([e_{1}] = e_{2})_{1}, ..., ([e_{1}] = e_{2})_{n}$.
The second uses a list of table fields and an expression that can
produce multiple values.

The simplest expression involving tables is the empty table constructor $\{\}$;
it always has type $\{\}_{unique}$.

As a more interesting example, let us see how our type system type checks
the table constructor $\{ [1] = ``x", [2] = ``y", [3] = ``z" \}$.

First, Typed Lua uses the auxiliary relation
$\env_{1}, \penv \vdash [e_{1}] = e_{2} : (F,V), \env_{2}$ to type check each
table field.
This auxiliary relation means that given a type environment $\env_{1}$
and a projection environment $\penv$, checking a table field $[e_{1}] = e_{2}$
produces a pair $(F,V)$ and a new type environment $\env_{2}$.
A pair $(F,V)$ means that $e_{1}$ has type $F$ and $e_{2}$ has type $V$,
where $F$ is the type of the key and $V$ is the type of the field value.

After type checking each table field, our type system uses each pair $(F,V)$
to build the table type that express the type of a given constructor, and
uses the predicate \emph{wf} to check whether this table type is well-formed.
The predicate \emph{wf} also uses the auxiliary predicate \emph{tag} to
forbid \emph{unique} and \emph{open} fields.
Formally, we can define \emph{wf} inductivelly as follows:
\[
\begin{array}{rcl}
wf(\{\overline{F:V}\}_{unique|open|fixed|closed}) & = & \forall i \; ((\nexists j \; i \not= j \,\wedge\, F_{i} \lesssim F_{j}) \,\wedge\, wf(V_{i}) \,\wedge\\
& & \;\;\;\; \lnot tag(V_{i},unique) \,\wedge\, \lnot tag(V_{i},open))\\
wf({\bf const}\; F) & = & wf(F) \\
wf(F_1 \cup F_2) & = & wf(F_1) \,\wedge\, wf(F_2) \\
wf(\mu x.F) & = & wf(F) \\
wf(S_1 \rightarrow S_2) & = & wf(S_1) \,\wedge\, wf(S_2) \\
wf(S_1 \sqcup S_2) & = & wf(S_1) \,\wedge\, wf(S_2)\\
wf(F{*}) &=& wf(F) \\
wf(F \times P) &=& wf(F) \,\wedge\,wf(P)\\
wf(F) & = & \top \;\;\;\mathrm{for\; all\; other\; cases}
\end{array}
\]

Well-formed table types avoid ambiguity.
For instance, this rule detects that the table type
$\{1:\Number, \Integer:\String, \Any:\Boolean\}$ is ambiguous,
because the type of the value stored by key $1$ can be
$\Number$, $\String$, or $\Boolean$, as $1 \lesssim 1$,
$1 \lesssim \Integer$, and $1 \lesssim \Any$.
Moreover, the type of the value stored by a key of type $\Integer$,
which is not the literal type $1$, can be $\Number$ or $\Boolean$,
as $\Integer \lesssim \Integer$, and $\Integer \lesssim \Any$.

Well-formed table types also do not allow \emph{unique} and
\emph{open} table types to appear in the type of the field values.
We made this restriction because our type system does not keep
track of aliases to table fields.
This means that allowing \emph{unique} and \emph{open} table
types to appear in the type of a value would allow the
creation of unsafe aliases.
Due to this restriction, the rule that type check table fields
use the auxiliary function \emph{fix} (in the definition of \emph{vt})
to change any \emph{unique} and \emph{open} table types
used in the field initializer to \emph{fixed}.
Rule \textsc{T-FIELD} defines this behavior:
\[
\begin{array}{c}
\mylabel{T-FIELD}\\
\dfrac{\env_{1}, \penv \vdash e_{2}:V, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{1}:F, \env_{3}}
      {\env_{1}, \penv \vdash [e_{1}] = e_{2}: (F,vt(F,V)), \env_{3}}
\end{array}
\]

The rule \textsc{T-FIELD} uses the auxiliary function \emph{vt}
to adjust the type of the value according to the type of the key.
More precisely, \emph{vt} includes the type $\Nil$ in the type of
the value when the type of the key is not a literal type.
It also uses \emph{fix} to prevent \emph{unique} and \emph{open}
table types to appear in the type of the field values.
We define these functions as follows:
\begin{align*}
vt(L, V) & = fix(V) \\
vt(F_1, F_2) & = nil(fix(F_2))\\
vt(F_1, {\bf const}\;F_2) & = {\bf const}\;nil(fix(F_2))\\
\\
fix(F_{1} \cup F_{2}) & = fix(F_{1}) \cup fix(F_{2})\\
fix(\{\overline{F{:}V}\}_{unique|open}) & = \{\overline{F{:}V}\}_{fixed} \\
fix(F) & = F
\end{align*}

The rule \textsc{T-CONSTRUCTOR1} uses these steps to type check a
table constructor with a list of table fields that do not end with
an expression that potentially returns multiple values:
\[
\begin{array}{c}
\mylabel{T-CONSTRUCTOR1}\\
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash ([e_{1}] = e_{2})_{i}:(F_{i},V_{i}), \env_{i+1} \;\;\;
       T = \{F_{1}{:}V_{1}, ..., F_{n}{:}V_{n}\}_{unique} \\
       wf(T) \;\;\;
       n = |\;\overline{[e_{1}] = e_{2}}\;| \;\;\;
       \env_{f} = merge(\env_{1}, ..., \env_{n+1})
       \end{array}}
      {\env_{1}, \penv \vdash \{\;\overline{[e_{1}] = e_{2}}\;\}:T, \env_{f}}
\end{array}
\]

Back to our example, the constructor
$\{ [1] = ``x", [2] = ``y", [3] = ``z" \}$ has type
$\{1:``x", 2:``y", 3:``z"\}_{unique}$ through rule \textsc{T-CONSTRUCTOR1}.
The subtyping rule for \emph{unique} table types allows us assigning
this table to a variable with a more general type such as
$\{1:\String, 2:\String, 3:\String\}_{closed}$ or even
$\{\Integer:\String \cup \Nil\}_{closed}$.

As another example, the constructor $\{[``x"] = 1, [``y"] = \{[``z"] = 2\}\}$
has type $\{``x":1, ``y":\{``z":2\}_{fixed}\}_{unique}$ through rule
\textsc{T-CONSTRUCTOR1}.
The inner table is \emph{fixed} to prevent the creation of unsafe aliases.

After presenting some typing rules of the table constructor,
we start the discussion of the rules that define the most
unusual feature of our type system: the refinement of table types.
The first kind of refinement allows programmers to add new
fields to \emph{unique} or \emph{open} table types through
field assignment.
For instance, in Section \ref{sec:tables} we presented the
following example:
\begin{verbatim}
    local person = {}
    person.firstname = "Lou"
    person.lastname = "Reed"
\end{verbatim}

We can translate this example to our reduced core as follows:
\begin{center}
\begin{tabular}{ll}
\multicolumn{2}{l}{$\mathbf{local} \; person = \{\} \; \mathbf{in}$}\\
& \multicolumn{1}{l}{$person[``firstname"] \; {<}\String{>} = ``Lou";$}\\
& \multicolumn{1}{l}{$person[``lastname"] \; {<}\String{>} = ``Reed"$}
\end{tabular}
\end{center}

In this example, we assign the type $\{\}_{unique}$ to the variable
$person$, then we refine its type to $\{``firstname":\String\}_{unique}$,
and then we refine its type to $\{``firstname":\String, ``lastname":\String\}_{unique}$.
Rule \textsc{T-REFINE1} type checks this use of refinement:
\[
\begin{array}{c}
\mylabel{T-REFINE1}\\
\dfrac{\begin{array}{c}
       \env_{1}(id) = \{\overline{F{:}V}\}_{unique}\\
       \env_{1}, \penv \vdash e:F_{new}, \env_{2} \;\;\;
       \nexists i \in 1..n \; F_{new} \lesssim F_{i} \;\;\;
       V_{new} = vt(F_{new},V) \;\;\; n = |\overline{F{:}V}|
       \end{array}}
      {\env_{1}, \penv \vdash id[e] {<}V{>}:V_{new}, \env_{2}[id \mapsto \{\overline{F{:}V}, F_{new}{:}V_{new}\}_{unique}]}
\end{array}
\]

The rule for refining \emph{open} table types is similar,
changing only the tag in the type of $id$:
\[
\begin{array}{c}
\mylabel{T-REFINE2}\\
\dfrac{\begin{array}{c}
       \env_{1}(id) = \{\overline{F{:}V}\}_{open}\\
       \env_{1}, \penv \vdash e:F_{new}, \env_{2} \;\;\;
       \nexists i \in 1..n \; F_{new} \lesssim F_{i} \;\;\;
       V_{new} = vt(F_{new},V) \;\;\; n = |\overline{F{:}V}|
       \end{array}}
      {\env_{1}, \penv \vdash id[e] {<}V{>}:V_{new}, \env_{2}[id \mapsto \{\overline{F{:}V}, F_{new}{:}V_{new}\}_{open}]}
\end{array}
\]

Our type system also includes analogous rules for adding methods
to \emph{unique} and \emph{open} tables as a side-effect of
type checking a method declaration, but we will not discuss them
in this section for brevity.

We use the refinement of table types to handle the declaration of
new global variables.
In Lua, the assignment \texttt{v = v + 1} translates to the statement
\texttt{\string_ENV["v"] = \string_ENV["v"] + 1} when \texttt{v}
is not a local variable, where \texttt{\string_ENV} is a table
that stores the global environment.
For this reason, Typed Lua treats accesses to global variables as field accesses
to an \emph{open} table in the top-level scope.
In the following examples we assume that $\string_ENV$ is in the
environment and has type $\{\}_{open}$.

As an example,
\[
\string_ENV[``x"] \; {<}\String{>} = ``foo" \;;\; \string_ENV[``y"] \; {<}\Integer{>} = 1
\]
uses field assignment to add fields $``x"$ and $``y"$ to $\string_ENV$.
Therefore, after these field assignments $\string_ENV$ has type
$\{``x":\String, ``y":\Integer\}_{open}$.

We do not allow the refinement of table types to add a field if it is
already present in the table's type.
For instance,
\[
\string_ENV[``x"] \; {<}\String{>} = ``foo" \;;\; \string_ENV[``x"] \; {<}\Integer{>} = 1
\]
does not type check, as we are trying to add $``x"$ twice.

We also do not allow the refinement of table types to introduce
fields with table types that are neither \emph{fixed} nor \emph{closed}.
For instance,
\begin{center}
\begin{tabular}{l}
$\string_ENV[``x"] \; {<}\{\}_{unique}{>} = \{\}$
\end{tabular}
\end{center}
refines the type of $\string_ENV$ from $\{\}_{open}$ to $\{``x":\{\}_{fixed}\}_{open}$.
Currently, our type system can only track \emph{unique} and
\emph{open} table types that are bound to local variables.

We can also use multiple assignment to refine table types:
\[
\string_ENV[``x"] \; {<}\String{>}, \string_ENV[``y"] \; {<}\Integer{>} = ``foo", 1
\]

This example type checks because all the environment changes are consistent, and
$``foo" \times 1 \times \Nil{*} \lesssim \String \times \Integer \times \Value{*}$.
By consistent we mean that we are only adding new fields.
More precisely, the first coercion expression refines the type of $\string_ENV$
to $\{``x":\String\}_{open}$, while
the second coercion expression refines the type of $\string_ENV$
to $\{``y":\Integer\}_{open}$.
Merging the two yields $\{``x":\String, ``y":\Integer\}_{open}$.
Nevertheless, the next example does not type check because it tries to add
the same field to $\string_ENV$, but with different types:
\[
\string_ENV[``x"] \; {<}\String{>}, \string_ENV[``x"] \; {<}\Integer{>} = ``foo", 1
\]

Aliasing an \emph{unique} or an \emph{open} table type can produce
either a \emph{closed} or a \emph{fixed} table type, depending on
the context that we are using a variable.
As we mentioned in Sections \ref{sec:oop} and \ref{sec:subtyping},
we need \emph{fixed} table types to type classes in object-oriented programming.
In the implementation we fix the aliasing of \emph{unique} and \emph{open}
table types that appear in a top-level return statement, and in other cases we
close the aliasing of \emph{unique} and \emph{open} table types.
However, in the formalization we chose to define this behavior in
a not deterministic way, as it makes easier the presentation of this behavior.

As an example,
\begin{center}
\begin{tabular}{lll}
\multicolumn{3}{l}{$\mathbf{local} \; a:\{\}_{unique} = \{\} \; \mathbf{in}$}\\
& \multicolumn{2}{l}{$\mathbf{local} \; b:\{\}_{open} = a \; \mathbf{in}$}\\
& & \multicolumn{1}{l}{$a[``x"] \; {<}\String{>} = ``foo";$}\\
& & \multicolumn{1}{l}{$b[``x"] \; {<}\Integer{>} = 1$}\\
\end{tabular}
\end{center}
does not type check, as aliasing $a$ produces the type $\{\}_{closed}$
that is not a subtype of $\{\}_{open}$, the type of $b$.
Our type system has this behavior to warn programmers about
potential unsafe behaviors after this kind of alias.
In this example, it is unsafe to add the field $``x"$ to $b$,
as it changes the value that is stored in the field $``x"$ of $a$.

Rules \textsc{T-IDREAD1} and \textsc{T-IDREAD2} define this non-deterministic behavior.
Rule \textsc{T-IDREAD1} uses the auxiliary function \emph{close} to
produce a \emph{closed} alias.
It also uses the auxiliary function \emph{open} to change the type of
the original reference from \emph{unique} to \emph{open},
because aliasing an \emph{unique} table type while keeping the original
reference \emph{unique} can be unsafe.
Rule \textsc{T-IDREAD2} uses the auxiliary function \emph{fix} to
produce a \emph{fixed} alias.
It also uses \emph{fix} to change the type of the original reference
to \emph{fixed}, because a \emph{fixed} table type does not allow
width subtyping.
We define these rules as follows:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{T-IDREAD1}\\
\dfrac{\env_{1}(id) = F}
      {\env_{1}, \penv \vdash id:close(F), \env_{1}[id \mapsto open(F)]}
\end{array}
\\ \\
\begin{array}{c}
\mylabel{T-IDREAD2}\\
\dfrac{\env_{1}(id) = F}
      {\env_{1}, \penv \vdash id:fix(F), \env_{1}[id \mapsto fix(F)]}
\end{array}
\end{array}
\]

We do not need to close \emph{unique} and \emph{open} tables that
appear in the left-hand side of assignments, because \textsc{T-IDREAD1}
and \textsc{T-IDREAD2} are sufficient to forbid the creation of an alias
to another \emph{unique} or \emph{open} table.
For this reason, identifiers that appear in the left-hand side
of assignments have their own rule \textsc{T-IDWRITE1}:
\[
\begin{array}{c}
\mylabel{T-IDWRITE1}\\
\dfrac{\env_{1}(id) = F}
      {\env_{1}, \penv \vdash id_{l}:F, \env_{1}}
\end{array}
\]

Our type system also has different rules for type checking table indexing to avoid
changing table types in these operations, as they cannot create aliases.
These rules also use the auxiliary function \emph{rconst} to strip the
$\Const$ type from the type of the value, if present.
We define these rules as follows:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{T-INDEXREAD1}\\
\dfrac{\begin{array}{c}
       \env_{1}(id) = \{\overline{F{:}V}\} \;\;\;
       \env_{1}, \penv \vdash e_{2}:F, \env_{2} \;\;\;
       \exists i \in 1{..}n \; F \lesssim F_{i} \;\;\;
       n = |\overline{F{:}V}|
       \end{array}}
      {\env_{1}, \penv \vdash id[e_{2}]:rconst(V_{i}), \env_{2}}
\end{array}
\\ \\
\begin{array}{c}
\mylabel{T-INDEXREAD2}\\
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash e_{1}:\{\overline{F{:}V}\}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3} \;\;\;
       \exists i \in 1{..}n \; F \lesssim F_{i} \;\;\;
       n = |\overline{F{:}V}|
       \end{array}}
      {\env_{1}, \penv \vdash e_{1}[e_{2}]:rconst(V_{i}), \env_{3}}
\end{array}
\end{array}
\]

Rule \textsc{T-INDEXREAD1} defines the case where using an identifier
to index a table does not create an alias, while rule \textsc{T-INDEXREAD2}
defines the case for indexing expressions where the expression
denoting the table is not an identifier.
The rules for indexing left-hand values are similar to these rules,
except that they ensure that the field is not $\Const$.

A second form of refinement happens when we want to use an
\emph{unique} or \emph{open} table type in a context that expects a
\emph{fixed} or \emph{closed} table type with a different shape.
This kind of refinement allows programmers to add optional fields
or merge existing fields.
To do that, Typed Lua includes a type coercion expression ${<}F{>} \; id$.
For instance, we can use this type coercion expression to make the following
example type check:
\begin{center}
\begin{tabular}{lll}
\multicolumn{3}{l}{$\mathbf{local} \; a:\{\}_{unique} = \{ \} \; \mathbf{in}$}\\
& \multicolumn{2}{l}{$a[``x"] \; {<}\String{>} = ``foo";$}\\
& \multicolumn{2}{l}{$a[``y"] \; {<}\String{>} = ``bar";$}\\
& \multicolumn{2}{l}{$\mathbf{local} \; b:\{``x":\String, ``y":\String \cup \Nil \}_{closed} =$}\\
& & \multicolumn{1}{l}{${<}\{``x":\String, ``y":\String \cup \Nil\}_{open}{>} \; a \; \mathbf{in} \; a[``z"] \; {<}\Integer{>} = 1$}
\end{tabular}
\end{center}

We can use $a$ to initialize $b$ because the coercion converts
the type of $a$ from $\{``x":\String, ``y":\String\}_{unique}$ to
$\{``x":\String, ``y":\String \cup \Nil\}_{open}$, and results in
$\{``x":\String, ``y":\String \cup \Nil\}_{closed}$,
which is a subtype of
$\{``x":\String, ``y":\String \cup \Nil\}_{closed}$, the type of $b$.
We can continue to refine the type of $a$ after aliasing it to $b$,
as it still holds an \emph{open} table.
At the end of this example, $a$ has type
$\{``x":\String, ``y":\String \cup \Nil, ``z":\Integer\}_{open}$.

Rules \textsc{T-COERCE1} and \textsc{T-COERCE2} define the behavior of the
type coercion expression:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{T-COERCE1}\\
\dfrac{\env_{1}(id) \subtype F \;\;\; tag(F,closed)}
      {\env_{1}, \penv \vdash {<}F{>} \; id:F, \env_{1}[id \mapsto reopen(F)]}
\end{array}
\;
\begin{array}{c}
\mylabel{T-COERCE2}\\
\dfrac{\env_{1}(id) \subtype F \;\;\; tag(F,fixed)}
      {\env_{1}, \penv \vdash {<}F{>} \; id:F, \env_{1}[id \mapsto F]}
\end{array}
\end{array}
\]

Note that the coercion rules only allow changing the type
of a variable if the new type is a supertype of the previous type,
and the resulting type is always \emph{fixed} or \emph{closed}
to prevent the creation of unsafe aliases.
If the coercion is to a \emph{closed} table type the type of the
table changes to an \emph{open} table type with the same shape,
but if the coercion is to a \emph{fixed} table type the table
has to assume the same type.

We also need to make sure to close all \emph{unique} and \emph{open}
table types before we type check a nested scope.
To do that, our type system uses some auxiliary functions to change
the type of variables before type checking a nested scope and
also to change the type of assigned and referenced variables after
type checking a nested scope.
The function \emph{closeall} closes all \emph{unique} and \emph{open} table types.
The function \emph{closeset} closes a given set of free assigned variables,
which is given by the function \emph{fav}.
The function \emph{openset} changes from \emph{unique} to \emph{open}
a given set of referenced variables, which is given by the function \emph{frv}.

As an example,
\begin{center}
\begin{tabular}{llll}
\multicolumn{4}{l}{$\mathbf{local} \; a:\{\}_{unique}, b:\{\}_{unique} = \{\}, \{\} \; \mathbf{in}$}\\
& \multicolumn{3}{l}{$\mathbf{local} \; f:\Integer \times \Nil{*} \rightarrow \Integer \times \Nil{*} =$}\\
& & \multicolumn{2}{l}{$\mathbf{fun} \; (x:\Integer):\Integer \times \Nil{*}$}\\
& & & \multicolumn{1}{l}{$b = a \;;\; \mathbf{return} \; x + 1$}\\
& \multicolumn{3}{l}{$\mathbf{in} \; a[``x"] \; {<}\Integer{>} = 1 \;;\; b[``x"] \; {<}\String{>} = ``foo" \;;\; \lfloor f(a[``x"]) \rfloor_{0}$}
\end{tabular}
\end{center}
does not type check because we cannot add the field
$``x"$ to $b$, as its type is closed.
The assignment $b = a$ type checks because, at that point,
$a$ and $b$ have the same type: $\{\}_{closed}$.
Their type was closed by \emph{closeall} before type checking
the function body.
Their type would be restored to $\{\}_{unique}$ after type checking
the function body, but that assignment also triggers other two type changes.
First, the function \emph{fav} includes $b$ in the set of variables
that should be closed by \emph{closeset}.
Then, the function \emph{frv} includes $a$ in the set of variables
that should change from \emph{unique} to \emph{open} by \emph{openset}.
After declaring $f$, $a$ has type $\{\}_{open}$ and $b$ has type $\{\}_{closed}$,
so we can refine the type of $a$, but we cannot refine the type of $b$.

Rule \textsc{T-FUNCTION1} types non-variadic function declarations,
and it illustrates this case:
\[
\begin{array}{c}
\mylabel{T-FUNCTION1}\\
\dfrac{\begin{array}{c}
       closeall(\env_{1})[\overline{id \mapsto F}], \penv[\ret \mapsto S] \vdash s, \env_{2} \\
       \env_{3} = openset(\env_{1}, frv(\mathbf{fun} \; (\overline{id{:}F}){:}S \; s)) \\
       \env_{4} = closeset(\env_{3}, fav(\mathbf{fun} \; (\overline{id{:}F}){:}S \; s))
       \end{array}}
      {\env_{1}, \penv \vdash \mathbf{fun} \; (\overline{id{:}F}){:}S \; s:F_{1} \times ... \times F_{n} \times \Nil{*} \rightarrow S, \env_{4}}
\end{array}
\]

This rule also extends the environment $\penv$, bounding the special
variable $\ret$ to the return type $S$.
Rule \textsc{T-RETURN} uses the type that is bound to $\ret$ in
$\penv$ to type check return statements:
\[
\begin{array}{c}
\mylabel{T-RETURN}\\
\dfrac{\env_{1} \vdash el:S_{1}, \env_{2} \;\;\;
       \penv(\ret) = S_{2} \;\;\;
       S_{1} \lesssim S_{2}}
      {\env_{1} \vdash \mathbf{return} \; el, \env_{2}}
\end{array}
\]

The rules for declaring variadic functions and recursive functions
are similar to \textsc{T-FUNCTION1}, and we did not discuss them in
this section for brevity.

\subsection*{Projections}
\label{sec:fap}

Lua programmers often overload the return type of functions to denote errors,
returning \texttt{nil} and an error message in case of error instead of
the usual return values, and our type system uses projection types to handle this idiom.

As an example, let us assume that \emph{idiv} and \emph{print} are functions
in the environment.
As we mentioned in Section \ref{sec:unions}, \emph{idiv} performs
integer division and has type
\[
\Integer \times \Integer \times \Nil{*} \rightarrow (\Integer \times \Integer \times \Nil{*}) \sqcup (\Nil \times \String \times \Nil{*})
\]
In case of success, it returns two integers: the result and the remainder.
In case of failure, it returns $\Nil$ plus an error message that describes
the error.
The function \emph{print} is a variadic function of type
$\Value{*} \rightarrow \Nil{*}$.
Let us also assume that $a$ and $b$ are local variables in the environment,
and that both have type $\Integer$.
Let us see how our type system type checks the following program:
\begin{center}
\begin{tabular}{ll}
\multicolumn{2}{l}{$\mathbf{local} \; q, r = idiv(a, b) \; \mathbf{in}$}\\
& \multicolumn{1}{l}{$\mathbf{if} \; q \; \mathbf{then} \; \lfloor print(q + r) \rfloor_{0} \; \mathbf{else} \; \lfloor print(``ERROR: " \; .. \; r) \rfloor_{0}$}
\end{tabular}
\end{center}

First, our type system uses the auxiliary relation
$\env_{1}, \penv \vdash el : E, \env_{2}, (x,S)$
for type checking $idiv(a, b)$.
This relation means that given a type environment $\env_{1}$ and
a projection environment $\penv$, we can check that an expression
list $el$ has type $E$ and produces a new type environment $\env_{2}$
and produces a pair $(x,S)$.
This pair means that the last expression of an expression list $el$
produces an union of second-level types $S$ that should be bound
to a fresh variable $x$ in the projection environment $\penv$,
as the resulting type of this expression is a tuple of projection
types $\pi_{i}^{x}$.
In our example, our type system uses rule \textsc{T-EXPLIST3} for
type checking $idiv(a, b)$:
\[
\begin{array}{c}
\mylabel{T-EXPLIST3}\\
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash e_{i}:F_{i}, \env_{i+1} \;\;\;
       \env_{1}, \penv \vdash me:S, \env_{n+2}\\
       S = F_{n+1} \times ... \times F_{n+m} \times \Nil{*} \sqcup F_{n+1}' \times ... \times F_{n+m}' \times \Nil{*} \\
       \env_{f} = merge(\env_{1}, ..., \env_{n+2}) \;\;\;
       n = |\;\overline{e}\;|
       \end{array}}
      {\env_{1}, \penv \vdash \overline{e},me:F_{1} \times ... \times F_{n} \times \pi_{1}^{x} \times ... \times \pi_{m}^{x} \times \Nil{*}, \env_{f}, (x,S)}
\end{array}
\]

Note that $idiv(a, b)$ has type
$\pi_{1}^{x} \times \pi_{2}^{x} \times \Nil{*}$ and produces the pair
\[
(x,(\Integer \times \Integer \times \Nil{*}) \sqcup (\Nil \times \String \times \Nil{*}))
\]

In the rule that type checks the declaration of unannotated variables,
our type system uses the pair $(x,S)$ to bound a union of
second-level types $S$ to a variable $x$ in the projection
environment $\penv$.
In our example, declaring $q$ and $r$
bounds the projection type $\pi_{1}^{x}$ to $q$ and
bounds the projection type $\pi_{2}^{x}$ to $r$,
where the projection variable $x$ bounds to
\[
(\Integer \times \Integer \times \Nil{*}) \sqcup (\Nil \times \String \times \Nil{*})
\]
in the projection environment $\penv$.
Rule \textsc{T-LOCAL2} illustrates this intuition:
\[
\begin{array}{c}
\mylabel{T-LOCAL2}\\
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash el:E, \env_{2}, (x,S)\\
       \env_{3} = \env_{2}[id_{1} \mapsto infer(E,1), ..., id_{n} \mapsto infer(E,n)] \\
       \env_{3}, \penv[x \mapsto S] \vdash s, \env_{4} \;\;\;
       n = |\;\overline{id}\;|
       \end{array}}
      {\env_{1}, \penv \vdash \mathbf{local} \; \overline{id} = el \; \mathbf{in} \; s, (\env_{4} - \{\overline{id}\})[\overline{id \mapsto \env_{2}(id)}]}
\end{array}
\]

This rule uses the auxiliary function \emph{infer} to get the
most general types of each variable that should be introduced in
the type environment for type checking $s$.
After type checking the statement $s$, rule \textsc{T-LOCAL2} produces a
new type environment $\env_{4}$ without the variables that it introduced
before type checking $s$.
We can define \emph{infer} as follows:
\begin{align*}
infer(T_{1} \times ... \times T_{n}{*}, i) & = \left\{
\begin{array}{ll}
general(T_{i}) & \text{if $i < n$}\\
general(nil(T_{n})) & \text{if $i >= n$}
\end{array} \right.
\end{align*}

\begin{align*}
general(\False) & = \Boolean\\
general(\True) & = \Boolean\\
general({\it int}) & = \Integer\\
general({\it float}) & = \Number\\
general({\it string}) & = \String\\
general(F_{1} \cup F_{2}) & = general(F_{1}) \cup general(F_{2})\\
general(S_{1} \rightarrow S_{2}) & = general2(S_{1}) \rightarrow general2(S_{2})\\
general(\{F_{1}{:}V_{1}, ..., F_{n}{:}V_{n}\}_{tag}) & = \{F_{1}{:}general(V_{1}), ..., F_{n}{:}general(V_{n})\}_{tag}\\
general(\mu x.F) & = \mu x.general(F)\\
general(T) & = T\\
\\
general2(F{*}) & = general(F){*}\\
general2(F \times P) & = general(F) \times general2(P)\\
general2(S_{1} \sqcup S_{2}) & = general2(S_{1}) \sqcup general2(S_{2})
\end{align*}

After assigning projection types to $q$ and $r$, reading $q$ will
use the projection type $\pi_{1}^{x}$ to project the type of $q$
into the union type $\Integer \cup \Nil$, while reading $r$ will
use the projection type $\pi_{2}^{x}$ to project the type of $r$
into the union type $\Integer \cup \String$.
Our type system defines this behavior through rule \textsc{T-IDREAD4},
which uses the auxiliary function \emph{proj} to project an
union of second-level types into an union of first-level types:
\[
\begin{array}{c}
\mylabel{T-IDREAD4}\\
\dfrac{\env_{1}(id) = \pi_{i}^{x}}
      {\env_{1}, \penv \vdash id:proj(\penv(x), i), \env_{1}}
\end{array}
\]

Now, we may want to discriminate $q$ and $r$ to check whether
the function call returned with success.
Introducing a projection variable $x$ in the projection environment allows our
type system to discriminate projection types $\pi_{i}^{x}$,
as they are a general way to not compromise the dependency between
the types of $q$ and $r$ after discriminating one of them,
so flow typing can narrow the type of both variables by testing
just one of them because the projection types of both variables
bound to the same projection variable.

The rule \textsc{T-IF5} shows the case where our type system
discriminates a projection type based on the tag \texttt{nil}.
It uses the auxiliary functions \emph{fopt} and \emph{fipt}
to filter a projection $x$, affecting all variables that bind to the same projection.
More precisely, the former function filters out the tuples that contain a type $F$ in the $i$-th component,
while the latter function filters out the tuples that do not contain $F$ in the $i$-th component.
We define \textsc{T-IF5} as follows:
\[
\begin{array}{c}
\mylabel{T-IF5}\\
\dfrac{\begin{array}{c}
       \env_{1}(id) = \pi_{i}^{x} \\
       S_{t} = fopt(\penv(x), \Nil, i) \;\;\;
       S_{e} = fipt(\penv(x), \Nil, i) \\
       \env_{1}, \penv[x \mapsto S_{t}] \vdash s_{1}, \env_{2}\\
       \env_{1}, \penv[x \mapsto S_{e}] \vdash s_{2}, \env_{3}\\
       \env_{4} = join(\env_{2}, \env_{3})
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; id \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{4}}
\end{array}
\]

Our previous example type checks through rule \textsc{T-IF5},
because it uses the information provided by the projection type $\pi_{1}^{x}$,
which is the type of $q$, to make the rule \textsc{T-IF5} use the function call
\[
fopt((\Integer \times \Integer \times \Nil{*}) \sqcup (\Nil \times \String \times \Nil{*}), \Nil, 1)
\]
to discriminate the projection $x$ to the single tuple
$\Integer \times \Integer \times \Nil{*}$ inside the $\mathbf{if}$ branch,
and the function call
\[
fipt((\Integer \times \Integer \times \Nil{*}) \sqcup (\Nil \times \String \times \Nil{*}), \Nil, 1)
\]
to discriminate the projection $x$ to the single tuple
$\Nil \times \String \times \Nil{*}$ inside the $\mathbf{else}$ branch.
Thus, reading $q$ and $r$ projects $\pi_{1}^{x}$ to $\Integer$ and
$\pi_{2}^{x}$ to $\Integer$ inside the $\mathbf{if}$ branch,
but it projects $\pi_{1}^{x}$ to $\Nil$ and $\pi_{2}^{x}$ to $\String$
inside the $\mathbf{else}$ branch.
Outside the condition, $q$ and $r$ use the original projection, that is,
they project to $\Integer \cup \Nil$ and $\Integer \cup \String$, respectively.

Our type system also includes rules that check whether a branch is unreachable.
Rules \textsc{T-IF6} and \textsc{T-IF7} respectively cover the case where the
$\mathbf{else}$ branch is unreachable and the case where the $\mathbf{then}$
branch is unreachable, because either the projected type of $\pi_{i}^{x}$ is
not a supertype of $\Nil$ or it is $\Nil$.
We define these rules as follows:
\[
\begin{array}{c}
\begin{array}{c}
\mylabel{T-IF6}\\
\dfrac{\begin{array}{c}
       \env_{1}(id) = \pi_{i}^{x} \\
       S_{t} = fopt(\penv(x), \Nil, i) \\
       fit(proj(\penv(x), i), \Nil) = \Void \\
       \env_{1}, \penv[x \mapsto S_{t}] \vdash s_{1}, \env_{2}
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; id \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{2}}
\end{array}
\;
\begin{array}{c}
\mylabel{T-IF7}\\
\dfrac{\begin{array}{c}
       \env_{1}(id) = \pi_{i}^{x} \\
       S_{e} = fipt(\penv(x), \Nil, i) \\
       fot(proj(\penv(x), i), \Nil) = \Void \\
       \env_{1}, \penv[x \mapsto S_{e}] \vdash s_{2}, \env_{2}
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; id \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{2}}
\end{array}
\end{array}
\]

Typed Lua does not allow assignments to left-hand values that are bound
to a projection type.
This kind of assignment would be unsound, because it could break the
dependency relation that the components of each tuple of the union have.
For instance, the following example does not type check:
\begin{center}
\begin{tabular}{ll}
\multicolumn{2}{l}{$\mathbf{local} \; q, r = idiv(a, b) \; \mathbf{in}$}\\
& \multicolumn{1}{l}{$r = ``foo";$}\\
& \multicolumn{1}{l}{$\mathbf{if} \; q \; \mathbf{then} \; \lfloor print(q + r) \rfloor_{0} \; \mathbf{else} \; \lfloor print(``ERROR: " \; .. \; r) \rfloor_{0}$}
\end{tabular}
\end{center}

In this example, the projected type of $r$ outside of the $\mathbf{if}$
statement is $\Integer \cup \String$, so the assignment looks fine.
However, the projected type of $r$ inside the $\mathbf{if}$ branch is $\Integer$,
not matching the $\String$ value that $r$ has after the assignment.


\subsection{1-D test case}
\begin{frame}
\frametitle{Fixed source}
Comparison between $SP_3$ and Diffusion solutions of the scalar flux.

\begin{columns}

    \column[t]{5cm}
	\begin{figure}[htbp!]
		\begin{center}
			\includegraphics[height=4cm]{figures/output-1g-fixed}
		\end{center}
		\caption{1 group.}
	\end{figure}

	\column[t]{5cm}
	\begin{figure}[htbp!]
		\begin{center}
			\includegraphics[height=4cm]{figures/output-3g-fixed}
		\end{center}
		\caption{3 groups.}
	\end{figure}
\end{columns}
\end{frame}

\begin{frame}
\frametitle{Eigenvalue problem}

Comparison between $SP_3$ and Diffusion solutions of the scalar flux.
Solutions are normalized to the maximum value of the flux (fast flux for the 3 group case).

\begin{columns}
    \column[t]{5cm}
	\begin{figure}[htbp!]
		\begin{center}
			\includegraphics[height=4cm]{figures/output-1g-crit}
		\end{center}
		\caption{1 group.}
	\end{figure}

	\column[t]{5cm}
	\begin{figure}[htbp!]
		\begin{center}
			\includegraphics[height=4cm]{figures/output-3g-crit}
		\end{center}
		\caption{3 groups.}
	\end{figure}
\end{columns}
\end{frame}

\subsection{2-D test case}
\begin{frame}
\frametitle{C5G2 MOX Benchmark}
	\begin{table}[htbp!]
	\centering
	\begin{tabular}{lccc}
	\toprule
	 & C5G2 Benchmark      & \multicolumn{2}{c}{SP3}          \\
	\midrule
	Case & $k_{Ref}$       & $k_{SP_3}$ & $\Delta_\rho$ [pcm] \\
	\midrule
	Heterogeneous & 0.96969  & 0.97106  & 145  \\
	Homogeneous   & 0.96983  & 0.97061  &  83  \\
	\bottomrule
	\end{tabular}
	\label{tab:2d-keff}
	\end{table}
\end{frame}

\begin{frame}
\frametitle{C5G2 MOX Benchmark (2)}
	\begin{figure}[htbp!]
		\begin{center}
			\includegraphics[height=5cm]{{figures/output-2g}}
		\end{center}
		\caption{Comparison of the heterogenous and homogeneous cases scalar flux.}
	\end{figure}
\end{frame}

\begin{frame}
\begin{columns}
\frametitle{C5G2 MOX Benchmark (3)}

    \column[t]{5cm}
	\begin{figure}[htbp!]
		\begin{center}
			\includegraphics[height=4cm]{figures/flux0_1}
		\end{center}
		\caption{$\Phi_{0, 1}$.}
	\end{figure}

	\column[t]{5cm}
	\begin{figure}[htbp!]
		\begin{center}
			\includegraphics[height=4cm]{figures/flux0_2}
		\end{center}
		\caption{$\Phi_{0, 2}$.}
	\end{figure}
\end{columns}
\end{frame}

\begin{frame}
\frametitle{C5G2 MOX Benchmark (4)}
\begin{columns}
    \column[t]{5cm}
	\begin{figure}[htbp!]
		\begin{center}
			\includegraphics[height=4cm]{figures/flux2_1}
		\end{center}
		\caption{$\Phi_{2, 1}$.}
	\end{figure}

	\column[t]{5cm}
	\begin{figure}[htbp!]
		\begin{center}
			\includegraphics[height=4cm]{figures/flux2_2}
		\end{center}
		\caption{$\Phi_{2, 2}$.}
	\end{figure}
\end{columns}
\end{frame}


\chapter{Software Implementation}
\label{appendix:implementation}

The main software used in this thesis was written in Python version 2.7.13.
Rather than writing several individual scripts which each ran their own experiments, the software was written as a unified framework which would allow consistent use of data, rapid experimentation, and reuse of critical experimental code.
This experiment briefly describes some of the notable elements of the software.

\section{Experiment Specification Files}

Experiments are specified using the YAML data format, a human readable data serialization language.
To run an experiment, the user calls the main experiment running script and passes the specification file name as an argument.
The specification file fully defines the experiment(s) being run, to include the data format, model architecture, and training/testing procedure.
This has a number of advantages.
First, it ensures traceability from experimental conditions to results.
A copy of the experiment file is placed in the same directory of the experiment results, ensuring that any results from past experiments can be understood and interpreted appropriately.
Second, it allows rapid iteration of experimentation, since running a modified version of an experiment is requires a simple modification of the specification file.
Third, it allows concurrent researchers to review each others' work without having lengthy discussions about the precise experimental settings used.
For illustration, the contents of an example YAML file are shown below (for Sum Coupling, receptive field size 21, for one, two , three, and four layers):

\begin{minted}[frame=single, fontsize=\small]{yaml}
type: 'experimentset'
common:
  type: 'traintest'
  args:
    test_frequency: 80
    vis_frequency: 80
    test_before_train: True
    num_epochs: 80
    minibatch_size: 128
    test_batch_size: 2000
    checkpoint_frequency: 80
  data:
    dataset: "dbd5"
    train_list: ["train_list_w_2B42.yml", "validate_list.yml"]
    test_list: "test_list_w_3R9A.yml"
    n_train: -1
    n_test: -1
    train_ratio: 10
    test_ratio: -1
    nans: "global_median"
    features:
    - "WINDOWED_POSITION_SPECIFIC_SCORING_MATRIX"
    - "RELATIVE_ACCESSIBLE_SURFACE_AREA"
    - "RESIDUE_DEPTH"
    - "PROTRUSION_INDEX"
    - "HALF_SPHERE_EXPOSURE"
    - "RES_DIST_AVE"
    #- "RES_DIST_STD"
    - "ANGLE_CCAO"
    #- "ANGLE_HSAA_COS"
    feature_args:
      profile_params:
        window_size: 1
        blast-database: "/s/<host>/a/tmp/blastdb/db"
      distance_matrix:
        preprocess: ["gaussian_kernel", 18]
      angle_matrix:
        preprocess: "divide_pi"
    representation: "pairwise_data_per_protein_with_hood_indices"
  metrics:
    - "learning_rate"
    - "params"
    - "loss_train"
    - "loss_test"
    - "roc_train"
    - "roc_test"
    - "rfpp_train"
    - "rfpp_test"
  model:
    name: "PWClassifier"
    layer_args: {init: "he", coupling: "sum", bias_init: "zero",
        nonlin: "relu", dropout_keep_prob: 0.5}
    loss: "tf_weighted_crossent"
    loss_args:
      pn_ratio: 0.1
    optimizer: "tf_sgd"
    optimizer_args:
      learning_rate: 0.1
experiments:
- - "1_layer_rf20"
  - data:
      nhood_size: 20
    model:
      layers:
      - ["star_v_conv", {filters: 256}]
      - ["merge_gather_swap_paired_examples",
              {mode: ["concat"]}, ["merge"]]
      - ["dense", {out_dims: 512}]
      - ["dense", {out_dims: 1, nonlin: "linear"}]
      - ["combine_swapped"]
- - "2_layer_rf20"
  - data:
      nhood_size: 20
    model:
      layers:
      - ["star_v_conv", {filters: 256}]
      - ["star_v_conv", {filters: 512}]
      - ["merge_gather_swap_paired_examples",
              {mode: ["concat"]}, ["merge"]]
      - ["dense", {out_dims: 512}]
      - ["dense", {out_dims: 1, nonlin: "linear"}]
      - ["combine_swapped"]
- - "3_layer_rf20"
  - data:
      nhood_size: 20
    model:
      layers:
      - ["star_v_conv", {filters: 256}]
      - ["star_v_conv", {filters: 256}]
      - ["star_v_conv", {filters: 512}]
      - ["merge_gather_swap_paired_examples",
              {mode: ["concat"]}, ["merge"]]
      - ["dense", {out_dims: 512}]
      - ["dense", {out_dims: 1, nonlin: "linear"}]
      - ["combine_swapped"]
- - "4_layer_rf20"
  - data:
      nhood_size: 20
    model:
      layers:
      - ["star_v_conv", {filters: 256}]
      - ["star_v_conv", {filters: 256}]
      - ["star_v_conv", {filters: 512}]
      - ["star_v_conv", {filters: 512}]
      - ["merge_gather_swap_paired_examples",
              {mode: ["concat"]}, ["merge"]]
      - ["dense", {out_dims: 512}]
      - ["dense", {out_dims: 1, nonlin: "linear"}]
      - ["combine_swapped"]
\end{minted}

\section{Convolution Functions}

Because all convolution approaches used a similar neural network architecture, each layer type was implemented as a function, and the relevant function is named in the experiment specification file (for example, "star\_v\_conv" in the YAML code above).
Each layer function would receive as inputs the outputs of the previous layer(s), and any number of keyword arguments specific to that layer.
The layer would define any TensorFlow operations on the inputs that produce the layer's output.
Below is an example function implementing a convolutional layer, which is a simplified version of "star\_v\_conv" mentioned above.

\begin{minted}[frame=single, fontsize=\small]{python}
def star_v_conv(layer_input, filters, init, bias_init, nonlin,
                coupling, dropout_keep_prob, bias, **kwargs):
    # get inputs
    vertices, edges, nh_indices = layer_input
    v_shape = vertices.get_shape()
    e_shape = edges.get_shape()
    nh_size = nh_indices.get_shape()[1].value

    # create weights
    Wvc = tf.Variable(initializer(init, (v_shape[1].value, filters)))
    bv = tf.Variable(initializer(bias_init, (filters,)), name="bv")
    Wvn = tf.Variable(initializer(init, (v_shape[1].value, filters)))
    We = tf.Variable(initializer(init, (e_shape[2].value, filters)))

    # create central vertex signals
    Zc = tf.matmul(vertices, Wvc, name="Zc")

    # create neighbor signals
    e_We = tf.tensordot(edges, We, axes=[[2], [0]], name="e_We")
    v_Wvn = tf.matmul(vertices, Wvn, name="v_Wvn")
    if coupling == "sum":
        Zn = tf.divide(
             tf.reduce_sum(tf.gather(v_Wvn, nh_indices), 1) \\
             + tf.reduce_sum(e_We, 1), \\
             nh_size)
    elif coupling == "product":
        Zn = tf.divide(
             tf.reduce_sum(tf.gather(v_Wvn, nh_indices) \\
             * e_We, axis=1), \\
             nh_size)

    # signal
    sig = Zn + Zc
    if bias:
        sig += bv

    # pass through the nonlinearity
    z = tf.reshape(nonlin(sig), tf.constant([-1, filters]))

    # dropout
    z = tf.nn.dropout(z, dropout_keep_prob)
    return z

\end{minted}