From 8f3d49d70f3a2e7fe15da78f53e37eea17291f68 Mon Sep 17 00:00:00 2001 From: Andreas Stadelmeier Date: Wed, 27 Dec 2023 14:29:33 +0100 Subject: [PATCH] Initial commit. Applying LipICS style to wildcard paper --- TIforWildFJ.tex | 319 +++++++++++ cc-by.pdf | Bin 0 -> 58331 bytes conclusion.tex | 35 ++ constraints.tex | 337 ++++++++++++ introduction.tex | 222 ++++++++ lipics-logo-bw.pdf | Bin 0 -> 83561 bytes lipics-v2021.cls | 1260 ++++++++++++++++++++++++++++++++++++++++++++ martin.bib | 310 +++++++++++ orcid.pdf | Bin 0 -> 88694 bytes prolog.tex | 206 ++++++++ soundness.tex | 191 +++++++ unify.tex | 1080 +++++++++++++++++++++++++++++++++++++ 12 files changed, 3960 insertions(+) create mode 100644 TIforWildFJ.tex create mode 100644 cc-by.pdf create mode 100644 conclusion.tex create mode 100644 constraints.tex create mode 100644 introduction.tex create mode 100644 lipics-logo-bw.pdf create mode 100644 lipics-v2021.cls create mode 100644 martin.bib create mode 100644 orcid.pdf create mode 100755 prolog.tex create mode 100644 soundness.tex create mode 100644 unify.tex diff --git a/TIforWildFJ.tex b/TIforWildFJ.tex new file mode 100644 index 0000000..9f0bbad --- /dev/null +++ b/TIforWildFJ.tex @@ -0,0 +1,319 @@ + +\documentclass[a4paper,UKenglish,cleveref, autoref, thm-restate]{lipics-v2021} +%This is a template for producing LIPIcs articles. +%See lipics-v2021-authors-guidelines.pdf for further information. +%for A4 paper format use option "a4paper", for US-letter use option "letterpaper" +%for british hyphenation rules use option "UKenglish", for american hyphenation rules use option "USenglish" +%for section-numbered lemmas etc., use "numberwithinsect" +%for enabling cleveref support, use "cleveref" +%for enabling autoref support, use "autoref" +%for anonymousing the authors (e.g. for double-blind review), add "anonymous" +%for enabling thm-restate support, use "thm-restate" +%for enabling a two-column layout for the author/affilation part (only applicable for > 6 authors), use "authorcolumns" +%for producing a PDF according the PDF/A standard, add "pdfa" + +%\pdfoutput=1 %uncomment to ensure pdflatex processing (mandatatory e.g. to submit to arXiv) +%\hideLIPIcs %uncomment to remove references to LIPIcs series (logo, DOI, ...), e.g. when preparing a pre-final version to be uploaded to arXiv or another public repository + +%\graphicspath{{./graphics/}}%helpful if your graphic files are in another directory + +\usepackage[T1]{fontenc} + +\usepackage{cite} +\usepackage[disable]{todonotes} % [disable] +\usepackage[utf8]{inputenc} +\usepackage{hyperref} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{subcaption} +\usepackage{prftree} +\usepackage{tabularx} +\usepackage{multicol} +\usepackage{nicematrix} +\usepackage{tikz} +\usepackage{soul} +\newcommand{\mathcolorbox}[2]{\colorbox{#1}{$\displaystyle #2$}} +\usepackage{cancel} +\usepackage{tcolorbox} + +\input{prolog} + +\bibliographystyle{plainurl}% the mandatory bibstyle + +\title{Global Type Inference for Featherweight Java with Wildcards} %TODO Please add + +%\titlerunning{Dummy short title} %TODO optional, please use if title is longer than one line + +\author{Andreas Stadelmeier}{DHBW Stuttgart, Campus Horb, Germany}{a.stadelmeier@hb.dhbw-stuttgart.de}{}{}%TODO mandatory, please use full name; only 1 author per \author macro; first two parameters are mandatory, other parameters can be empty. Please provide at least the name of the affiliation and the country. The full address is optional. Use additional curly braces to indicate the correct name splitting when the last name consists of multiple name parts. + +\author{Martin Plümicke}{DHBW Stuttgart, Campus Horb, Germany}{pl@dhbw.de}{}{} + +\author{Peter Thiemann}{Universität Freiburg, Institut für Informatik, Germany}{thiemann@informatik.uni-freiburg.de}{}{} + +\authorrunning{A. Stadelmeier and M. Plümicke and P. Thiemann} %TODO mandatory. First: Use abbreviated first/middle names. Second (only in severe cases): Use first author plus 'et al.' + +\Copyright{Andreas Stadelmeier and Martin Plümicke and Peter Thiemann} %TODO mandatory, please use full first names. LIPIcs license is "CC-BY"; http://creativecommons.org/licenses/by/3.0/ + +\ccsdesc[500]{Software and its engineering~Language features} +%\ccsdesc[300]{Software and its engineering~Syntax} + +\keywords{type inference, Java, subtyping, generics} %TODO mandatory; please add comma-separated list of keywords + +\category{} %optional, e.g. invited paper + +\relatedversion{} %optional, e.g. full version hosted on arXiv, HAL, or other respository/website +%\relatedversiondetails[linktext={opt. text shown instead of the URL}, cite=DBLP:books/mk/GrayR93]{Classification (e.g. Full Version, Extended Version, Previous Version}{URL to related version} %linktext and cite are optional + +%\supplement{}%optional, e.g. related research data, source code, ... hosted on a repository like zenodo, figshare, GitHub, ... +%\supplementdetails[linktext={opt. text shown instead of the URL}, cite=DBLP:books/mk/GrayR93, subcategory={Description, Subcategory}, swhid={Software Heritage Identifier}]{General Classification (e.g. Software, Dataset, Model, ...)}{URL to related version} %linktext, cite, and subcategory are optional + +%\funding{(Optional) general funding statement \dots}%optional, to capture a funding statement, which applies to all authors. Please enter author specific funding statements as fifth argument of the \author macro. + +%\acknowledgements{I want to thank \dots}%optional + +%\nolinenumbers %uncomment to disable line numbering + + + +%Editor-only macros:: begin (do not touch as author)%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\EventEditors{John Q. Open and Joan R. Access} +\EventNoEds{2} +\EventLongTitle{42nd Conference on Very Important Topics (CVIT 2016)} +\EventShortTitle{CVIT 2016} +\EventAcronym{CVIT} +\EventYear{2016} +\EventDate{December 24--27, 2016} +\EventLocation{Little Whinging, United Kingdom} +\EventLogo{} +\SeriesVolume{42} +\ArticleNo{23} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{document} + +\maketitle + +%TODO mandatory: add short abstract of the document +\begin{abstract} +TODO: Abstract +\end{abstract} + +\input{introduction} + +%\input{tRules} + +%\input{tiRules} + +\input{constraints} + +\section{Capture Conversion} +The input to our type inference algorithm does not contain let statements. +Those are added after computing a type solution. +Let statements act as capture conversion and only have to be applied in method calls involving wildcard types. + +\begin{figure} + \begin{minipage}{0.45\textwidth} +\begin{lstlisting}[style=fgj] + List clone(List l); +example(p){ + return clone(p); +} +\end{lstlisting} + \end{minipage}% + \hfill + \begin{minipage}{0.5\textwidth} +\begin{lstlisting}[style=tfgj] +(*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) example((*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) p){ + return let x : (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) = p in + clone(x) : (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*); +} +\end{lstlisting} + \end{minipage} +\caption{Type inference adding capture conversion}\label{fig:addingLetExample} + \end{figure} + +Figure \ref{fig:addingLetExample} shows a let statement getting added to the typed output. +The method \texttt{clone} cannot be called with the type $\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$. +After a capture conversion \texttt{x} has the type $\exptype{List}{\rwildcard{X}}$ with $\rwildcard{X}$ being a free variable. +Afterwards we have to find a supertype of $\exptype{List}{\rwildcard{X}}$, which does not contain free variables +($\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$ in this case). + +During the constraint generation step most types are not known yet and are represented by a type placeholder. +During a methodcall like the one in the \texttt{example} method in figure \ref{fig:ccExample} the type of the parameter \texttt{p} +is not known yet. +The type \texttt{List} would be one possibility as a parameter type for \texttt{p}. +To make wildcards work for our type inference algorithm \unify{} has to apply capture conversions if necessary. + +The type placeholder $\tv{r}$ is the return type of the \texttt{example} method. +One possible type solution is $\tv{p} \doteq \tv{r} \doteq \wctype{\rwildcard{X}}{List}{\rwildcard{X}}$, +which leads to: +\begin{verbatim} +List example(List p){ + return clone(p); +} +\end{verbatim} + +But by substituting $\tv{p} \doteq \wctype{\rwildcard{X}}{List}{\rwildcard{X}}$ in the constraint +$\tv{p} \lessdot \exptype{List}{\wtv{x}}$ leads to +$\wctype{\rwildcard{X}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{x}}$. + +To make this typing possible we have to introduce a capture conversion via a let statement: +$\texttt{return}\ (\texttt{let}\ \texttt{x} : \wctype{\rwildcard{X}}{List}{\rwildcard{X}} = \texttt{p}\ \texttt{in} \ +\texttt{clone}\generics{\rwildcard{X}}(x) : \wctype{\rwildcard{X}}{List}{\rwildcard{X}})$ + +Inside the let statement the variable \texttt{x} has the type $\exptype{List}{\rwildcard{X}}$ + +$ +\begin{array}[c]{l} +\wildcardEnv \vdash C \cup \set{\wtv{a} \doteq \rwildcard{G}}\\ + \hline +[\type{G}/\wtv{a}]\wildcardEnv \vdash [\type{G}/\wtv{a}]C \cup \set{\tv{a} \doteq \type{G}} +\end{array} +$ + +This spawns additional problems. +%TODO +%we need the constraint set to be a list +%not on every constraint CC is allowed. The unify algorithm does not know the context in which a constraint was generated +%free type variables cannot leave the scope of the method call + +\begin{figure} +\begin{minipage}{0.45\textwidth} +\begin{verbatim} + List clone(List l){...} + +example(p){ + return clone(p); +} +\end{verbatim} + \end{minipage}% + \hfill + \begin{minipage}{0.35\textwidth} +\begin{constraintset} + \textbf{Constraints:}\\ + $ + \tv{p} \lessdot \exptype{List}{\wtv{x}}, \\ +\tv{p} \lessdot \tv{r}, \\ +\tv{p} \lessdot \type{Object}, +\tv{r} \lessdot \type{Object} + $ +\end{constraintset} + \end{minipage} + +\caption{Type inference example}\label{fig:ccExample} +\end{figure} + +In addition with free variables this leads to unwanted behaviour. +Take the constraint +$\wctype{\rwildcard{X}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}$ for example. +After a capture conversion from $\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$ to $\exptype{List}{\rwildcard{Y}}$ and a substitution $\wtv{a} \doteq \rwildcard{Y}$ +we get +$\exptype{List}{\rwildcard{Y}} \lessdot \exptype{List}{\rwildcard{Y}}$. +Which is correct if we apply capture conversion to the left side: +$\exptype{List}{\rwildcard{X}} <: \exptype{List}{\rwildcard{X}}$ +If the input constraints did not intend for this constraint to undergo a capture conversion then \unify{} would produce an invalid +type solution due to: +$\wctype{\rwildcard{X}}{List}{\rwildcard{X}} \nless: \exptype{List}{\rwildcard{X}}$ +The reason for this is the \texttt{S-Exists} rule's premise +$\text{dom}(\Delta') \cap \text{fv}(\exptype{List}{\rwildcard{X}}) = \emptyset$. + +Additionally free variables are not allowed to leave the scope of a capture conversion +introduced by a let statement. +%TODO we combat both of this with wildcard type placeholders (? flag) + +Type placeholders which are not flagged as possible free variables ($\wtv{a}$) can never hold a free variable or a type containing free variables. +Constraint generation places these standard place holders at method return types and parameter types. +\begin{lstlisting}[style=fgj] + List clone(List l); +(*@$\red{\tv{r}}$@*) example((*@$\red{\tv{p}}$@*) p){ + return clone(p); +} +\end{lstlisting} +This prevents type solutions that contain free variables in parameter and return types. +When calling a method which already has a type annotation we have to consider adding a capture conversion in form of a let statement. +The constraint $\tv{p} \lessdot \exptype{List}{\wtv{x}}$ signals the \unify{} algorithm that here a capture conversion is possible. +$\sigma(\tv{p}) = \wctype{\rwildcard{X}}{List}{\rwildcard{X}}, \sigma(\tv{r}) = \wctype{\rwildcard{X}}{List}{\rwildcard{X}}, $ is a possible solution. +But only when adding a capture conversion: +\begin{lstlisting}[style=fgj] + List clone(List l); +(*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) example((*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) p){ + return let x : (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*) = p in clone(x) : (*@$\wctype{\rwildcard{X}}{List}{\rwildcard{X}}$@*); +} +\end{lstlisting} +\unify{}'s type solution for constraints involving free variables only holds under special circumstances. +Constraint $\tv{p} \lessdot \exptype{List}{\wtv{x}}$ only holds when a capture conversion is applied to the left side: +$\Delta, \Delta' \vdash CC(\sigma(\tv{p})) <: \sigma(\exptype{List}{\wtv{x}})$ +and there is a an environment $\Delta'$ holding all type variables used inside the subtype relation. +This is done by packing the method call inside a let statement, which performs a capture conversion on all expressions used as parameters. +%TODO: Explain (do soundness and TYPE algorithm first) + +A type solution of the \unify{} algorithm only guarantees correct subtyping for constraints not containing free variables. +Constraints like $\wctype{\rwildcard{X}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}$ only guarantee +$\Delta, \Delta' \vdash \sigma(\wctype{\rwildcard{X}}{List}{\rwildcard{X}}) <: \sigma(\exptype{List}{\wtv{a}})$ when +adding a $\Delta'$ environment and applying a capture conversion on the left side. +In this case the type solution would be $\tv{a} \to \rwildcard{X}$ leading to: +$\Delta, \set{\rwildcard{X}} \vdash \exptype{List}{\rwildcard{X}} <: \exptype{List}{\rwildcard{X}}$ + +This is the reason input constraints containing free variables cannot be stored in a set. +$\wtv{a} \lessdot \wtv{b}$ is not the same as $\wtv{a} \lessdot \wtv{b}$. +Both constraints will end up the same after a substitution for both placeholders $\tv{a}$ and $\tv{b}$. +But afterwards a capture conversion is applied, which can generate different types on the left sides. +\begin{itemize} + \item $\text{CC}(\wctype{\rwildcard{X}}{List}{\rwildcard{X}}) \implies \exptype{List}{\rwildcard{Y}}$ + \item $\text{CC}(\wctype{\rwildcard{X}}{List}{\rwildcard{X}}) \implies \exptype{List}{\rwildcard{Z}}$ +\end{itemize} + + +Also the subtype relation is not symmetric for types involving free type variables. +$\type{T} \lessdot \type{S}$ and $\type{S} \lessdot \type{T}$ doesnt mean $\type{T} = \type{S}$, because we apply a capture conversion on every constraint. +Only for constraints without free variables symmetry is given. + +% Can untyped methods also get a capture conversion? NO! + +%TODO: Explain why capture conversion is needed (also in respect to martins algorithm) + +\input{Unify} + +\section{Limitations} + +This example does not work: + +\begin{minipage}{0.35\textwidth} + \begin{verbatim} +class Example{ + Pair make(List l){...} + bool compare(Pair p){...} + + bool test(List l){ + return compare(make(l)); + } +} +\end{verbatim} + \end{minipage}% + \hfill + \begin{minipage}{0.55\textwidth} +\begin{constraintset} + \textbf{Constraints:}\\ + $ + \wctype{\wildcard{A}{\type{Object}}{\bot}}{List}{\rwildcard{A}} \lessdot \exptype{List}{\wtv{x}}, \\ + \exptype{Pair}{\wtv{x},\wtv{x}} \lessdot \tv{r}, \\ + \tv{r} \lessdot \exptype{Pair}{\tv{z}, \tv{z}}%,\\ + %\tv{y} \lessdot \tv{m} + $\\ +\end{constraintset} + \end{minipage} + + +\input{conclusion} + +\include{soundness} +%\include{termination} + +\bibliography{martin} + +\appendix +%\include{examples} +%\input{exampleWildcardParameter} +%\input{commonPatternsProof} +%\input{appendix} +\end{document} diff --git a/cc-by.pdf b/cc-by.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3b7aba19995d1f831e17df9f3ab6b66732ac0c7b GIT binary patch literal 58331 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 D4UieO literal 0 HcmV?d00001 diff --git a/conclusion.tex b/conclusion.tex new file mode 100644 index 0000000..988cd4d --- /dev/null +++ b/conclusion.tex @@ -0,0 +1,35 @@ +\section{Conclusion and Further Work} +% we solved the problems given in the introduction (see examples TODO give names to examples) +The problems introduced in the openening \ref{challenges} can be solved via our \unify{} algorithm (see examples \ref{example1} and \ref{example2}). +As you can see by the given examples our type inference algorithm can calculate +type solutions for programs involving wildcards. + +Going further we try to proof soundness and completeness for \unify{}. + + +% The tricks are: +% \begin{itemize} +% \item Erasing wildcards by setting $\type{U} \doteq \type{L}$ +% \end{itemize} + +% Improvements: +% \begin{itemize} +% \item Straightforward algorithm. Less data types used. Only two sort of constraints. +% \end{itemize} + +% \subsection{Problems} +% The algorithm is lacking completeness. + +% \begin{verbatim} +% void m(List a){} + +% m2(l){ +% l.add("String"); +% } +% \end{verbatim} + +%COnstraints: +%l <. List +%String <. a + + diff --git a/constraints.tex b/constraints.tex new file mode 100644 index 0000000..9ef6c51 --- /dev/null +++ b/constraints.tex @@ -0,0 +1,337 @@ + +\section{Constraint generation} +Our type inference algorithm is split into two parts. +A constraint generation step \textbf{TYPE} and a \unify{} step. + +Method names are not unique. +It is possible to define the same method in multiple classes. +The \TYPE{} algorithm accounts for that by generating Or-Constraints. +This can lead to multiple possible solutions. + +%\subsection{Well-Formedness} + + +%Why do we need a constraint generation step? +%% The problem is NP-Hard +%% a method call, does not know which type it will produce +%% depending on its type the + +%NO equals constraints during the constraint generation step! +\begin{figure}[tp] + \begin{align*} + % Type + \type{T}, \type{U} &::= \tv{a} \mid \wtv{a} \mid \mv{X} \mid {\wcNtype{\Delta}{N}} && \text{types and type placeholders}\\ + \type{N} &::= \exptype{C}{\il{T}} && \text{class type (with type variables)} \\ + % Constraints + \simpleCons &::= \type{T} \lessdot \type{U} && \text{subtype constraint}\\ + \orCons{} &::= \set{\set{\overline{\simpleCons_1}}, \ldots, \set{\overline{\simpleCons_n}}} && \text{or-constraint}\\ + \constraint &::= \simpleCons \mid \orCons && \text{constraint}\\ + \consSet &::= \set{\constraints} && \text{constraint set}\\ + % Method assumptions: + \methodAssumption &::= \exptype{C}{\ol{X} \triangleleft \ol{N}}.\texttt{m} : \exptype{}{\ol{Y} + \triangleleft \ol{P}}\ \ol{\type{T}} \to \type{T} && + \text{method + type assumption}\\ + \localVarAssumption &::= \texttt{x} : \itype{T} && \text{parameter + assumption}\\ + \mtypeEnvironment & ::= \overline{\methodAssumption} & + & \text{method type environment} \\ + \typeAssumptionsSymbol &::= ({\mtypeEnvironment} ; \overline{\localVarAssumption}) + \end{align*} + \caption{Syntax of constraints and type assumptions.} + \label{fig:syntax-constraints} +\end{figure} + +\begin{figure}[tp] + \begin{gather*} + \begin{array}{@{}l@{}l} + \fjtype & ({\mtypeEnvironment}, \mathtt{class } \ \exptype{C}{\ol{X} \triangleleft \ol{N}} \ \mathtt{ extends } \ \mathtt{N \{ \overline{T} \ \overline{f}; \, K \, \overline{M} \}}) =\\ + & \begin{array}{ll@{}l} +\textbf{let} & \forall \texttt{m} \in \ol{M}: \tv{a}_\texttt{m}, \ol{\tv{a}_m} \ \text{fresh} \\ + & \ol{\methodAssumption} = \begin{array}[t]{l} + \set{ \mv{m'} : (\exptype{C}{\ol{X} \triangleleft \ol{N}} \to \ol{\tv{a}} \to \tv{a}) \mid + \mv{m'} \in \ol{M} \setminus \set{\mv{m}}, \, \tv{a}\, \ol{\tv{a}}\ \text{fresh} } \\ +\ \cup \, \set{\mv{m} : (\exptype{C}{\ol{X} \triangleleft \ol{N}} \to \ol{\tv{a}_m} \to \tv{a}_\mv{m})} +\end{array} + \\ + & C_m = \typeExpr(\mtypeEnvironment \cup \set{\mv{this} : + \exptype{C}{\ol{X}} , \, \ol{x} : \ol{\tv{a}_m} }, \texttt{e}, \tv{a}_\texttt{m}) \\ +\textbf{in} + & { ( \mtypeEnvironment \cup \ol{\methodAssumption}, \, + \bigcup_{\texttt{m} \in \ol{M}} C_m ) + } + \end{array} + \end{array} + \end{gather*} + \caption{Constraint generation for classes} + \label{fig:constraints-for-classes} +\end{figure} + +% \textbf{Method Assumptions} + +% %$\Pi$ is a set of method assumptions used by the $\fjtype{}$ algorithm. + +% % \begin{verbatim} +% % class Example { +% % Y m(Example p){ ... } +% % } +% % \end{verbatim} + +% In Featherweight Java a method type is bound to a specific class. +% The class \texttt{Example} shown above contains one method \texttt{m}: + +% \begin{displaymath} +% \textit{mtype}({\texttt{m}, \exptype{Example}{\type{X}}}) = \generics{\type{Y}} \ \exptype{Example}{\type{Y}} \to \type{Y} +% \end{displaymath} + +% $\Pi$ is a set of method assumptions used by the $\fjtype{}$ algorithm. +% It's a map of method types to method names. +% Every method name has a set of possible types, +% because there could be more than one method with the same name in a program consisting out of multiple classes. +% To simplify the syntax of method assumptions, we add the inheriting class type to the parameter list: + +% \begin{displaymath} +% \Pi = \set{ \texttt{m} : \generics{\type{X}, \type{Y}} \ (\exptype{Example}{\type{X}}, \exptype{Example}{\type{Y}}) \to \type{Y}} +% \end{displaymath} + +% \begin{verbatim} +% class Example { } + +% Y m(Example this, Example p){ ... } +% \end{verbatim} + +The constraint generation step is the same as the one for regular Generic Featherweight Java. +Wildcard types are not used during the constraint generation step and have no influence on it. + +\begin{displaymath} + \begin{array}{@{}l@{}l} + \typeExpr{} &({\mtypeEnvironment} , \texttt{e}.\texttt{f}, \tv{a}) = \\ + & \begin{array}{ll} + \textbf{let} + & \tv{r} \ \text{fresh} \\ + & \consSet_R = \typeExpr({\mtypeEnvironment}, \texttt{e}, \tv{r})\\ + & \constraint = \begin{array}[t]{@{}l@{}l} + \orCons\set{ + \set{ & + \tv{r} \lessdot \exptype{C}{\ol{\wtv{a}}} , + [\overline{\wtv{a}}/\ol{X}]\type{T} \lessdot \tv{a} , \ol{\tv{a}} \lessdot [\overline{\tv{a}}/\ol{X}]\ol{N} + } \\ + & \quad \mid \mv{T}\ \mv{f} \in \texttt{class}\ \exptype{C}{\ol{X} \triangleleft \ol{N}} \set{ \ol{T\ f}; \ldots} + , \, \overline{\wtv{a}} \text{ fresh} + }\end{array}\\ + {\mathbf{in}} & { + \consSet_R \cup \set{\constraint}} + \end{array} + \end{array} +\end{displaymath} + +The set of method assumptions returned by the \textit{mtypes} function is used to generate the constraints for a method call expression: + +There are two kinds of method calls. +The ones to already typed methods and calls to untyped methods. + +%Soundness: TODO + + +\begin{displaymath} +\begin{array}{@{}l@{}l} + \typeExpr{} & ({\mtypeEnvironment} , \texttt{e}.\mathtt{m}(\overline{\texttt{e}}), \tv{a} ) = \\ + & \begin{array}{ll} + \textbf{let} + & \tv{r}, \ol{\tv{r}} \text{ fresh} \\ + & \consSet_R = \typeExpr(({\mtypeEnvironment} ; + \overline{\localVarAssumption}), \texttt{e}, \tv{r})\\ + & \overline{\consSet} = \typeExpr({\mtypeEnvironment}, \ol{e}, \ol{\tv{r}}) \\ + & \begin{array}{@{}l@{}l} + \constraint = \orCons\set{ & + \begin{array}[t]{l} + \{ \tv{r} \lessdot \exptype{C}{\ol{\wtv{a}}}, + \overline{\tv{r}} \lessdot \ol{T}, + \type{T} \lessdot \tv{a}, + \overline{\wtv{a}} \lessdot \ol{N} \} + \end{array}\\ + & \ |\ + (\exptype{C}{\ol{X} \triangleleft \ol{N}}.\texttt{m} : \overline{\type{T}} \to \type{T}) \in + {\mtypeEnvironment} + , \, \overline{\wtv{a}} \text{ fresh} } + \end{array}\\ + \mathbf{in} & \consSet_R \cup \overline{\consSet} \cup \constraint + \end{array} + \end{array} +\end{displaymath} + +\begin{displaymath} +\begin{array}{@{}l@{}l} + \typeExpr{} & ({\mtypeEnvironment} , \texttt{e}.\mathtt{m}(\overline{\texttt{e}}), \tv{a} ) = \\ + & \begin{array}{ll} + \textbf{let} + & \tv{r}, \ol{\tv{r}} \text{ fresh} \\ + & \consSet_R = \typeExpr(({\mtypeEnvironment} ; + \overline{\localVarAssumption}), \texttt{e}, \tv{r})\\ + & \overline{\consSet} = \typeExpr({\mtypeEnvironment}, \ol{e}, \ol{\tv{r}}) \\ + & \begin{array}{@{}l@{}l} + \constraint = \orCons\set{ & + \begin{array}[t]{l} + [\overline{\wtv{a}}/\ol{Y}] [\overline{\wtv{b}}/\ol{X}] \{ \tv{r} \lessdot \exptype{C}{\ol{X}}, + \overline{\tv{r}} \lessdot \ol{T}, + \type{T} \lessdot \tv{a}, + \overline{\wtv{a}} \lessdot \ol{N}, + \overline{\wtv{b}} \lessdot \ol{N'} \} + \end{array}\\ + & \ |\ + (\exptype{C}{\ol{X} \triangleleft \ol{N}}.\texttt{m} : \generics{\ol{Y} \triangleleft \ol{N}}\overline{\type{T}} \to \type{T}) \in + {\mtypeEnvironment} + , \, \overline{\wtv{a}} \text{ fresh}, \, \overline{\wtv{b}} \text{ fresh} } + \end{array}\\ + \mathbf{in} & \consSet_R \cup \overline{\consSet} \cup \constraint + \end{array} + \end{array} +\end{displaymath} +\\[1em] +\noindent +\textbf{Example:} +\begin{verbatim} +class Class1{ + X m(List lx, List lt){ ... } + List wGet(){ ... } + List get() { ... } +} + +class Class2{ + example(c1){ + return c1.m(c1.get(), c1.wGet()); + } +} +\end{verbatim} +%This example comes with predefined type annotations. +We assume the class \texttt{Class1} has already been processed by our type inference algorithm, +which has lead to the given type annotations for \texttt{Class1}. +Now we call the $\fjtype{}$ function with the class \texttt{Class2} and the method assumptions for the preceeding class: +\begin{displaymath} +\mtypeEnvironment = \left\{\begin{array}{l} + \type{Class1}.\texttt{m}: \generics{\type{X} \triangleleft \type{Object}} \ + (\exptype{List}{\type{X}}, \, \wctype{\wildcard{A}{\type{X}}{\bot}}{List}{\wildcard{A}{\type{X}}{\bot}}) \to \type{X}, \\ + \type{Class1}.\texttt{wGet}: () \to \wctype{\wildcard{A}{\type{Object}}{\type{String}}}{List}{\wildcard{A}{\type{Object}}{\type{String}}}, \\ + \type{Class1}.\texttt{get}: () \to \exptype{List}{\type{String}} +\end{array} \right\} +\end{displaymath} + +The result of the $\typeExpr{}$ function is the constraint set +\begin{displaymath} +C = \left\{ \begin{array}{l} +\tv{c1} \lessdot \type{Class1}, \\ +\tv{p1} \lessdot \exptype{List}{\wtv{x}}, \\ +\exptype{List}{\type{String}} \lessdot \tv{p1}, \\ +\tv{p2} \lessdot \wctype{\wildcard{A}{\wtv{x}}{\bot}}{List}{\rwildcard{A}}, \\ +\wctype{\wildcard{A}{\type{String}}{\bot}}{List}{\rwildcard{A}} \lessdot \tv{p2} +\end{array} \right\} +\end{displaymath} + + +The first parameter of a method assumption is the receiver type $\type{T}_r$. +\texttt{Class1} for this example. +Therefore the $(\tv{c1} \lessdot \type{Class1})$ constraint. +The type variable $\tv{c1}$ is assigned to the parameter \texttt{c1} of the \texttt{example} method. + +or a simplified version: + +\begin{displaymath} +C = \left\{ \begin{array}{l} +\tv{c1} \lessdot \type{Class1}, \\ +\exptype{List}{\type{String}} + \lessdot \exptype{List}{\wtv{x}}, \\ +\wctype{\wildcard{A}{\type{String}}{\bot}}{List}{\rwildcard{A}} + \lessdot \wctype{\wildcard{A}{\wtv{x}}{\bot}}{List}{\rwildcard{A}} +\end{array} \right\} +\end{displaymath} + + +$\wtv{x}$ is a type variable we use for the generic $\type{X}$. It is flagged as a free type variable. +%TODO: Do an example where wildcards are inserted and we need capture conversion +%\unify{} returns the solution $(\sigma = \set{ \tv{x} \to \type{String} })$ + +% \\[1em] +% \noindent +% \textbf{Example:} +% \begin{verbatim} +% class Class1 { +% Pair make(List l){ ... } +% boolean compare(Pair p) { ... } + +% example(l){ +% return compare(make(l)); +% } +% } +% \end{verbatim} + +% The method call \texttt{make(l)} generates the constraints +% \begin{displaymath} +% \tv{l} \lessdot \exptype{List}{\tv{x}}, \exptype{Pair}{\tv{x}, \tv{x}} \lessdot \tv{m} +% \end{displaymath} +% with $\tv{l}$ being the type placeholder for the variable \texttt{l} +% and $\tv{m}$ is the type variable for the return type of the method call. +% $\tv{m}$ is then used as the parameter for the \texttt{compare} method: +% \begin{displaymath} +% \tv{m} \lessdot \exptype{Pair}{\tv{y}, \tv{y}} +% \end{displaymath} +% Note the conversion of the generic parameters \texttt{X} and \texttt{Y} to type variables $\tv{x}$ and $\tv{y}$. + + + +% Step 3 of the \unify{} algorithm has to look for every possible supertype of $\exptype{Pair}{\tv{x}, \tv{x}}$, +% when processing the $\exptype{Pair}{\tv{x}, \tv{x}} \lessdot \tv{m}$ constraint. + +\begin{displaymath} + \begin{array}{@{}l@{}l} + \typeExpr{} &({\mtypeEnvironment} , e_1 \elvis{} e_2, \tv{a}) = \\ + & \begin{array}{ll} + \textbf{let} + & \tv{r}_1, \tv{r}_2 \ \text{fresh} \\ + & \consSet_1 = \typeExpr({\mtypeEnvironment}, e_1, \tv{r}_2)\\ + & \consSet_2 = \typeExpr({\mtypeEnvironment}, e_2, \tv{r}_2)\\ + {\mathbf{in}} & { + \consSet_1 \cup \consSet_2 \cup + \set{\tv{r}_1 \lessdot \tv{a}, \tv{r}_2 \lessdot \tv{a}}} + \end{array} + \end{array} +\end{displaymath} + +%We could skip wfresh here: +\begin{displaymath} + \begin{array}{@{}l@{}l} + \typeExpr{} &({\mtypeEnvironment} , x, \tv{a}) = + \mtypeEnvironment(x) + \end{array} +\end{displaymath} + +\begin{displaymath} + \begin{array}{@{}l@{}l} + \typeExpr{} &({\mtypeEnvironment} , \texttt{new}\ \type{C}(\overline{e}), \tv{a}) = \\ + & \begin{array}{ll} + \textbf{let} + & \ol{\tv{r}} \ \text{fresh} \\ + & \overline{\consSet} = \typeExpr({\mtypeEnvironment}, \overline{e}, \ol{\tv{r}}) \\ + & C = \set{\ol{\tv{r}} \lessdot [\ol{\tv{a}}/\ol{X}]\ol{T}, \ol{\tv{a}} \lessdot \ol{N} \mid \texttt{class}\ \exptype{C}{\ol{X} \triangleleft \ol{N}} \set{ \ol{T\ f}; \ldots}} \\ + {\mathbf{in}} & { + \overline{\consSet} \cup + \set{\tv{a} \doteq \exptype{C}{\ol{a}}}} + \end{array} + \end{array} +\end{displaymath} + +% Problem: +% > void t2(List l){} + +% void test(List> l){ +% t2(l); +% } +% Problem: +% List> <. List, a <. List +% Y.List =. a +% Z.List <. List + +% These constraints should fail! + +\section{Result Generation} +If \unify{} returns atleast one type solution $(\Delta, \sigma)$ +the last step of the type inference algorithm is to generate a typed class. diff --git a/introduction.tex b/introduction.tex new file mode 100644 index 0000000..ca5c1a5 --- /dev/null +++ b/introduction.tex @@ -0,0 +1,222 @@ + +\section{Type Inference for Java} +%The goal is to find a correct typing for a given Java program. +Type inference for Java has many use cases and could be used to help programmers by inserting correct types for them, +Finding better type solutions for already typed Java programs (for example more generical ones), +or allowing to write typeless Java code which is then type infered and thereby type checked by our algorithm. +The algorithm proposed in this paper can determine a correct typing for the untyped Java source code example shown in figure \ref{fig:intro-example-typeless}. +Our algorithm is also capable of finding solutions involving wildcards as shown in figure \ref{fig:intro-example-typed}. + +This paper extends a type inference algorithm for Featherweight Java (\cite{TIforFGJ}) by adding wildcards. +The last step to create a type inference algorithm compatible to the Java type system. +The algorithm is a modified version of the \unify{} algorithm presented in \cite{plue09_1}. + +%TODO +% The goal is to proof soundness in respect to the type rules introduced by \cite{aModelForJavaWithWildcards} +% and \cite{WildcardsNeedWitnessProtection}. + +\begin{figure}[tp] + \begin{subfigure}[t]{0.49\linewidth} + \begin{lstlisting}[style=fgj] +genList() { + if( ... ) { + return new List(); + } else { + return new List(); + } +} + \end{lstlisting} + \caption{Java method with missing return type} + \label{fig:intro-example-typeless} + \end{subfigure} + ~ + \begin{subfigure}[t]{0.49\linewidth} + \begin{lstlisting}[style=tfgj] +List genList() { + if( ... ) { + return new List(); + } else { + return new List(); + } +} + \end{lstlisting} + \caption{Correct type} + \label{fig:intro-example-typed} + \end{subfigure} + %\caption{Example code} + %\label{fig:intro-example-code} + \end{figure} + +% \subsection{Wildcards} +% Java subtyping involving generics is invariant. +% For example \texttt{List} is not a subtype of \texttt{List}. +% %Wildcards introduce variance by allowing \texttt{List} to be a subtype of \texttt{List}. + +% \texttt{List} is not a valid return type for the method \texttt{genList}. +% The type inference algorithm has to find the correct type involving wildcards (\texttt{List}). + +\subsection{Java Wildcards} +Wildcards add variance to Java type parameters. +In Java a \texttt{List} is not a subtype of \texttt{List} +even though it seems intuitive with \texttt{String} being a subtype of \texttt{Object}. +Here wildcards come into play. + +$\exptype{List}{String} <: \wctype{\wildcard{X}{\bot}{\type{Object}}}{List}{\rwildcard{X}}$ +means \texttt{List} is a subtype of \texttt{List}. +The syntax used here allows for wildcard parameters to have a name, an uppper and lower bound at the same time, +and a type they are bound to. +In this case the name is $\rwildcard{X}$ and it's bound to the the type \texttt{List}. +% Additionally they can hold a upper or lower bound restriction like \texttt{List}. +% Our representation of this type is: $\wctype{\wildcard{X}{\type{String}}{\type{Object}}}{List}{\rwildcard{X}}$ +% Every wildcard has a name ($\rwildcard{X}$ in this case) and an upper and lower bound (respectively \texttt{Object} and \texttt{String}). + + +\subsection{Constraints} + +Constraints consist of normal types and type variables: + +$\exptype{List}{String} \lessdot \tv{a}, \exptype{List}{Integer} \lessdot \tv{a}$ + +\noindent +Those two constraints imply that we have to find a type replacement for type variable $\tv{a}$, +which is a supertype of $\exptype{List}{String}$ aswell as $\exptype{List}{Integer}$. +This paper describes a \unify{} algorithm to solve these constraints and calculate a type solution $\sigma$. +For the example above a correct solution would be $\sigma(\tv{a}) = \wctype{\rwildcard{X}}{List}{\rwildcard{X}}$. + +\subsection{Challenges}\label{challenges} +The introduction of wildcards adds additional challenges. +% we cannot replace every type variable with a wildcard +Type variables can also be used as type parameters, for example +$\exptype{List}{String} \lessdot \exptype{List}{\tv{a}}$. +A problem arises when replacing type variables with wildcards. + +% Wildcards are not reflexive. +% ( on the equals property ), every wildcard has to be capture converted when leaving its scope + +% do not substitute free type variables + +Lets have a look at two examples: +\begin{itemize} +\item \begin{example} \label{intro-example1} +The first one is a valid Java program. +The type \texttt{List} is \textit{capture converted} to a fresh type variable $\rwildcard{X}$ +which is used as the generic method parameter \texttt{A}. + +Java uses capture conversion to replace the generic \texttt{A} by a capture converted version of the +\texttt{? super String} wildcard. +Knowing that the type \texttt{String} is a subtype of any type the wildcard \texttt{? super String} can inherit +it is safe to pass \texttt{"String"} for the first parameter of the function. + +\begin{verbatim} + List add(A a, List la) {} + + List list = ...; + add("String", list); +\end{verbatim} +The constraints representing this code snippet are: + +\begin{displaymath} + \type{String} \lessdot \wtv{a},\, +\wctype{\wildcard{X}{\type{Object}}{\type{String}}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}} +\end{displaymath} + +Here $\sigma(\tv{a}) = \rwildcard{X}$ is a valid solution. +\end{example} + +\item \begin{example}\label{intro-example2} +This example displays an incorrect Java program. +The method call to \texttt{concat} with two wildcard lists is unsound. +Each list could be of a different kind and therefore the \texttt{concat} cannot succeed. +\begin{verbatim} + List concat(List l1, List l2) {} + + List list = ... ; + concat(list, list); +\end{verbatim} +The constraints for this example are: + +$\wctype{\wildcard{X}{\type{Object}}{\bot}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}, \\ +\wctype{\wildcard{X}{\type{Object}}{\bot}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\wtv{a}}$ +%$\exptype{List}{?} \lessdot \exptype{List}{\tv{a}}, +%\exptype{List}{?} \lessdot \exptype{List}{\tv{a}}$ + +Remember that the given constraints cannot have a valid solution. +%This is due to the fact that the wildcard variables cannot leave their scope. +In this example the \unify{} algorithm should not replace $\tv{a}$ with the captured wildcard $\rwildcard{X}$. +\end{example} + +\end{itemize} + +The \unify{} algorithm only sees the constraints with no information about the program they originated from. +The main challenge was to find an algorithm which computes $\sigma(\tv{a}) = \rwildcard{X}$ for example \ref{intro-example1} but not for example \ref{intro-example2}. +% Solution: A type variable can only take one type and not a wildcard type. + % A wildcard type is only treated like a wildcard while his definition is in scope (during the reduce rule) + + + + +% \subsection{Capture Conversion} +% \begin{verbatim} +% List add(A a, List la) {} + +% List list = ...; + +% add("String", list); +% \end{verbatim} +% The constraints representig this code snippet are: +% $\type{String} \lessdot \tv{a}, +% \wctype{\wildcard{X}{\type{Object}}{\type{String}}}{List}{\rwildcard{X}} \lessdot \exptype{List}{\tv{a}}$ +% Under the hood the typechecker has to find a replacement for the generic method parameter \texttt{A}. + +% Java allows a method \texttt{ List add(A a, List la)} to be called with +% \texttt{String} and \texttt{List}. +% A naive approach would be to treat wildcards like any other type and replace \texttt{A} +% with \texttt{? super String}. +% Generating the method type \texttt{List add(? super String a, List la)}. + +% This does not work for a method like +% \texttt{ void merge(List l1, List l2)}. +% It is crucial for this method to be called with two lists of the same type. +% Substituting a wildcard for the generic \texttt{A} leads to +% \texttt{void merge(List l1, List l2)}, +% which is unsound. + +% Capture conversion utilizes the fact that instantiated classes always have an actual type. +% \texttt{new List()} and \texttt{new List()} are +% valid instances. +% \texttt{new List()} is not. +% Every type $\wcNtype{\Delta}{N}$ contains an underlying instance of a type $\type{N}$. +% Knowing this fact allows to make additional assumptions. + +% \wildFJ{} type rules allow for generic parameters to be replaced by wildcard types. +% This is possible because wildcards are split into two parts. +% Their declaration at the environment part $\Delta$ of a type $\wcNtype{\Delta}{N}$ +% and their actual use in the body of the type $\type{N}$. +% Replacing the generic \texttt{A} in the type \texttt{List} +% by a wildcard $\type{X}$ will not generate the type \texttt{List}. +% \texttt{List} is the equivalent of $\wctype{\wildcard{X}{\type{Object}}{\bot}}{List}{\type{X}}$. +% The generated type here is $\exptype{List}{\type{X}}$, which has different subtype properties. +% There is no information about what the type $\exptype{List}{\type{X}}$ actually is. +% It has itself as a subtype and for example a type like $\exptype{ArrayList}{\type{X}}$. + +% A method call for example only works with values, which are correct instances of classes. +% Capture conversion automatically converts wildcard type to a concrete class type, +% which then can be used as a parameter for a method call. + +% In \wildFJ{} this is done via let statements. + +% Written in FJ syntax: $\type{N}$ is a initialized type and +% $\wcNtype{\Delta}{N}$ is a type containing wildcards $\Delta$. + +% It is crucial for the wildcard names to never be used twice. +% Otherwise the members of a list with type $\wctype{\type{X}}{List}{\type{X}}$ and +% a list with type $\wctype{\type{X}}{List}{\type{X}}$ would be the same. $\type{X}$ in fact. + +% The let statement adds wildcards to the environment. +% Those wildcards are not allowed to escape the scope of the let statement. +% Which is a problem for our type inference algorithm. + +% The capture converted version of the type $\wctype{\rwildcard{X}}{Box}{\rwildcard{X}}$ is +% $\exptype{Box}{\rwildcard{X}}$. +% The captured type is only used as an intermediate type during a method call. + diff --git a/lipics-logo-bw.pdf b/lipics-logo-bw.pdf new file mode 100644 index 0000000000000000000000000000000000000000..26b83d627ac94e4d9aeaacdea480fefde08bc2c3 GIT binary patch literal 83561 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 z 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 GfBJuHEVD-d literal 0 HcmV?d00001 diff --git a/prolog.tex b/prolog.tex new file mode 100755 index 0000000..ba7e959 --- /dev/null +++ b/prolog.tex @@ -0,0 +1,206 @@ +\usepackage{xspace} +\usepackage{color,ulem} +\usepackage{listings} +\lstset{language=Java, + showspaces=false, + showtabs=false, + breaklines=true, + showstringspaces=false, + breakatwhitespace=true, + basicstyle=\ttfamily\fontsize{8}{9.6}\selectfont, %\footnotesize + escapeinside={(*@}{@*)}, + captionpos=b, +} +\lstdefinestyle{fgj}{backgroundcolor=\color{lime!20}} +\lstdefinestyle{tfgj}{backgroundcolor=\color{lightgray!20}} + + +\newcommand\mv[1]{{\tt #1}} +\newcommand{\ol}[1]{\overline{\tt #1}} +\newcommand{\exptype}[2]{\mathtt{#1 \texttt{<} #2 \texttt{>} }} +\newcommand\ddfrac[2]{\frac{\displaystyle #1}{\displaystyle #2}} + +\newcommand{\sarray}[2]{\begin{array}[t]{#1} #2 \end{array}} + +%\newcommand{\olsub}{\textrm{$\, \leq^\ast \,$}\ } +\newcommand{\olsub}{\textrm{$<:$}\ } + +\newcommand{\sub}\olsub%{\mbox{$<$}} + +\newcommand{\set}[1]{\{ #1 \} } + +\definecolor{red}{rgb}{1,0,0} +\newcommand{\red}[1]{\textcolor{red}{#1}} + +\newcommand{\commentarystar}[1]{\red{\({}^*\)}\marginpar[\tiny + \red{\({}^*\)#1}]{\tiny \red{\({}^*\)#1}}} +\newcommand{\commentary}[1]{\marginpar[\tiny + \red{#1}]{\tiny \red{#1}}} +\newcommand{\commentarymark}[1]{\color{red} #1\ensuremath{^*}\color{black}} +\newcommand{\commentarymargintext}[2]{\color{red} #1$^*$ + \color{black}\marginpar[\tiny \red{\({}^*\)#2}]{\tiny \red{\({}^*\)#2}}} +\newcommand{\commentaryintext}[2]{\color{red} #1\textrm{$^*${\tiny #2}}\color{black}} +\newcommand{\commentarymath}[2]{\color{red} #1^*\color{black}\)\marginpar[\tiny \red{\({}^*\)#2}]{\tiny \red{\({}^*\)#2}}\(} +\newcommand{\replaced}[2]{\erased{#1}\inserted{#2}} +\newcommand{\erased}[1]{\commentary{\sout{#1}}} +\newcommand{\inserted}[1]{\color{red}#1\color{black}\xspace} + +\newcommand\Erase[1]{|#1|} +\newcommand\Angle[1]{\langle#1\rangle} + +\newcommand\TFGJ{FGJ-GT\xspace} +\newcommand\FGJGT{FGJ-GT\xspace} +\newcommand\FGJType{\textbf{FGJType} } + +\newcommand\TVX{\mv X} +\newcommand\TVY{\mv Y} +\newcommand\TVZ{\mv Z} +\newcommand\TVW{\mv W} + +\newcommand\CL[1]{\textit{Cl}$_{#1}$} +\newcommand\subconstr{\lessdot} +\newcommand\eqconstr{\doteq} +\newcommand\subeq{\mathbin{\texttt{<:}}} +\newcommand\extends{\ensuremath{\triangleleft}} + +\newcommand\rulename[1]{\textup{\textsc{(#1)}}} +\newcommand{\generalizeRule}{General} + +%%% FJ-IT Type rules +\newcommand{\environmentvdash}{\Pi;\Delta;\Gamma \vdash} + +\newcommand{\fjtypeinference}{\textbf{FJTypeInference}} + +%%% Commands for FGJTYPE algorithm +\newcommand{\tv}[1]{\mathit{ #1 }} +%\newcommand{\fjtypeInsert}{\textbf{FJTypeInsert}} +\newcommand{\unifyGenerics}{\ensuremath{\Delta}}% {\ensuremath{\overline{\type{G}\triangleleft \type{H}}}} +\newcommand{\fjtype}{\textbf{FJType}} +\newcommand{\unify}{\textbf{Unify}} +\newcommand{\typeMethod}{\textbf{TYPEMethod}} +\newcommand{\typeExpr}{\textbf{TYPEExpr}} +\newcommand{\constraint}{\ensuremath{\mathit{c}}}%{\ensuremath{\mathtt{C}}} +\newcommand{\consSet}{C}%{\ensuremath{\overline{\mathtt{C}}}} +\newcommand{\orCons}{\textit{oc}}%{\ensuremath{\textbf{C}_{||}}} +\newcommand{\simpleCons}{\textit{sc}} +\newcommand{\overridesFunc}{\textit{overrides}} +\newcommand{\typeAssumptionsSymbol}{\ensuremath{\Theta}} +\newcommand{\typeAssumptions}{\ensuremath{(\mv{\Pi} ; \overline{\localVarAssumption})}}%{\ensuremath{(\overline{\methodAssumption} ; \overline{\fieldAssumption}; \overline{\localVarAssumption})}} +\newcommand{\constraints}{\ensuremath{\mathit{\overline{c}}}} +\newcommand{\itype}[1]{\ensuremath{\mathit{#1}}} +\newcommand{\il}[1]{\ensuremath{\overline{\itype{#1}}}} +\newcommand{\type}[1]{\mathtt{#1}} +\newcommand{\anyType}[1]{\mathit{#1}} +\newcommand{\gType}[1]{\texttt{#1}} +\newcommand{\mtypeEnvironment}{\ensuremath{\Pi}} +\newcommand{\methodAssumption}{\ensuremath{\mathtt{\lambda}}} +\newcommand{\localVarAssumption}{\ensuremath{\mathtt{\eta}}} +\newcommand{\expandLB}{\textit{expandLB}} + +\def\exptypett#1#2{\texttt{#1}\textrm{{\tt <#2}}\textrm{{\tt >}}\xspace} +\def\exp#1#2{#1(\,#2\,)\xspace} +\newcommand{\ldo}{, \ldots , } + +% WILDCARD specific: +\newcommand{\xtype}[2]{\ensuremath{\exists #1 . \type{#2}}} +\newcommand{\xtypevar}[1]{\ensuremath{\exists \emptyset . \type{#1}}} + +\newcommand{\wtypestore}[3]{\ensuremath{#1 = \wtype{#2}{#3}}} +%\newcommand{\wtype}[2]{\ensuremath{[#1\ #2]}} +\newcommand{\wtv}[1]{\ensuremath{\tv{#1}_?}} +\newcommand{\wcstore}{\ensuremath{\Delta}} + +%\newcommand{\rwildcard}[1]{\ensuremath{\mathtt{#1}_?}} +\newcommand{\rwildcard}[1]{\ensuremath{\mathtt{#1}}} +\newcommand{\wildcardEnv}{\ensuremath{\mathbb{W}}} +\newcommand{\wildcard}[3]{\ensuremath{\mathtt{#1 : [#3 .. #2]}}} +\newcommand{\cwildcard}[3]{\ensuremath{\mathtt{\overleftarrow{#1}^{#2}_{#3}}}} + +\newcommand{\generics}[1]{\ensuremath{\mathtt{\texttt{<} {#1} \texttt{>} }}} + +\newcommand{\lessdotCC}{\ensuremath{\lessdot^{\texttt{c}}}} + +\newcommand{\ccDecaptureRule}{\rulename{CC-Decapture}} +\newcommand{\ccInvalidate}{\rulename{CC-Invalidate}} + +\newcommand{\ruleWCEquals}[0]{\rulename{WC-Equals}} +\newcommand{\ruleReduceWC}[0]{\rulename{Reduce}} +\newcommand{\ruleReduce}[0]{\rulename{Reduce}} +\newcommand{\ruleSubstWC}[0]{\rulename{Subst-WC}} +\newcommand{\subclass}{\mathtt{\sqsubset}\mkern-5mu :} + +\newcommand{\TameFJ}{\text{TameFJ}} +\newcommand{\TamedFJ}{\textbf{TamedFJ}} +\newcommand{\TYPE}{\textbf{TYPE}} + +\newcommand{\vdashI}[0]{\ \ . \kern-0.8em \vdash } + + +\newcommand{\wildcardTV}[1]{\type{#1}_?} +\newcommand{\replaceWC}[2]{\ensuremath{[#1/#2]_?}} +\newcommand{\replaceAdapt}[2]{\ensuremath{[#1/#2]_\uparrow}} + +\newcommand{\wcEnv}[3]{#1 : [#2\ ..\ #3]} +\newcommand{\fresh}[1]{\textit{fresh}(#1)} + + +\newcommand{\typerule}[1]{\small\textsc{#1}} +\newcommand{\letstmt}[2]{\texttt{let}\ #1 \ \texttt{in} \ #2} +\newcommand{\elvis}[0]{\ensuremath{\ {?}{:}\ }} + +\newcommand{\wildFJ}[0]{\textbf{WildFJ}} + +%\newcommand{\wfresh}[0]{\textit{wfresh}} + +%COLORS: +\definecolor{change}{RGB}{201,201,255} +\definecolor{subst}{RGB}{241,203,255} +\definecolor{addition}{RGB}{225,247,213} +\definecolor{highlight}{RGB}{255,189,189} +\definecolor{frame}{HTML}{634b7d} +%\definecolor{gray}{RGB}{120, 120, 120} +%\definecolor{frame}{RGB}{241, 246, 249} + +\tcbset{colback=white,colframe=frame,fonttitle=\bfseries,coltitle=white} + +\newcommand{\deduction}[2]{ + \begin{array}[c]{l} +#1 \\ +\hline +\vspace*{-0.4cm}\\ +#2 +\end{array} +} + +\newcommand{\nextdeduction}[1] + { + \begin{array}{@{}l@{}r@{}} + \begin{array}[c]{l} + \hline + \vspace*{-0.4cm}\\ + #1 + \end{array} % \rulename{#3} + \end{array} + } + +\newcommand{\subst}[2]{ +\left[ #1 / #2 \right] +} + +\newenvironment{constraintset} + { +\begin{tcolorbox} + } + { +\end{tcolorbox} + } + +\newcommand{\wcNtype}[2]{#1 .\ntype{#2}} +\newcommand{\wctype}[3]{#1 .\exptype{#2}{#3}} +\newcommand{\wtype}[1]{\mathit{#1}} +\newcommand{\ntype}[1]{\mathtt{#1}} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "TIforGFJ" +%%% End: diff --git a/soundness.tex b/soundness.tex new file mode 100644 index 0000000..13f4b36 --- /dev/null +++ b/soundness.tex @@ -0,0 +1,191 @@ +\section{Soundness} + + + +% %This lemma can be used to proof Normalize rule! +% \begin{lemma}\label{lemma:wildcardReplacement} +% Wildcards with the same upper and lower bound can be replaced by their bounds without breaking subtype relations. +% \begin{description} +% \item[If] $\Delta \cup \set{\wildcard{X}{\type{U}}{\type{L}}} \vdash \type{T} <: \type{S}$ +% \item[and] $\type{U} = \type{L}$ and $\text{fv}(\type{U}) = \emptyset$ +% \item[Then] $\Delta \vdash [\type{U}/\type{X}]\type{T} <: [\type{U}/\type{X}]\type{S}$ +% \end{description} +% \end{lemma} +% \textit{Proof:} %TODO +% %By structural induction over the subtype relation +% %S-Refl: by assumption L <: L implies [\type{U}/\type{X}]L + +% \begin{lemma}\label{lemma:noAdditionalFV} +% Type solution $\sigma$ does not add additional free variables. +% \begin{description} +% \item[If] $(\sigma, \Delta) = \unify{}( \overline{ \type{S} \lessdot \type{T} } \cup C)$ +% \item[and] $fv(\overline{ \type{S} }) = \emptyset$, $fv(\overline{ \type{T} }) = \emptyset$ +% \item[Then] $fv(\sigma(\overline{ \type{S} })) = \emptyset, fv(\sigma(\overline{ \type{T} })) = \emptyset$ +% \end{description} +% \end{lemma} + +% \begin{lemma} +% % https://math.libretexts.org/Bookshelves/Mathematical_Logic_and_Proof/Book%3A_Mathematical_Reasoning__Writing_and_Proof_(Sundstrom)/07%3A_Equivalence_Relations/7.03%3A_Equivalence_Classes +% $\doteq$ is an equivalence relation on a constraint set $C$. + +% \begin{description} +% \item[If] $\Delta \vdash \overline{\type{T} <: \type{S}}$ and $\type{T} \doteq \type{S}$ +% \item[Then] $\Delta \vdash [\type{T}/\type{S}](\overline{\type{T} <: \type{S}})$ +% \end{description} +% \end{lemma} + +\begin{lemma} +The \unify{} algorithm only produces correct output for constraints not containing free variables. + +\begin{description} +\item[If] $(\sigma, \Delta) = \unify{}( \overline{ \type{S} \lessdot \type{T} } \cup \overline{ \type{S'} \lessdot \type{T'} } )$ %\cup \overline{ \type{S} \doteq \type{S'} })$ +\item[and] $fv(\overline{ \type{S} }) = \emptyset$, $fv(\overline{ \type{T} }) = \emptyset$ +\item[Then] there exists a $\Delta'$ with: +$\Delta \vdash \overline{\sigma(\type{S}) <: \sigma(\type{T})}$ +and $\Delta, \Delta' \vdash \overline{\text{CC}(\sigma(\type{S'})) <: \sigma(\type{T'})}$ +% and $\sigma(\type{T'}) = \sigma(\type{T'})$. + +The function $\text{CC}$ is given as $\text{CC}(\wcNtype{\Delta}{N}) = \type{N}$ +\end{description} +\end{lemma} + +\textit{Proof:} +%(we are going backwards over the algorithm) +%first we have to determine the \Delta'' -> it's only the wildcards which are free in N +% during this proof we can use Delta'' as we like + +For every step in the \unify{} algorithm: +Assuming the unifier $\sigma$ is correct for a constraint set $C'$, the unifier is also correct for the +constraint set $C$ before the transformation. +\begin{description} +\item[Assumption:] $\unify{}(C) = (\Delta, \sigma)$, with $\Delta \vdash \sigma(C)$ +\item[Induction step:] For every case $C'$ which can be transformed to $C$ we have to show $\Delta \vdash \sigma(C')$ +\end{description} + +\unify{} terminates with $C = \emptyset$ for which the preposition holds: +$\Delta \vdash \sigma(\emptyset)$ + +We now show that for every transformation of a constraint set $C$ to a constraint set $C'$ +the preposition holds for $C$ using the assumption that it holds for $C'$ : +$\Delta \vdash \sigma(C') \implies \Delta \vdash \sigma(C)$ + +\begin{description} +\item[AddDelta] $C$ is not changed +\item[GenDelta] by definition, S-Var-Left, and S-Trans %The generated type variable is unique due to the solved form property. %and the solved form property (no $\tv{a}$ in $C$) +\item[GenSigma] by definition. +% holds for $\set{\tv{a} \doteq \type{G}}$ by definition. +% Holds for $C$ by assumption and because $\tv{a} \notin C$ by solved form definition ($[\type{G}/\tv{a}]C = C$). +\item[Ground] Assumption and S-Bot +\item[Sub-Elim] Assumption and S-Refl +\item[Force] by assumption and $\rwildcard{X} = \type{U}$ %TODO: step 5 should remove all X^T_T with T (make wildcards with same upper and lower bounds to normal types) +\item[Raise] Assumption, S-Trans +\item[Settle] Assumption, S-Trans +\item[Super] S-Extends ($\vdash \wctype{\Delta}{C}{\ol{T}} <: \wctype{\Delta}{D}{[\ol{T}/\ol{X}]\ol{N}}$), S-Trans +\item[\generalizeRule{}] by Assumption, because $C \subset C'$ +\item[Adapt] Assumption, S-Extends, S-Trans +\item[Adopt] Assumption, because $C \subset C'$ +%\item[Capture, Reduce] are always applied together. We have to destinct between two cases: +\item[Capture] +If $\text{fv}(\wctype{\Delta}{C}{\ol{T}}) = \emptyset$ the preposition holds by Assumption and S-Exists. +If $\text{fv}(\wctype{\Delta}{C}{\ol{T}}) \neq \emptyset$ we have to show $\Delta' \vdash \text{CC}(\sigma(\wctype{\overline{\wildcard{B}{\type{U'}}{\type{L'}}}}{C}{\ol{S}})) <: \sigma(\wctype{\Delta}{C}{\ol{T}})$, +which holds by assumption with $\Delta'$ chosen in a way that $\text{fv}(\exptype{C}{\ol{S}}) \subseteq \Delta'$. The variables $\ol{C}$ in $\ol{S}$ can be renamed to $\ol{B}$, because $\ol{C}$ are fresh. +%If $\text{fv}(\wctype{\Delta}{C}{\ol{T}}) \neq \emptyset$ we have to show $\Delta \vdash \sigma(\exptype{C}{\ol{S}}) <: \sigma(\wctype{\Delta}{C}{\ol{T}})$. +%$\Delta \vdash \sigma([\ol{C}/\ol{B}]\exptype{C}{\ol{S}}) <: \sigma(\wctype{\Delta}{C}{\ol{T}})$ holds by assumption and +%the variables $\ol{B}$ in $\ol{S}$ can be renamed to $\ol{C}$, because $\ol{C} \notin \ol{S}$ ($\ol{C}$ are fresh). +%The assumption implies $\text{fv}(\ol{S}) \subseteq \text{dom}(\Delta \cup \set{\overline{\wildcard{C}{\type{U'}}{\type{L'}}}})$ +%, which implies $\text{fv}(\ol{S}) \subseteq \text{dom}(\Delta \cup \set{\overline{\wildcard{B}{\type{U'}}{\type{L'}}}})$. + +%We are doing a capture conversion. If $\type{T}$ does not contain free variables, this does not affect the subtype relation. +\item[Reduce] %Assumption and S-Exists. +If $\text{fv}(\exptype{C}{\ol{S}}) = \emptyset$ the preposition holds by Assumption and S-Exists. +If $\text{fv}(\exptype{C}{\ol{S}}) \neq \emptyset$ there exists a $\Delta'$ with +$\Delta' \vdash \text{CC}(\sigma(\exptype{C}{\ol{S}})) <: \sigma(\wctype{\overline{\wildcard{A}{\type{U}}{\type{L}}}}{C}{\ol{T}})$. +\item[Match] Assumption, S-Trans +\item[Trim] Assumption and S-Exists +\item[Remove] $C$ is not changed +\item[Circle] S-Refl +\item[Swap] by definition +\item[Erase] S-Refl +\item[Equals] by definition +% \item[Reduce] +% The renaming from $\rwildcard{C}$ to $\rwildcard{B}$ is not a problem. It's allowed to rename wildcards inside a type. +% Removing $\rwildcard{C}$ from the environment does not change anything because it was freshly generated and is used nowhere. + +% The rest follows directly from S-Exists. +% We can say: $\text{fv}(\wctype{\overline{\wildcard{A}{\type{U}}{\type{L}}}}{C}{\ol{T}}) = \emptyset$, +% because the input to the \unify{} algorithm has no free type variables and we never substitute a type with free type variables +% and none of the other steps of the algorithm generates a $\lessdot$ constraint containing free type variables on the right side. %TODO: proof + +% $\text{fv}(\ol{T}) \subseteq \text{dom}(\wildcardEnv \cup \overline{\wildcard{B}{\type{U'}}{\type{L'}}})$ +% TODO: The capture conversion has to be when substituting a $\wtv{a}$ variable. Then we have to rename! +% %Lets first try it without the capture conversion. And involve the wtvs in the second step +% % The algorithm works by never substituting wildcards + + + +% \unify{} cannot guarantee the premise $\text{dom}(\Delta, \Delta') \cap \text{fv}(\wcNtype{\overline{\wildcard{X}{\type{U}}{\type{L}}}}{N}) = \emptyset$. +% We loosen the soundness requirements and allow a arbitrary environment $\Delta''$ to be added to the right side of the subtype relation. +% This is still sufficient to proof soundness for the whole algorithm. +% We show that the need for the additional environment $\Delta''$ can be satisfied by a let statement. + +% \begin{itemize} +% \item $\Delta, \Delta' \vdash [\ol{T}/\ol{X}]\ol{L} <: \ol{T}$: S-Exists +% \item $\Delta, \Delta' \vdash \ol{T} <: [\ol{T}/\ol{X}]\ol{U}$: S-Exists +% \item $\textit{fv}(\ol{T}) \subseteq \text{dom}{\Delta, \Delta'}$: $\wildcardEnv$ holds all variables %TODO: Proof +% \end{itemize} +\item[Normalize] Assumption and lemma 5 \emph{substitution preserves subtyping}.%\ref{lemma:wildcardReplacement}. (Or Lemma 5 from the wildcard paper. \emph{substitution preserves subtyping}) +% The GenSigma step replaces both sides of $\rwildcard{A} \doteq \rwildcard{B}$ with the upper bound $\type{U}$. +% This works for every constraint, whether it contains free variables or not. +% It does not add to free variables of constraints because the upper bound does not contain any. +The GenSigma and Gen Delta steps remove Wildcards which have the same upper and lower bound. +$\rwildcard{A},\rwildcard{B} \notin \sigma(C)$ + +% sigma(T) = sigma(U) we have to show that T = U means \Delta \vdash [T/U]C \implies \Delta \vdash [U/T]C +% the constraints L <. U, U <. L lead to L =. U +%If L is List with X being free wildcard +%then U <. L will fail if U is type variable + + + + +% this is because bounds never contain free variables (is that true?) + +%This type contains free variables when A is replaced by an CC wildcard + +%This must fail: +\begin{verbatim} + A m(List> l, A) + +m(List> l, "hi") +\end{verbatim} +%This fails because of Equals rule (TODO: proof) + +\item[Tame] same reasoning as Normalize +\item[Bot] S-Bot +\item[Pit] S-Bot +\item[Upper] S-Trans and S-VarLeft +\item[Lower] S-Trans and S-VerRight +\item[Subst-WC] by S-Refl +\item[Subst] +$\sigma(C \cup \set{\tv{a} \doteq \type{T}}) = \sigma([\type{T}/\tv{a}]C \cup \set{\tv{a} \doteq \type{T}})$ +and +$\sigma(\wildcardEnv) = \sigma([\type{T}/\tv{a}]\wildcardEnv)$ +\item[Subst-WC] +%Proof by Lemma 5 \emph{Type substitution preserves subtyping} from \cite{WildcardsNeedWitnessProtection}. +Same as Subst +\end{description} + +\subsection{Type Inference Soundness} +The type solution is a correct one in respect to the type rules. + +Problem: +The capture conversion and let statements. +Constraint a <. b => CC(X.C) <: C +Why is X the only type used + +$\type{T} \lessdot \type{S}$: +If the left part of the constraint has no free variables the solution $\sigma(\type{T})$ will have neither. +This means that all used type variables on both sides are bound in the global environment or the environment of the left side +%X.C <: C +%C = C (both sides must be the same) +%the left side has no free variables! \ No newline at end of file diff --git a/unify.tex b/unify.tex new file mode 100644 index 0000000..63a92ce --- /dev/null +++ b/unify.tex @@ -0,0 +1,1080 @@ + +\section{Unify}\label{sec:unify} +\newcommand{\gtype}[1]{\type{#1}} +%\newcommand{\tw}[1]{\tv{#1}_?} +The \unify{} algorithm computes the type solution. + +\begin{description} + \item[Input:] List of constraints $C = \set{ \type{T} \lessdot \type{T}, \type{T} \doteq \type{T} \ldots}$ + +The input constraints must be of the following format: + +\begin{tabular}{lcll} + $c $ &$::=$ & $\type{T} \lessdot \type{U}$ & Constraint \\ + $\type{T}, \type{U}, \type{L} $ & $::=$ & $\tv{a} \mid \wtv{a} \mid \ntype{N}$ & Type variable or Wildcard Variable or Type \\ + $\ntype{N}, \ntype{S}$ & $::=$ & $\wctype{\overline{\wildcard{X}{U}{L}}}{C}{\ol{T}} $ & Class Type \\ +\end{tabular}\\[0.5em] + +\noindent +Additional requirements: +\begin{itemize} + \item The input only consists of $\lessdot$ constraints +% \item No free variables in type parameters. +% A constraint like $\tv{a} \lessdot \exptype{List}{\rwildcard{X}}$ is prohibited. +% $\tv{a} \lessdot \wctype{\rwildcard{X}}{List}{\rwildcard{X}}$ is valid. + \item the input is a list of constraints. It cannot be a set. + A constraint set containing the constraint $\tv{a} \lessdot \type{T}$ twice + is a different to one that contains it only once. + %\item every wildcard is bound to its enclosing type. +\item Naming scheme of every wildcard environment has to be the same. +%TODO: We need this so that wildcard substitutions get the correct name. also the Equals rule needs this condition +%Example: +Although alpha renaming of wildcards inside a type is allowed by the type system the \unify{} algorithm never does it. +Renaming wildcards leads to additional problems in the substitution rules and in the result containing substitutions with renamed wildcards. +For the \rulename{Equals} to work properly it is adviced to name all wildcards in a specific scheme. +For example by numbering them according to their appereance inside the type parameters +(e.g. $\wctype{\rwildcard{1}, \rwildcard{2}}{Pair}{\rwildcard{1}, \rwildcard{2}}$). +\end{itemize} + +\item[Output:] +Set of unifiers $Uni = \set{\sigma_1, \ldots, \sigma_n}$ and an environment $\Delta$ +\end{description} + +The \unify{} algorithm internally uses the following data types: + +\begin{tabular}{lcll} + $C $ &$::=$ &$\overline{c}$ & Constraint set \\ + $c $ &$::=$ & $\type{T} \lessdot \type{T} \mid \type{T} \doteq \type{T}$ & Constraint \\ + $\type{T}, \type{U}, \type{L} $ & $::=$ & $\tv{a} \mid \wtv{a} \mid \gtype{G}$ & Type variable or Type \\ + $\gtype{G}$ & $::=$ & $\type{X} \mid \ntype{N}$ & Wildcard, or Class Type \\ + $\ntype{N}, \ntype{S}$ & $::=$ & $\wctype{\triangle}{C}{\ol{T}} $ & Class Type \\ + $\triangle$ & $::=$ & $\overline{\wtype{W}}$ & Wildcard Environment \\ + $\wtype{W}$ & $::=$ & $\wildcard{X}{U}{L}$ & Wildcard \\ +\end{tabular} + +The $\wtv{a}$ type variables are flagged as wildcard type variables. +These type variables can be substituted by a wildcard or a type with free wildcard variables. +As long as a type variable is flagged with as $\wtv{a}$ it will only be used by the subst-wc rule in step 1. +In step 2 all of the wildcard flags are dismissed. +The output therefore never contains these flags. + +\unify{} applies a capture conversion everywhere it is possible (see \rulename{Capture} rule). +Capture conversion removes a types bounding environment $\Delta$. +Type variables used in its type parameters are now bound to a global scope and not locally anymore. + +With \texttt{C} being class names and \texttt{A} being wildcard names. +The wildcard type $\wildcard{X}{U}{L}$ consist out of an upper bound $\type{U}$, a lower bound $\type{L}$ +and a name $\mathtt{X}$. + +The \rulename{Normalize} rule eliminates wildcards. % TODO +This is done by setting the upper and lower bound to the same value. +We generate wildcards with the \rulename{\generalizeRule} rule. +It is important to generate new wildcards in a standardized fashion. +When having two constraints $\type{T} \lessdot \tv{a}$ and $\type{T} \lessdot \tv{b}$, +then after applying the \rulename{\generalizeRule} rule the freshly generated constraints are +$\tv{a} \doteq \type{T'}, \tv{b} \doteq \type{T'}$. +Both type variables get assigned the same type. +This is necessary for the \rulename{Equals} rule to work properly. + + +\begin{figure} + \begin{center} + \leavevmode + \fbox{ + \begin{tabular}[t]{l@{~}l} + \rulename{Subst} & + $\begin{array}[c]{l} +\wildcardEnv \vdash C \cup \set{\tv{a} \doteq \type{T}}\\ + \hline +[\type{T}/\tv{a}]\wildcardEnv \vdash [\type{T}/\tv{a}] +C \cup \set{\tv{a} \doteq \type{T}} + \end{array} + \quad \begin{array}{c} + \tv{a} \notin \type{T} \\ + \text{fv}(\type{T}) = \emptyset + \end{array}$\\ +\\ +\rulename{Subst-WC} &$ + \begin{array}[c]{l} +\wildcardEnv \vdash C \cup \set{\wtv{a} \doteq \rwildcard{G}}\\ + \hline +[\type{G}/\wtv{a}]\wildcardEnv \vdash [\type{G}/\wtv{a}]C \cup \set{\tv{a} \doteq \type{G}} + \end{array} \quad \wtv{a} \notin \type{G} +$ +\end{tabular}} +\end{center} +\caption{Substitution rules}\label{fig:subst-rules} +\end{figure} + + +\begin{figure} + \begin{center} + \leavevmode + \fbox{ + \begin{tabular}[t]{l@{~}l} + % \rulename{normalize} + % & $ + % \begin{array}[c]{l} + % \wildcardEnv \cup \set{\wildcard{A}{\type{U}}{\type{L}}, \wildcard{B}{U'}{L'}} \vdash C \cup \, \set{ \rwildcard{A} \doteq \rwildcard{B} } \\ + % \hline + % \vspace*{-0.4cm}\\ + % \wildcardEnv \cup \set{\wildcard{A}{\type{U}}{\type{L}}, \wildcard{B}{U'}{L'}} \vdash C \cup \, \set{ \type{L} \doteq \type{U} , \type{U} \doteq \type{U'}, \type{L} \doteq \type{L'} } + % \end{array} + % $ + % \\\\ + \rulename{Upper} + & $ + \begin{array}[c]{l} + \wildcardEnv \cup \set{\wildcard{A}{U}{L}} \vdash C \cup \, \set{ \type{A} \lessdot \type{T} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \cup \set{\wildcard{A}{U}{L}} \vdash C \cup \, \set{ \type{U} \lessdot \type{T} } + \end{array} + $ + \\\\ + \rulename{Lower} + & $ + \begin{array}[c]{l} + \wildcardEnv \cup \set{\wildcard{A}{U}{L}} \vdash C \cup \set{ \type{T} \lessdot \type{A} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \cup \set{\wildcard{A}{U}{L}} \vdash C \cup \set{ \type{T} \lessdot \type{L} } + \end{array} + $ + \\\\ + \rulename{Bot} + & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \set{ \bot \lessdot \type{T} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \vdash C + \end{array} + $ + \\\\ + \rulename{Pit} + & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \set{ \tv{a} \lessdot \bot } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \vdash C \cup \set{ \tv{a} \doteq \bot } + \end{array} + $ + \\\\ +\end{tabular}} +\end{center} +\caption{Wildcard reduce rules}\label{fig:wildcard-rules} +\end{figure} + +\begin{figure} + \begin{center} + \leavevmode + \fbox{ + \begin{tabular}[t]{l@{~}l} +\rulename{normalize} + & $ + \begin{array}[c]{l} + \wildcardEnv \cup \set{\wildcard{A}{\type{U}}{\type{L}}, \wildcard{B}{U'}{L'}} \vdash C \cup \, \set{ \rwildcard{A} \doteq \rwildcard{B} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \cup \set{\wildcard{A}{\type{U}}{\type{L}}, \wildcard{B}{U'}{L'}} \vdash C \cup \, \set{ \type{L} \doteq \type{U} , \type{U'} \doteq \type{L'}, \type{U} \doteq \type{U'} } + \end{array} \quad + \text{fv}(\type{U}, \type{U'}, \type{L}, \type{L'}) = \emptyset + $ + \\\\ +\rulename{Tame} + & $ + \begin{array}[c]{l} + \wildcardEnv \cup \set{\wildcard{A}{\type{U}}{\type{L}}} \vdash C \cup \, \set{ \rwildcard{A} \doteq \type{T} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \cup \set{\wildcard{A}{\type{U}}{\type{L}}} \vdash C \cup \, \set{ \type{L} \doteq \type{T}, \type{U} \doteq \type{T} } + \end{array} \quad \text{fv}(\type{U}, \type{L}) = \emptyset + $ + \\\\ + % \rulename{Equals} %TODO + % & $ + % \begin{array}[c]{l} + % \wildcardEnv \vdash C \cup \, \set{ \type{N} \doteq \type{N'} } \\ + % \hline + % \vspace*{-0.4cm}\\ + % \wildcardEnv \vdash C \cup \, + % \set{ + % \type{N} \lessdot \type{N'}, \type{N'} \lessdot \type{N} + % } + % \end{array} \quad \text{fv}(\type{N}) = \text{fv}(\type{N'}) = \emptyset + % $ + % \\\\ + \rulename{Equals} %TODO + & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \, \set{ \wctype{\Delta}{C}{\ol{T}} \doteq \wctype{\Delta}{C}{\ol{T'}} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \vdash C \cup \, + \set{ + % \pi(\ol{T}) \doteq \pi(\ol{T'} ) + \ol{T} \doteq \ol{T'} + } + \end{array} +% \quad \begin{array}{l} +% \text{given a permutation}\ \pi\ \text{with:}\\ +% \pi(\Delta) = \pi(\Delta') +% \end{array} + $ + \\\\ + \rulename{Erase} + & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \, \set{ \type{T} \doteq \type{T} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \vdash C + \end{array} + $ + \\\\ + \rulename{Erase} + & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \, \set{ \type{T} \lessdot \type{T} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \vdash C + \end{array} + $ + \\\\ + \rulename{Swap} & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \set{\type{G} \doteq \tv{a}}\\ + \hline + \wildcardEnv \vdash C \cup \set{\tv{a} \doteq \type{G}} + \end{array} + \quad + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \set{\type{G} \doteq \wtv{a}}\\ + \hline + \wildcardEnv \vdash C \cup \set{\wtv{a} \doteq \type{G}} + \end{array} \quad + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \set{\type{N} \doteq \rwildcard{A}}\\ + \hline + \wildcardEnv \vdash C \cup \set{\rwildcard{A} \doteq \type{N}} + \end{array}$ + \\\\ +\rulename{Circle} & $ +\begin{array}[c]{l} + \wildcardEnv \vdash C \cup \, \set{\tv{a}_1 \lessdot + \tv{a}_2, \tv{a}_2 \lessdot \tv{a}_3, \dots, \tv{a}_n \lessdot \tv{a}_1}\\ + \hline + \wildcardEnv \vdash C \cup \, \set{\tv{a}_1 \doteq \tv{a}_2, \tv{a}_2 \doteq \tv{a}_3, \dots , \tv{a}_n \doteq \tv{a}_1} +\end{array} \quad n>0 + $ +\end{tabular}} +\end{center} +\caption{Constraint normalize rules}\label{fig:normalizing-rules} +\end{figure} + +The \rulename{match} rule generates fresh wildcards $\overline{\wildcard{A}{\tv{u}}{\tv{l}}}$. +Their upper and lower bounds are fresh type variables. + +%Unify only renames the wildcards in the reduce rule +% It's the only place where wildcards are coming into play (theres always a reduce step before a wildcard substitution is possible) + + +% die wildcard variablen sollten erst am Ende ausgetauscht werden gegen normale variablen +% das funktioniert, da die im Reduce step erstellten direkt substituiert werden +% die anderen erlauben Capture Conversion aber nur wenn der Methodentyp und Parametertyp schon feststeht! (gleich Mächtig wie TI in Java) +% a? <. T -> +% T <. a? -> +% a? =. T -> substitute! +% bei normalen Typvariablen werden keine Wildcards substituiert + +% \begin{tcolorbox} +% $ +% \wctype{\rwildcard{X}}{Box}{\rwildcard{X}} \lessdot \exptype{Box}{\tv{a}_?}, \\ +% \exptype{Box}{\tv{a}_?} \lessdot \wctype{\rwildcard{X}}{Box}{\rwildcard{X}} +% $ +% \end{tcolorbox} + +\begin{figure} +\begin{center} + \fbox{ + \begin{tabular}[t]{l@{~}l} + \rulename{Remove} + & $ + \begin{array}[c]{@{}ll} + \begin{array}[c]{l} + \wildcardEnv \vdash C \\ + % \cup \, \set{ \wtv{a} \lessdot \type{T} }\\ + \hline + \vspace*{-0.4cm}\\ +\wildcardEnv \vdash [\tv{a}/\wtv{a}]C + \end{array} + &\begin{array}[c]{l} + \wtv{a} \in C \\ + \tv{a} \ \text{fresh} + \end{array} + \end{array} + $ + \\\\ + % \rulename{Trim} + % & $ + % \begin{array}[c]{@{}ll} + % \begin{array}[c]{l} + % \wildcardEnv \vdash C + % \cup \, \set{ \wcNtype{\Delta}{N} \lessdot \wctype{\Delta', \wildcard{B}{\type{U}}{\type{L}}}{C}{\ol{S}} }\\ + % \hline + % \vspace*{-0.4cm}\\ + % C \cup \, \set{ \wcNtype{\Delta}{N} \lessdot \wctype{\Delta'}{C}{\ol{S}} } + % \end{array} + % &\begin{array}[c]{l} + % \rwildcard{B} \notin \ol{S} + % \end{array} + % \end{array} + % $ + % \\\\ + \end{tabular}} + \end{center} +\caption{Wildcard variable substitution rules}\label{fig:wtv-rules} +\end{figure} + +\begin{figure} + \begin{center} + \leavevmode + \fbox{ + \begin{tabular}[t]{l@{~}l} + \rulename{Match} + & $ + \begin{array}[c]{@{}ll} + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \, \set{ + \tv{a} \lessdot \wctype{\Delta}{D}{\ol{T}}, \tv{a} \lessdot \wctype{\Delta'}{D'}{\ol{T'}} }\\ + \hline + \vspace*{-0.4cm}\\ +\wildcardEnv \vdash C \cup \, \left\{ \begin{array}[c]{l} + \tv{a} \lessdot \wctype{\overline{\wildcard{A}{\tv{u}}{\tv{l}}}}{C}{\overline{\rwildcard{A}}}, + \ol{\tv{l}} \lessdot \ol{\tv{u}}, \\ + \wctype{\overline{\wildcard{A}{\tv{u}}{\tv{l}}}}{C}{\overline{\rwildcard{A}}} + \lessdot \wctype{\Delta}{D}{\ol{T}}, \\ + \wctype{\overline{\wildcard{A}{\tv{u}}{\tv{l}}}}{C}{\overline{\rwildcard{A}}} + \lessdot \wctype{\Delta'}{D'}{\ol{T'}} +\end{array} +\right\} + \end{array} + &\begin{array}[c]{l} + \text{fresh}\ \overline{\wildcard{A}{\tv{u}}{\tv{l}}} \\ + \type{C} \ll \type{D}\\ + \type{C} \ll \type{D'} % TODO: THe match rule has to pick the most general type for C + \end{array} + \end{array} + $ + \\\\ + \ruleReduceWC{} + & + $ + \begin{array}[c]{@{}ll} + \begin{array}[c]{l} + \wildcardEnv \vdash + C \cup \, \set{ \exptype{C}{\ol{S}} \lessdot + \wctype{\overline{\wildcard{A}{\type{U}}{\type{L}}}}{C}{\ol{T}} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv + \vdash C \cup \, \set{ + \ol{\type{S}} \doteq [\ol{\wtv{a}}/\overline{\rwildcard{A}}]\ol{\type{T}}, + \ol{\wtv{a}} \lessdot [\ol{\wtv{a}}/\overline{\rwildcard{A}}]\ol{U}, [\ol{\wtv{a}}/\overline{\rwildcard{A}}]\ol{L} \lessdot \ol{\wtv{a}} } + \end{array} + %\quad \ol{Y} = \textit{fresh}(\ol{X}) + \quad \begin{array}[c]{l} + \ol{\wtv{a}} \ \text{fresh}\\ + %\text{fv}(\exptype{C}{\ol{S}}) \subseteq \text{dom}(\overline{\wildcard{B}{\type{U'}}{\type{L'}}}) + %\text{dom}(\overline{\wildcard{A}{\type{U}}{\type{L}}}) \subseteq \text{fv}(\exptype{C}{\ol{T}}) \\ + %\text{fv}(\wctype{\overline{\wildcard{A}{\type{U}}{\type{L}}}}{C}{\ol{T}}) = \emptyset + \end{array} + \end{array} + $ + \\\\ + \rulename{Capture} + & + $ + \begin{array}[c]{@{}ll} + \begin{array}[c]{l} + \wildcardEnv \vdash + C \cup \, \set{ \wctype{\overline{\wildcard{B}{\type{U'}}{\type{L'}}}}{C}{\ol{S}} \lessdot \wctype{\Delta}{C}{\ol{T}} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \cup \overline{\wildcard{C}{\type{U'}}{\type{L'}}} + \vdash C \cup \, \set{ + [\ol{\rwildcard{C}}/\ol{\rwildcard{B}}] \exptype{C}{\ol{S}} \lessdot \wctype{\Delta}{C}{\ol{T}} } + \end{array} + %\quad \ol{Y} = \textit{fresh}(\ol{X}) + \quad \begin{array}[c]{l} + \ol{\rwildcard{C}} \ \text{fresh}\\ + %\text{fv}(\type{T}) \neq \emptyset + \end{array} + \end{array} + $ + \\\\ + \rulename{Adopt} + & $ + \begin{array}[c]{@{}ll} + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \, \set{ + \tv{b} \lessdot \tv{a}, +\tv{a} \lessdot \type{N}, \tv{b} \lessdot \type{N'}} \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \vdash C \cup \, \set{ + \tv{b} \lessdot \type{N}, + \tv{b} \lessdot \tv{a}, +\tv{a} \lessdot \type{N} , \tv{b} \lessdot \type{N'} + } + \end{array} + \end{array} + $ + \\\\ + \rulename{Adapt} + & + $ + \begin{array}[c]{@{}ll} + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \, \set{ \wctype{\Delta}{C}{\ol{T}} \lessdot + \wctype{\Delta'}{D'}{\ol{T'}} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \vdash C \cup \, \set{ \wctype{\Delta}{D}{[\ol{\type{T}}/\ol{X}]\ol{S}} \lessdot \wctype{\Delta'}{D'}{\ol{T'}} } + + \end{array} + & \begin{array}[c]{l} + \type{C} \ll \type{D'} \\ + \texttt{class} \ \exptype{C}{\ol{X} \triangleleft \ol{N}} \triangleleft \exptype{D}{\ol{S}} + \end{array} + \end{array} + $ + \end{tabular}} + \end{center} +\caption{Constraint reduce rules}\label{fig:reduce-rules} +\end{figure} + +The new constraint generated by the adopt rule may be eliminated by the match rule. +The adopt rule still needs to be applied only once per constraint. + +Wildcards consist out of three parts. +A name, a scope and a upper and lower bound. + +% The \unify{} algorithm from \cite{plue09_1} substitutes type variables with wildcards. +% A constraint $\wctype{\wildcard{X}{\type{Object}}{\bot}}{C}{\rwildcard{X}} \lessdot \exptype{C}{\tv{a}}$ +% has no solution. +% Replacing the type variable $\tv{a}$ with the wildcard $\rwildcard{X}$ is not correct! +% The wildcard $\rwildcard{X}$ cannot leave its scope and the type $\exptype{C}{\rwildcard{X}}$ +% is considered invalid. + +Wildcards are not reflexive. A box of type $\wctype{\rwildcard{X}}{Box}{\rwildcard{X}}$ +is able to hold a value of any type. It could be a $\exptype{Box}{String}$ or a $\exptype{Box}{Integer}$ etc. +Also two of those boxes do not necessarily contain the same type. +But there are situations where it is possible to assume that. +For example the type $\wctype{\rwildcard{X}}{Pair}{\exptype{Box}{\rwildcard{X}}, \exptype{Box}{\rwildcard{X}}}$ +is a pair of two boxes, which always contain the same type. +Inside the scope of the \texttt{Pair} type, the wildcard $\rwildcard{X}$ stays the same. + +The algorithm starts with an empty wildcard environment $\wildcardEnv{}$. +Only the reduce rule adds wildcards to that environment. +And every added wildcard gets a fresh unique name. +This ensures the wildcard environment $\wildcardEnv{}$ never +gets the same wildcard twice. + +When a new type is generated by the \unify{} algorithm it always has the form +$\wctype{\ol{\rwildcard{A}}}{C}{\ol{\rwildcard{A}}}$. + +\textbf{Step 1:} +Apply the rules depicted in the figures \ref{fig:normalizing-rules}, \ref{fig:reduce-rules} and \ref{fig:wildcard-rules} exhaustively. +Starting with the \rulename{circle} rule. Afterwards the other rules in figure \ref{fig:normalizing-rules}. + +The first step of the algorithm is able to remove wildcards. +Removing a wildcard works by setting its lower and upper bound to be equal. +(Def: $\type{Object} = \wildcard{A}{Object}{Object}$). +The \rulename{Equals} rule is responsible for this. + +\textbf{Example:} +\begin{displaymath} + \begin{array}[c]{@{}ll} + \begin{array}[c]{l} + \wildcardEnv \cup \set{ \wildcard{X}{\tv{u}}{\tv{l}} } \vdash + C \cup \, \set{ \type{Object} \doteq \type{X}, \tv{l} \lessdot \tv{u} } \\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \cup \set{ \wildcard{X}{\tv{u}}{\tv{l}} } \vdash C \cup \, + \set{\type{Object} \lessdot \type{X}, \type{X} \lessdot \type{Object}, \tv{l} \lessdot \tv{u} + }\\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \cup \set{ \wildcard{X}{\tv{u}}{\tv{l}} } \vdash C \cup \, + \set{\type{Object} \lessdot \tv{l}, \tv{u} \lessdot \type{Object}, \tv{l} \lessdot \tv{u} + }\\ + \hline + \vspace*{-0.4cm}\\ + \ldots\\ + \hline + \vspace*{-0.4cm}\\ + \wildcardEnv \cup \set{ \wildcard{X}{\type{Object}}{\type{Object}} } \vdash C \\ + \end{array} + \end{array} +\end{displaymath} + +\begin{description} +\item [$\ll$ relation:] +The $\ll$ relation is the reflexive and transitive closure of the \texttt{extends} relations: +\begin{displaymath} + \begin{array}[c]{c} +\exptype{C}{\ol{X} \triangleleft \ol{N}} \triangleleft \exptype{D}{\ol{N}} \\ +\hline +\vspace*{-0.4cm}\\ +\texttt{C} \ll \texttt{D} +\end{array} +\quad +\begin{array}[c]{l} + \\ +\hline +\vspace*{-0.4cm}\\ +\texttt{C} \ll \texttt{C} +\end{array} +\quad +\begin{array}[c]{l} +\texttt{C} \ll \texttt{D}, \texttt{D} \ll \texttt{E} \\ +\hline +\vspace*{-0.4cm}\\ +\texttt{C} \ll \texttt{E} +\end{array} +\end{displaymath} +The algorithm uses it to determine if two types are possible subtypes of one another. +This is needed in the \rulename{adapt} and \rulename{match} rules. + +%\textbf{Wildcard renaming}\\ +\item[Wildcard renaming:] +The \rulename{reduce} rule separates wildcards from their environment. +At this point each wildcard gets a new and unique name. +To only rename the respective wildcards the reduce rule renames wildcards up to alpha conversion: +($[\ol{C}/\ol{B}]$ in the \rulename{reduce} rule) +\begin{align*} + [\type{A}/\type{B}]\type{B} &= \type{A} \\ + [\type{A}/\type{B}]\type{C} &= \type{C} & \text{if}\ \type{B} \neq \type{C}\\ + [\type{A}/\type{B}]\wcNtype{\Delta}{N} &= \wcNtype{\Delta}{[\type{A}/\type{B}]N} & \text{if}\ \type{B} \notin \Delta \\ + [\type{A}/\type{B}]\wcNtype{\Delta}{N} &= \wcNtype{\Delta}{N} & \text{if}\ \type{B} \in \Delta \\ +\end{align*} + +\item[Free Variables:] +The $\text{fv}$ function assumes every wildcard type variable to be a free variable aswell. + +%\textbf{Fresh Wildcards}\\ +\item[Fresh Wildcards:] +$\text{fresh}\ \overline{\wildcard{A}{\tv{u}}{\tv{l}}}$ generates fresh wildcards. +The new names $\ol{A}$ are fresh, aswell as the type variables $\ol{\tv{u}}$ and $\ol{\tv{l}}$, +which are used for the upper and lower bounds. +\end{description} +% \noindent +% \textbf{Example: (reduce-rule)} +% %The \ruleReduceWC{} resembles the \texttt{S-Exists} subtyping rule. +% %It converts wildcard types to fresh type variables. +% %For example take the input constraint $\exptype{Pair}{\ntype{Object},\tv{b}} \lessdot \wctype{\wildcard{A}{\tv{c}}{\tv{d}}}{Pair}{\wildcard{A}{\tv{c}}{\tv{d}},\wildcard{A}{\tv{c}}{\tv{d}}}$. +% %First we apply the \ruleReduceWC{} rule, which replaces $\wildcard{A}{\tv{c}}{\tv{d}}$ with a fresh type variable $\tv{a}$: +% We assume the input constraints $C = \exptype{Pair}{\ntype{Object},\tv{b}} \lessdot \wctype{\wildcard{A}{\tv{c}}{\tv{d}}}{Pair}{\wildcard{A}{\tv{c}}{\tv{d}},\wildcard{A}{\tv{c}}{\tv{d}}}$. +% The type on the right side $\wctype{\wildcard{A}{\tv{c}}{\tv{d}}}{Pair}{\wildcard{A}{\tv{c}}{\tv{d}},\wildcard{A}{\tv{c}}{\tv{d}}}$ +% \begin{align*} +% \ddfrac{ +% \exptype{Pair}{\ntype{Object},\tv{b}} \lessdot \wctype{\wildcard{A}{\tv{c}}{\tv{d}}}{Pair}{\wildcard{A}{\tv{c}}{\tv{d}},\wildcard{A}{\tv{c}}{\tv{d}}} +% }{ +% \ntype{Object} \doteq \tv{a}, \tv{b} \doteq \tv{a}, \tv{a} \lessdot \tv{c}, \tv{d} \lessdot \tv{a} +% } \ruleReduceWC{} +% \end{align*} + +% By substition we get the result: % $\tv{a} \doteq \type{Object}$, $\tv{a} \doteq \type{Object}$, $\ldots$. + +% \begin{align*} +% \ddfrac{ +% \ntype{Object} \doteq \tv{a}, \tv{b} \doteq \tv{a}, \tv{a} \lessdot \tv{c}, \tv{d} \lessdot \tv{a} +% }{ +% \tv{a} \doteq \ntype{Object} , \tv{b} \doteq \ntype{Object}, \ntype{Object} \lessdot \tv{c}, \tv{d} \lessdot \ntype{Object} +% } \rulename{Subst} +% \end{align*} +% \\[1em] + +\noindent +\textbf{Step 2:} +%If there are no $(\type{T} \lessdot \tv{a})$ constraints remaining in the constraint set $C$ +%resume with step 4. + +The rules in figure \ref{fig:step2-rules} offer multiple possibilities to deal with constraints of the form $\type{N} \lessdot \tv{a}$. +This builds a search tree over multiple possible solutions. +\unify{} has to try each branch and accumulate the resulting solutions into a solution set. + +\begin{figure} +\begin{center} + \fbox{ + \begin{tabular}[t]{l@{~}l} + \rulename{\generalizeRule} + & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \wctype{\Delta}{C}{\ol{T}} \lessdot \tv{a}\\ + \hline + \wildcardEnv \vdash C \cup \set{\wctype{\Delta}{C}{\ol{T}} \lessdot \tv{a}, + \tv{a} \doteq \wctype{\overline{\wildcard{X}{\tv{u}}{\tv{l}}}}{C}{\overline{\rwildcard{X}}}, + %\overline{\tv{l} \lessdot \tv{u}}, % not needed, due to subst and reduce rule which are used afterwards + \overline{\tv{u} \lessdot \type{S}} + } + \end{array} \quad \begin{array}[c]{l} + \texttt{class} \ \exptype{C}{\ol{X \triangleleft \type{S}}} \triangleleft \exptype{D}{\ol{N}} \\ + \text{fresh}\ \overline{\wildcard{X}{\tv{u}}{\tv{l}}} + \end{array} + $ + \\\\ + \rulename{Super} + & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \wctype{\Delta}{C}{\ol{T}} \lessdot \tv{a}\\ + \hline + \wildcardEnv \vdash C \cup \set{ \wctype{\Delta}{D}{[\ol{T}/\ol{X}]\ol{N}} \lessdot \tv{a} } + %\set{\wctype{\ol{\wtype{W}}}{D}{[\ol{X}/\ol{Y}]\ol{Z}} \lessdot \tv{a}} + \end{array} \quad + \begin{array}{l} + \texttt{class} \ \exptype{C}{\ol{X}} \triangleleft \exptype{D}{\ol{N}} \\ + \ol{X} \notin \wildcardEnv \cup \Delta + \end{array} + $ + \\\\ + \rulename{Settle} + & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \set{ \tv{a} \lessdot \type{N}, + \tv{a} \lessdot^* \tv{b}} + \\ + \hline + \wildcardEnv \vdash C \cup \set{ \tv{a} \lessdot^* \tv{b}, \tv{b} \lessdot \type{N} } + \end{array} + $ + \\\\ + \rulename{Raise} + & $ + \begin{array}[c]{l} + \wildcardEnv \vdash C \cup \set{ \tv{a} \lessdot \type{N}, + \tv{a} \lessdot \tv{b}} + \\ + \hline + \wildcardEnv \vdash C \cup \set{\tv{a} \lessdot \type{N}, \type{N} \lessdot \tv{b} } + \end{array} + $ + \\\\ + \end{tabular}} + \end{center} +\caption{Step 2 branching: Multiple rules can be applied to the same constraint} +\label{fig:step2-rules} +\end{figure} + + +%For every $\type{T} \lessdot \tv{a}$ constraint, the unify algorithm has to consider every possible supertype of $\type{T}$. +%For every $\type{N}$ with $\type{T} \leq \type{N}$: ($\texttt{class} \ \exptype{T}{\ol{Y} \triangleleft \ol{N}} \triangleleft \type{N}$) +%There are two different ways of handling a $\type{T} \lessdot \tv{a}$ constraint: +%TODO: why the \generalizeRule is basically the Same rule for regular type placeholders + +% Replacing regular type placeholders causes problems related to method calls and capture conversion. + +% List same(List a, List b){} + +% \begin{lstlisting} +% List f; +% List problem(){ +% return same(problem(), problem()) ?: f; +% } +% \end{lstlisting} +% \begin{constraints} +% r <. List +% r <. List +% X.List <. r +% \end{constraints} +% %TODO + +\unify{} generates wildcard types for constraints of the form $\type{N} \lessdot \tv{a}$ with the \rulename{\generalizeRule} rule. +Otherwise only the wildcards already defined in the input constraints will be included in the result. +\rulename{\generalizeRule} attempts to give $\tv{a}$ a more general type by replacing only the type parameters with fresh wildcards. +The second variation sets $\tv{a}$ to the direct supertype of type \texttt{C}. +For the constraint $\texttt{Object} \lessdot \tv{a}$ the algorithm can only apply $\tv{a} \doteq \texttt{Object}$, +because \texttt{Object} has no other supertype than itself. + +Constraints of the form $\set{ \tv{a} \lessdot \type{N}, \tv{a} \lessdot^* \tv{b}}$ +need to be handled in a similiar fashion. +The type variable $\tv{b}$ could either be a sub or a supertype of the type $\type{N}$. +We have to consider both possibilities. +\\[1em] +% The specification of the \unify{} algorithm has only two rules generating $\doteq$-Constraints +% , \rulename{Reduce} and \rulename{Ground}. +% $\doteq$-Constraints and the accompaning substitutions are dangerous respective to the soundness of the algorithm. +% For the soundness proof of the \unify{} algorithm we have to show every generation of equals constraints +% and the subsequent application of the \rulename{subst} rule is correct. +% We try to use them as sparsely as possible to simplify the soundness proof. +% You can notice this at \rulename{Equals} or \rulename{Force}: +% Instead of setting $\type{U} \doteq \type{L}$, we say +% $\type{U} \lessdot \type{L}, \type{L} \lessdot \type{U}$. + +\noindent +\textbf{Step 3} +\textbf{(Eliminate Wildcard Variables):} +If no more rules in step 2 are applicable \unify{} has to eliminate all wildcard variables +and start over at step 1. +If $C$ does not contain any wildcard variables the algorithm proceeds with step 4. + +We apply the \rulename{Clean} rule exhaustively to $C''$: +\begin{gather*} + \begin{array}[c]{lll} + \rulename{Clean} & +\begin{array}[c]{l} + \wildcardEnv \vdash C\\ + \hline + [\tv{a}/\wtv{a}]\wildcardEnv, [\tv{a}/\wtv{a}]\sigma \vdash [\tv{a}/\wtv{a}]C %\cup \set{\tv{b} \doteq \tv{a}} +\end{array} +\quad \wtv{a} \in C +\end{array} +\end{gather*} + +% \begin{gather*} +% \begin{array}[c]{lll} +% \rulename{Subst} & +% \begin{array}[c]{l} +% \wildcardEnv \vdash C \cup \set{\tv{a} \doteq \wctype{\triangle}{C}{\ol{T}}}\\ +% \hline +% [\wctype{\triangle}{C}{\ol{T}}/\tv{a}]\wildcardEnv \vdash [\wctype{\triangle}{C}{\ol{T}}/\tv{a}] +% C \cup \set{\tv{a} \doteq \wctype{\triangle}{C}{\ol{T}}} +% \end{array} +% & \tv{a} \notin \ol{T} \\ +% & \\ +% \rulename{Subst-wc} & +% \begin{array}[c]{l} +% \wildcardEnv \vdash C \cup \set{\tv{a} \doteq \rwildcard{A}}\\ +% \hline +% [\rwildcard{A}/\tv{a}]\wildcardEnv \vdash [\rwildcard{A}/\tv{a}] C \cup \set{\tv{a} \doteq \rwildcard{A}} +% \end{array} +% \end{array} +% \end{gather*} + +%or $\type{T}$ is not of the form $\wctype{\triangle}{C}{\ol{G}}$ with $\text{fv}(\ol{G}) = \emptyset$. +%Here the $\text{fv}(\ol{G})$ also applies to type variables. +%$\tv{x} \doteq \exptype{C}{\tv{a}}$ is invalid, because $\tv{a}$ could become a free wildcard in that context. + +\noindent +\textbf{Step 4:} +We apply the rules in figure \ref{fig:cleanup-rules} exhaustively and proceed with step 5. +%and start over at step 1. +%If the constraint set is in solved form afterwards the algorithm proceeds with step 5. + +\begin{figure} + \begin{center} + \leavevmode + \fbox{ + \begin{tabular}[t]{l@{~}l} + \rulename{SubElim} + & $\begin{array}[c]{l} + \wildcardEnv \vdash C \cup \set{\tv{a} \lessdot \tv{b}}\\ + \hline + [\tv{a}/\tv{b}]\wildcardEnv \vdash [\tv{a}/\tv{b}]C \cup \set{ \tv{b} \doteq \tv{a} } + \end{array} + $ + \\\\ +\rulename{Ground} +& $\begin{array}[c]{@{}ll} +\begin{array}[c]{l} + \wildcardEnv \cup \overline{\set{\wildcard{X}{\type{U}}{\tv{a}}}} \vdash C \cup \, \set{ + \overline{\tv{a} \lessdot \type{T}} } \\ +\hline +\vspace*{-0.4cm}\\ +\wildcardEnv \cup \overline{\set{\wildcard{X}{\type{U}}{\bot}}} \vdash +C \cup \set{ \tv{a} \doteq \bot } +\end{array} +&\begin{array}[c]{l} +%\forall \wctype{\Delta}{C}{\ol{T}} \in C: \tv{a} \notin \ol{T} \\ +\tv{a} \notin C, \, \rwildcard{X} \notin C, \, \tv{a} \notin \overline{T} %\\ +%\text{length}( \overline{\tv{a} \lessdot \type{T}} ) > 1 +\end{array} +\end{array}$ +\\\\ +\rulename{Crunch} +& $\begin{array}[c]{@{}ll} +\begin{array}[c]{l} +\wildcardEnv \vdash C \cup \, \set{ \tv{a} \doteq \wctype{\Delta', \set{\overline{\wildcard{X}{\type{U}}{\type{L}}}}}{C}{\ol{S}} } \\ +\hline +\vspace*{-0.4cm}\\ +\wildcardEnv \vdash +C \cup \set{ \tv{a} \doteq \wctype{\Delta'}{C}{[\ol{U}/\ol{X}]\ol{S}}} +\end{array} +&\begin{array}[c]{l} + \ol{U} = \ol{L} +\end{array} +\end{array}$ +\\\\ +\rulename{Crunch} +& $\begin{array}[c]{@{}ll} +\begin{array}[c]{l} +\wildcardEnv \vdash C \cup \, \set{ \tv{a} \lessdot \wctype{\Delta', \set{\overline{\wildcard{X}{\type{U}}{\type{L}}}}}{C}{\ol{S}} } \\ +\hline +\vspace*{-0.4cm}\\ +\wildcardEnv \vdash +C \cup \set{ \tv{a} \lessdot \wctype{\Delta'}{C}{[\ol{U}/\ol{X}]\ol{S}}} +\end{array} +&\begin{array}[c]{l} + \ol{U} = \ol{L} +\end{array} +\end{array}$ +% \\\\ % The force rule is unnecessary because every type placeholder has an upper bound Object (a <. Object) The match rule eliminates those wildcards +% \rulename{Force} &$ +% \begin{array}[c]{@{}ll} +% \begin{array}[c]{l} +% \wildcardEnv \cup \set{\wildcard{X}{\type{U}}{\type{L}}} +% \vdash C \cup \, \set{ +% \tv{a} \lessdot \type{N} } \\ +% \hline +% \vspace*{-0.4cm}\\ +% \wildcardEnv +% \vdash +% C \cup \, \set{ \tv{a} \lessdot [\type{U}/\rwildcard{X}]\type{N}, +% \type{U} \doteq \type{L} } +% \end{array} +% &\begin{array}[c]{l} +% \type{X} \in \text{fv}(\type{N}) \\ +% %\Delta' = \Delta \cup \set{\wildcard{X}{\type{U}}{\type{L}}} +% \end{array} +% \end{array}$ +% \\\\ +% \rulename{FlatOut} &$ +% \begin{array}[c]{@{}ll} +% \begin{array}[c]{l} +% \wildcardEnv \cup \set{\wildcard{X}{\type{U}}{\type{L}}} +% \vdash C \cup \, \set{ +% \tv{a} \lessdot \wcNtype{\Delta}{N} } \\ +% \hline +% \vspace*{-0.4cm}\\ +% \wildcardEnv \cup \set{\wildcard{X}{\type{U}}{\type{L}}} +% \vdash +% C +% \end{array} +% &\begin{array}[c]{l} +% \type{X} \in \text{fv}(\wcNtype{\Delta}{N}) \\ +% \tv{a} \notin C , \, \tv{a} \notin \wildcardEnv, \tv{a} \notin \sigma +% \end{array} +% \end{array}$ + \end{tabular}} +\end{center} +\caption{Cleanup rules}\label{fig:cleanup-rules} +\end{figure} + +The cleanup step prepares the constraint set for the last step by applying the following concepts: +%Two transformations are done which also help to remove unnecessary types from the solution set. +\begin{description} +\item[Bottom type] +The bottom type $\bot$ is used to generate \texttt{? extends} wildcard definitions. +This is the only possible solution when dealing with multiple upper bounds: +$\tv{a} \lessdot \type{T}, \tv{a} \lessdot \type{S}$ is usually not a correct solution (given $\type{S}$ and $\type{T}$ are no subtypes of eachother). +But if $\tv{a}$ is a lower bound of a wildcard it can be set to $\bot$. +Those constraints only stay in the constraint set after the first step if $\type{S}$ and $\type{T}$ do not have a common subtype. +The \rulename{Ground} rule uses this concept to generate \texttt{extends} Wildcards. + +\item[Eliminating Wildcards] +Wildcards that have the same upper and lower bounds can be removed. +This is done by the \rulename{Crunch} rule. + +\textit{Example:} The type $\wctype{\wildcard{X}{\type{String}}{\type{String}}}{List}{\rwildcard{X}}$ +becomes $\exptype{List}{\type{String}}$. + + +%TODO: The a =. T (with T containing free variables) could be removed here. +% Not needed for the soundness of the algorithm, but handy for the implementation (check this when implementing the algorithm) +\end{description} + +\noindent +\textbf{Step 5 (Generating Result):} +Apply the rules in figure \ref{fig:generation-rules} until $\wildcardEnv = \emptyset$ and $C = \emptyset$. +The resulting $\Delta, \sigma$ is a correct solution. + +For this step to succeed there should only be four kinds of constraints left. +\begin{enumerate} +%\item\label{item:3} $\tv{a} \lessdot \tv{b}$ %, with $a$ and $b$ both isolated type variables +\item $\tv{a} \doteq \tv{b}$ +%\item $\wtv{a} \doteq \type{G}$ +\item\label{item:1} $\tv{a} \lessdot \wctype{\ol{\wtype{W}}}{C}{\ol{\type{T}}}$, with $\text{fv}(\wctype{\ol{\wtype{W}}}{C}{\ol{\type{T}}}) = \emptyset$ +\item\label{item:2} $\tv{a} \doteq \wctype{\ol{\wtype{W}}}{C}{\ol{\type{T}}}$, with $\tv{a} \notin \ol{\type{T}}$ % and $\text{fv}(\wctype{\ol{\wtype{W}}}{C}{\ol{\type{T}}}) = \emptyset$ +\item\label{item:3} $\tv{a} \doteq \rwildcard{X}$ +\end{enumerate} +% Constraints of the form $\tv{a} \doteq \rwildcard{X}$ are also possible. +% should we add those to the \Delta environment? +% How about removing them completely from the result set? Check with soundness condition + +%Each type placeholder $\tv{a}$ must solely appear on the left side of a constraint. +\unify{} fails if there is any $\tv{a} \doteq \type{T}$ such that $\tv{a}$ occurs in $\type{T}$. +For the cases \ref{item:1}, \ref{item:2}, and \ref{item:3} the placeholder $\tv{a}$ +cannot appear anywhere else in the constraint set. +Otherwise the generation rules \rulename{GenSigma} and \rulename{GenDelta} will not be able to process every constraint. + +% After applying the GenDelta and GenSigma rules unifiers $\sigma$ do not contain +% a unifier of the form $\tv{a} \to \tv{b}$. +% Otherwise the found solution is incorrect. +% This only happens if the input constraints contain type variables with no upper bound constraint like $\tv{a} \lessdot \type{N}$. + +% \begin{displaymath} +% \deduction{ +% \wildcardEnv \cup \set{\wildcard{B}{\type{G}}{\type{G'}}} \vdash C \implies \Delta, \sigma +% }{ +% \wildcardEnv \vdash C \implies \Delta \cup \set{\wildcard{B}{\type{G}}{\type{G'}}}, \sigma +% }\quad \text{tph}(\type{G}) = \emptyset, \text{tph}(\type{G'}) = \emptyset, +% \rwildcard{B} \notin \text{dom}(\Delta) +% \quad \rulename{AddDelta} +% \end{displaymath} + +\begin{figure} +\begin{center} + \fbox{ + \begin{tabular}[t]{l@{~}l} + \rulename{GenDelta} + & $ + \deduction{ + \wildcardEnv \vdash C \cup \set{\tv{b} \lessdot \type{N} } \implies \Delta, \sigma + }{ + \wildcardEnv \vdash [\type{B}/\tv{b}]C \implies \Delta \cup \set{\wildcard{B}{\type{N}}{\bot}}, \sigma \cup \set{\tv{b} \to \type{B}} + } \quad + \begin{array}{l} + \text{tph}(\type{N}) = \emptyset, \text{fv}(\type{N}) = \emptyset \\ + \rwildcard{B} \ \text{fresh}, \tv{b} \notin \text{dom}(\sigma) + \end{array} + $ + \\\\ + \rulename{AddSigma} + & $ + \deduction{ + \wildcardEnv \vdash C \cup \set{\tv{a} \doteq \rwildcard{X}} \implies \Delta, \sigma + }{ + \wildcardEnv \vdash C \cup \set{\tv{a} \doteq \rwildcard{X}} \implies \Delta, \sigma + \cup \set{\tv{a} \to \rwildcard{X}} + } + $ + \\\\ + \rulename{GenSigma} + & $ + \deduction{ + \wildcardEnv \vdash C \cup + \set{\tv{a} \doteq \type{T} } \implies \Delta, \sigma + }{ + \wildcardEnv \vdash C \implies \Delta, \sigma \cup + \set{\tv{a} \to \type{T} } + } \quad + \begin{array}{l} + \text{tph}(\type{T}) = \emptyset \\ + \tv{a} \notin \text{dom}(\sigma) + \end{array} + $ + \\\\ + \end{tabular}} + \end{center} +\caption{Generate result} +\label{fig:generation-rules} +\end{figure} + +%TODO: Solved form is obsolete due to GenSigma/GenDelta +% \begin{figure} +% \begin{description} +% \item[Solved form] +% A set $C$ of constraints is in solved form if it only contains +% constraints of the following form: +% \begin{enumerate} +% %\item\label{item:3} $\tv{a} \lessdot \tv{b}$ %, with $a$ and $b$ both isolated type variables +% \item $\tv{a} \doteq \tv{b}$ +% %\item $\wtv{a} \doteq \type{G}$ +% \item\label{item:1} $\tv{a} \lessdot \wctype{\ol{\wtype{W}}}{C}{\ol{\type{T}}}$, with $\text{fv}(\wctype{\ol{\wtype{W}}}{C}{\ol{\type{T}}}) = \emptyset$ +% \item\label{item:2} $\tv{a} \doteq \wctype{\ol{\wtype{W}}}{C}{\ol{\type{T}}}$, with $\tv{a} \notin \ol{\type{T}}$ % and $\text{fv}(\wctype{\ol{\wtype{W}}}{C}{\ol{\type{T}}}) = \emptyset$ +% \end{enumerate} +% %Each type variable $\tv{a}$ can only appear once on a left side of a constraint. +% In case~\ref{item:1} the type variable $\tv{a}$ must not appear on the left of another constraint. +% In case~\ref{item:2} the type variabel $\tv{a}$ must not appear anywhere else in the constraint set $C$. +% % of the form~\ref{item:1} or~\ref{item:2} or ~\ref{item:3} . +% \end{description} +% \caption{Solved form definition}\label{def:solved-form} +% \end{figure} + +% Wildcards with the same name are interlinked. +% The \ruleReduceWC{} replaces all wildcards with the same name with type variables. +% We also use the fact that wildcards of the same name represent the same type at all times. +% So we can erase them in the \rulename{Same} rule. + +% We have to ensure that every wildcard definition is unique. +% When substituting types, every time a type with wildcard definitions is added somewhere, we have to rename those wildcards. + +%\subsection{Unify as Pseudocode} +% The subst rule can be applied multiple times to the same constraint, but its better to mark the a =. T constraint to do it only once +% The step 3 has to clone the constraint set and the wildcard environment and try every way + +% \section{High-Level rules} +% The \unify{} specification tries to be as simple as possible +% with each rule doing only one simple transformation. +% We define additional transformation rules, which deviate directly from the given algorithm. +% They come to use in the examples section. + +% \begin{figure} +% \begin{center} +% \leavevmode +% \fbox{ +% \begin{tabular}[t]{l@{~}l} +% \rulename{Encase} +% & $ +% \deduction{ +% \wildcardEnv \vdash C \cup \set{ \exptype{C}{\type{T}} \lessdot \wctype{\wildcard{X}{\type{U}}{\type{L}}}{C}{\rwildcard{X}} } +% }{ +% \wildcardEnv \vdash \subst{\type{T}}{\tv{x}}C \cup \set{ \type{T} \lessdot \type{U}, \type{L} \lessdot \type{T} } +% } +% $ +% \\\\ +% \rulename{Flatten} +% & $ +% \deduction{ +% \wildcardEnv \vdash C \cup \set{ \type{T} \lessdot \tv{a}, \tv{a} \lessdot \type{T} } +% }{ +% \wildcardEnv \vdash \subst{\type{T}}{\tv{a}}C \cup \set{ \tv{a} \doteq \type{T} } +% } +% $ +% \\\\ +% \rulename{Assimilate} +% & $ +% \deduction{ +% \wildcardEnv \vdash C \cup \set{\wctype{\wildcard{X}{\tv{u}}{\tv{l}}}{C}{\rwildcard{X}} \lessdot \exptype{C}{\type{T}}, \tv{l} \lessdot \tv{u} } +% }{ +% \wildcardEnv \vdash +% C \cup \set{\tv{u} \doteq \type{T}, \tv{l} \doteq \type{T}} +% } +% $ +% \\\\ +% \rulename{Narrow} +% & +% $\deduction{ +% \wildcardEnv \vdash C \cup \set{ +% \wctype{\wildcard{X}{\type{U}}{\type{L}}}{C}{\rwildcard{X}} \lessdot \wctype{\wildcard{X}{\type{U'}}{\type{L'}}}{C}{\rwildcard{X}} +% } +% }{ +% \wildcardEnv \vdash C \cup \set{ +% \type{L'} \lessdot \type{L}, \type{U} \lessdot \type{U'} +% } +% }$ +% \\\\ +% \rulename{Redeem} +% & +% $\deduction{ +% \wildcardEnv \vdash C \cup \set{\wctype{\Delta}{C}{\rwildcard{X}} \lessdot \wctype{\wildcard{X}{\type{Object}}{\bot}}{C}{\rwildcard{X}}} +% }{ +% \wildcardEnv \vdash C +% }$ +% \\\\ +% \rulename{Standoff} +% & +% $\deduction{ +% \wildcardEnv \cup \set{ \wildcard{X}{\type{U}}{\type{L}}, \wildcard{Y}{\type{U'}}{\type{L'}} } \vdash \rwildcard{X} \doteq \rwildcard{Y} +% }{ +% \wildcardEnv \cup \set{ \wildcard{X}{\type{U}}{\type{L}}, \wildcard{Y}{\type{U'}}{\type{L'}} } \vdash \rwildcard{U} \lessdot \type{L'}, \type{U'} \lessdot \type{L} +% }$ +% \\\\ +% \end{tabular}} +% \end{center} +% \caption{Common transformations}\label{fig:wildcard-rules} +% \end{figure}

|9U??eVep2)xb5KN?*YiRpD?er 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 PF#79X|8;RLef|FcC1s?p literal 0 HcmV?d00001 diff --git a/lipics-v2021.cls b/lipics-v2021.cls new file mode 100644 index 0000000..9107039 --- /dev/null +++ b/lipics-v2021.cls @@ -0,0 +1,1260 @@ +%% +%% This is file `lipics-v2021.cls'. +%% +%% ----------------------------------------------------------------- +%% Author: Dagstuhl Publishing & le-tex publishing services +%% +%% This file is part of the lipics package for preparing +%% LIPICS articles. +%% +%% Copyright (C) 2021 Schloss Dagstuhl +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `maintained'. +%% +%% The Current Maintainer of this work is +%% Schloss Dagstuhl (publishing@dagstuhl.de). +%% ----------------------------------------------------------------- +%% +\ProvidesClass{lipics-v2021} + [2023/05/12 v3.1.3 LIPIcs articles] +\NeedsTeXFormat{LaTeX2e}[2015/01/01] +\emergencystretch1em +\advance\hoffset-1in +\advance\voffset-1in +\advance\hoffset2.95mm +\newif\if@nobotseplist \@nobotseplistfalse +\def\@endparenv{% + \addpenalty\@endparpenalty\if@nobotseplist\else\addvspace\@topsepadd\fi\@endpetrue} +\def\@doendpe{% + \@endpetrue + \def\par{\@restorepar + \everypar{}% + \par + \if@nobotseplist + \addvspace\topsep + \addvspace\partopsep + \global\@nobotseplistfalse + \fi + \@endpefalse}% + \everypar{{\setbox\z@\lastbox}% + \everypar{}% + \if@nobotseplist\global\@nobotseplistfalse\fi + \@endpefalse}} +\def\enumerate{% + \ifnum \@enumdepth >\thr@@\@toodeep\else + \advance\@enumdepth\@ne + \edef\@enumctr{enum\romannumeral\the\@enumdepth}% + \expandafter + \list + \csname label\@enumctr\endcsname + {\advance\partopsep\topsep + \topsep\z@\@plus\p@ + \ifnum\@listdepth=\@ne + \labelsep0.72em + \else + \ifnum\@listdepth=\tw@ + \labelsep0.3em + \else + \labelsep0.5em + \fi + \fi + \usecounter\@enumctr\def\makelabel##1{\hss\llap{##1}}}% + \fi} +\def\endenumerate{\ifnum\@listdepth=\@ne\global\@nobotseplisttrue\fi\endlist} +\def\itemize{% + \ifnum \@itemdepth >\thr@@\@toodeep\else + \advance\@itemdepth\@ne + \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}% + \expandafter + \list + \csname\@itemitem\endcsname + {\advance\partopsep\topsep + \topsep\z@\@plus\p@ + \ifnum\@listdepth=\@ne + \labelsep0.83em + \else + \ifnum\@listdepth=\tw@ + \labelsep0.75em + \else + \labelsep0.5em + \fi + \fi + \def\makelabel##1{\hss\llap{##1}}}% + \fi} +\def\enditemize{\ifnum\@listdepth=\@ne\global\@nobotseplisttrue\fi\endlist} +\def\@title{\textcolor{red}{Author: Please provide a title}} +\let\@subtitle\@empty +\def\subtitle#1{\gdef\@subtitle{#1}} +\def\subtitleseperator{: } +\def\@sect#1#2#3#4#5#6[#7]#8{% + \ifnum #2>\c@secnumdepth + \let\@svsec\@empty + \else + \refstepcounter{#1}% + \protected@edef\@svsec{\@seccntformat{#1}\relax}% + \fi + \@tempskipa #5\relax + \ifdim \@tempskipa>\z@ + \begingroup + #6{% + \@hangfrom{\hskip #3\relax + \ifnum #2=1 + \colorbox{lipicsYellow}{\kern0.15em\@svsec\kern0.15em}\quad + \else + \@svsec\quad + \fi}% + \interlinepenalty \@M #8\@@par}% + \endgroup + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7}% + \else + \def\@svsechd{% + #6{\hskip #3\relax + \@svsec #8}% + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7}}% + \fi + \@xsect{#5}} +\def\@seccntformat#1{\csname the#1\endcsname} +\def\@biblabel#1{\textcolor{lipicsGray}{\sffamily\bfseries#1}} +\def\EventLogoHeight{25} +\def\copyrightline{% + \ifx\@hideLIPIcs\@undefined + \ifx\@EventLogo\@empty + \else + \setbox\@tempboxa\hbox{\includegraphics[height=\EventLogoHeight\p@]{\@EventLogo}}% + \rlap{\hspace\textwidth\hspace{-\wd\@tempboxa}\hspace{\z@}% + \vtop to\z@{\vskip-0mm\unhbox\@tempboxa\vss}}% + \fi + \scriptsize + \vtop{\hsize\textwidth + \nobreakspace\par + \@Copyright + \ifx\@EventLongTitle\@empty\else\@EventLongTitle.\\\fi + \ifx\@EventEditors\@empty\else + \@Eds: \@EventEditors + ; Article~No.\,\@ArticleNo; pp.\,\@ArticleNo:\thepage--\@ArticleNo:\number\numexpr\getpagerefnumber{TotPages}% + \\ + \fi + \setbox\@tempboxa\hbox{\IfFileExists{lipics-logo-bw.pdf}{\includegraphics[height=14\p@,trim=0 15 0 0]{lipics-logo-bw}}{\includegraphics[height=14\p@, width=62pt]{example-image-plain}}}% + \hspace*{\wd\@tempboxa}\enskip + \href{https://www.dagstuhl.de/lipics/}% + {Leibniz International Proceedings in Informatics}\\ + \smash{\unhbox\@tempboxa}\enskip + \href{https://www.dagstuhl.de}% + {Schloss Dagstuhl -- Leibniz-Zentrum f{\"u}r Informatik, Dagstuhl Publishing, Germany}}% + \fi} +\def\ps@plain{\let\@mkboth\@gobbletwo + \let\@oddhead\@empty + \let\@evenhead\@empty + \let\@evenfoot\copyrightline + \let\@oddfoot\copyrightline} +\def\lipics@opterrshort{Option "\CurrentOption" not supported} +\def\lipics@opterrlong{The option "\CurrentOption" from article.cls is not supported by lipics.cls.} +\DeclareOption{a5paper}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{b5paper}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{legalpaper}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{executivepaper}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{landscape}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{10pt}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{11pt}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{12pt}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{oneside}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{twoside}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{titlepage}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{notitlepage}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{onecolumn}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{twocolumn}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{fleqn}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{openbib}{\@latexerr{\lipics@opterrshort}{\lipics@opterrlong}} +\DeclareOption{a4paper}{\PassOptionsToClass{\CurrentOption}{article} + \advance\hoffset-2.95mm + \advance\voffset8.8mm} +\DeclareOption{numberwithinsect}{\let\numberwithinsect\relax} +\DeclareOption{cleveref}{\let\usecleveref\relax} +\DeclareOption{autoref}{\let\useautoref\relax} +\DeclareOption{anonymous}{\let\authoranonymous\relax} +\DeclareOption{thm-restate}{\let\usethmrestate\relax} +\DeclareOption{authorcolumns}{\let\authorcolumns\relax} +\let\compactauthor\relax +\DeclareOption{oldauthorstyle}{\let\compactauthor\@empty} +\DeclareOption{compactauthor}{\let\compactauthor\relax} +\DeclareOption{pdfa}{\let\pdfa\relax} +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}} +\ProcessOptions +\LoadClass[twoside,notitlepage,fleqn]{article} +\renewcommand\normalsize{% + \@setfontsize\normalsize\@xpt{13}% + \abovedisplayskip 10\p@ \@plus2\p@ \@minus5\p@ + \abovedisplayshortskip \z@ \@plus3\p@ + \belowdisplayshortskip 6\p@ \@plus3\p@ \@minus3\p@ + \belowdisplayskip \abovedisplayskip + \let\@listi\@listI} +\normalsize +\renewcommand\small{% + \@setfontsize\small\@ixpt{11.5}% + \abovedisplayskip 8.5\p@ \@plus3\p@ \@minus4\p@ + \abovedisplayshortskip \z@ \@plus2\p@ + \belowdisplayshortskip 4\p@ \@plus2\p@ \@minus2\p@ + \def\@listi{\leftmargin\leftmargini + \topsep 4\p@ \@plus2\p@ \@minus2\p@ + \parsep 2\p@ \@plus\p@ \@minus\p@ + \itemsep \parsep}% + \belowdisplayskip \abovedisplayskip +} +\renewcommand\footnotesize{% + \@setfontsize\footnotesize{8.5}{9.5}% + \abovedisplayskip 6\p@ \@plus2\p@ \@minus4\p@ + \abovedisplayshortskip \z@ \@plus\p@ + \belowdisplayshortskip 3\p@ \@plus\p@ \@minus2\p@ + \def\@listi{\leftmargin\leftmargini + \topsep 3\p@ \@plus\p@ \@minus\p@ + \parsep 2\p@ \@plus\p@ \@minus\p@ + \itemsep \parsep}% + \belowdisplayskip \abovedisplayskip +} +\renewcommand\large{\@setfontsize\large{10.5}{13}} +\renewcommand\Large{\@setfontsize\Large{12}{14}} +\setlength\parindent{1.5em} +\setlength\headheight{3mm} +\setlength\headsep {10mm} +\setlength\footskip{3mm} +\setlength\textwidth{140mm} +\setlength\textheight{222mm} +\setlength\oddsidemargin{32mm} +\setlength\evensidemargin{38mm} +\setlength\marginparwidth{25mm} +\setlength\topmargin{13mm} +\setlength{\skip\footins}{2\baselineskip \@plus 4\p@ \@minus 2\p@} +\def\@listi{\leftmargin\leftmargini + \parsep\z@ \@plus\p@ + \topsep 8\p@ \@plus2\p@ \@minus4\p@ + \itemsep \parsep} +\let\@listI\@listi +\@listi +\def\@listii {\leftmargin\leftmarginii + \labelwidth\leftmarginii + \advance\labelwidth-\labelsep + \topsep 4\p@ \@plus2\p@ \@minus\p@ + \parsep\z@ \@plus\p@ + \itemsep \parsep} +\def\@listiii{\leftmargin\leftmarginiii + \labelwidth\leftmarginiii + \advance\labelwidth-\labelsep + \topsep 2\p@ \@plus\p@\@minus\p@ + \parsep \z@ + \partopsep \p@ \@plus\z@ \@minus\p@ + \itemsep \z@ \@plus\p@} +\def\ps@headings{% + \def\@evenhead{\large\sffamily\bfseries + \llap{\hbox to0.5\oddsidemargin{ \ifx\@hideLIPIcs\@undefined\ifx\@ArticleNo\@empty\textcolor{red}{XX}\else\@ArticleNo\fi:\fi\thepage\hss}}\leftmark\hfil}% + \def\@oddhead{\large\sffamily\bfseries\rightmark\hfil + \rlap{\hbox to0.5\oddsidemargin{\hss \ifx\@hideLIPIcs\@undefined\ifx\@ArticleNo\@empty\textcolor{red}{XX}\else\@ArticleNo\fi:\fi\thepage}}}% + \def\@oddfoot{\hfil + \rlap{% + \vtop{% + \vskip10mm + \colorbox{lipicsYellow} + {\@tempdima\evensidemargin + \advance\@tempdima1in + \advance\@tempdima\hoffset + \hb@xt@\@tempdima{% + \ifx\@hideLIPIcs\@undefined + \textcolor{lipicsGray}{\normalsize\sffamily + \bfseries\quad + \expandafter\textsolittle + \expandafter{\@EventShortTitle}}% + \fi + \strut\hss}}}}} + \let\@evenfoot\@empty + \let\@mkboth\markboth + \let\sectionmark\@gobble + \let\subsectionmark\@gobble} +\pagestyle{headings} +\renewcommand\maketitle{\par + \begingroup + \thispagestyle{plain} + \renewcommand\thefootnote{\@fnsymbol\c@footnote}% + \if@twocolumn + \ifnum \col@number=\@ne + \@maketitle + \else + \twocolumn[\@maketitle]% + \fi + \else + \newpage + \global\@topnum\z@ % Prevents figures from going at top of page. + \@maketitle + \fi + \thispagestyle{plain}\@thanks + \endgroup + \global\let\thanks\relax + \global\let\maketitle\relax + \global\let\@maketitle\relax + \global\let\@thanks\@empty + \global\let\@author\@empty + \global\let\@date\@empty + \global\let\@title\@empty + \global\let\@subtitle\@empty + \global\let\title\relax + \global\let\author\relax + \global\let\date\relax + \global\let\and\relax +} +\newwrite\tocfile +\def\@maketitle{% + \newpage + \null\vskip-\baselineskip + \vskip-\headsep + \@titlerunning + \@authorrunning + %%\let \footnote \thanks + \parindent\z@ \raggedright + \if!\@title!\def\@title{\textcolor{red}{Author: Please fill in a title}}\fi + {\LARGE\sffamily\bfseries\mathversion{bold}\@title \if!\@subtitle!\else{\\\Large\sffamily\bfseries\mathversion{bold}\@subtitle}\fi \par}% + \vskip 1em + \ifx\@author\orig@author + \textcolor{red}{Author: Please provide author information}% + \else + {\def\thefootnote{\@arabic\c@footnote}% + \setcounter{footnote}{0}% + \fontsize{9.5}{12}\selectfont\@author}% + \fi + \bgroup + \immediate\openout\tocfile=\jobname.vtc + \protected@write\tocfile{ + \let\footnote\@gobble + \let\thanks\@gobble + \def\footnotemark{} + \def\and{and }% + \def\,{ } + \def\\{ } + }{% + \string\contitem + \string\title{\@title \if!\@subtitle!\else\subtitleseperator \@subtitle\fi}% + \string\author{\@authorsfortoc}% + \string\page{\@ArticleNo:\thepage--\@ArticleNo:\number\numexpr\getpagerefnumber{TotPages}}}% + \closeout\tocfile + \egroup + \par} +\renewcommand\tableofcontents{% + \section*{\contentsname}% + \@starttoc{toc}} +\setcounter{secnumdepth}{4} +\renewcommand\section{\@startsection {section}{1}{\z@}% + {-3.5ex \@plus -1ex \@minus -.2ex}% + {2.3ex \@plus.2ex}% + {\sffamily\Large\bfseries\raggedright}} +\renewcommand\subsection{\@startsection{subsection}{2}{\z@}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\sffamily\Large\bfseries\raggedright}} +\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\sffamily\Large\bfseries\raggedright}} +\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}% + {-3.25ex \@plus-1ex \@minus-.2ex}% + {1.5ex \@plus .2ex}% + {\sffamily\large\bfseries\raggedright}} +\renewcommand\subparagraph{\@startsection{subparagraph}{5}{\z@}% + {3.25ex \@plus1ex \@minus .2ex}% + {-1em}% + {\sffamily\normalsize\bfseries}} +\newcommand{\proofsubparagraph}{\@startsection{subparagraph}{5}{\z@}% + {3.25ex \@plus1ex \@minus .2ex}% + {-1em}% + {\color{lipicsGray}\sffamily\normalsize\bfseries}} +\setlength\leftmargini \parindent +\setlength\leftmarginii {1.2em} +\setlength\leftmarginiii{1.2em} +\setlength\leftmarginiv {1.2em} +\setlength\leftmarginv {1.2em} +\setlength\leftmarginvi {1.2em} +\renewcommand\labelenumi{% + \textcolor{lipicsGray}{\sffamily\bfseries\upshape\mathversion{bold}\theenumi.}} +\renewcommand\labelenumii{% + \textcolor{lipicsGray}{\sffamily\bfseries\upshape\mathversion{bold}\theenumii.}} +\renewcommand\labelenumiii{% + \textcolor{lipicsGray}{\sffamily\bfseries\upshape\mathversion{bold}\theenumiii.}} +\renewcommand\labelenumiv{% + \textcolor{lipicsGray}{\sffamily\bfseries\upshape\mathversion{bold}\theenumiv.}} +\renewcommand\labelitemi{% + \textcolor{lipicsBulletGray}{\ifnum\@listdepth=\@ne + \rule{0.67em}{0.33em}% + \else + \rule{0.45em}{0.225em}% + \fi}} +\renewcommand\labelitemii{% + \textcolor{lipicsBulletGray}{\rule{0.45em}{0.225em}}} +\renewcommand\labelitemiii{% + \textcolor{lipicsBulletGray}{\sffamily\bfseries\textasteriskcentered}} +\renewcommand\labelitemiv{% + \textcolor{lipicsBulletGray}{\sffamily\bfseries\textperiodcentered}} +\renewenvironment{description} + {\list{}{\advance\partopsep\topsep\topsep\z@\@plus\p@ + \labelwidth\z@ \itemindent-\leftmargin + \let\makelabel\descriptionlabel}} + {\ifnum\@listdepth=\@ne\global\@nobotseplisttrue\fi\endlist} +\renewcommand*\descriptionlabel[1]{% + \hspace\labelsep\textcolor{lipicsGray}{\sffamily\bfseries\mathversion{bold}#1}} +\def\topmattervskip{0.7} +\renewenvironment{abstract}{% + \vskip\topmattervskip\bigskipamount + \noindent + \rlap{\color{lipicsLineGray}\vrule\@width\textwidth\@height1\p@}% + \hspace*{7mm}\fboxsep1.5mm\colorbox[rgb]{1,1,1}{\raisebox{-0.4ex}{% + \large\selectfont\sffamily\bfseries\abstractname}}% + \vskip3\p@ + \fontsize{9}{12}\selectfont + \noindent\ignorespaces} + {\vskip\topmattervskip\baselineskip\noindent + \subjclassHeading + \ifx\@ccsdescString\@empty + \textcolor{red}{Author: Please fill in 1 or more \string\ccsdesc\space macro}% + \else + \@ccsdescString + \fi + \vskip\topmattervskip\baselineskip + \noindent\keywordsHeading + \ifx\@keywords\@empty + \textcolor{red}{Author: Please fill in \string\keywords\space macro}% + \else + \@keywords + \fi + \ifx\@hideLIPIcs\@undefined + \ifx\@DOIPrefix\@empty\else + \vskip\topmattervskip\baselineskip\noindent + \doiHeading\href{https://doi.org/\@lipicsdoi}{\@lipicsdoi}% + \fi + \fi + \ifx\@category\@empty\else + \vskip\topmattervskip\baselineskip\noindent + \categoryHeading\@category + \fi + \ifx\@relatedversion\@empty\else + \vskip\topmattervskip\baselineskip\noindent + \relatedversionHeading\ifx\authoranonymous\relax\textcolor{red}{Anonymous related version(s)}\else\@relatedversion\fi + \fi + \ifx\@supplement\@empty\else + \vskip\topmattervskip\baselineskip\noindent + \supplementHeading\ifx\authoranonymous\relax\textcolor{red}{Anonymous supplementary material}\else\@supplement\fi + \fi + \ifx\@funding\@empty\else + \vskip\topmattervskip\baselineskip\noindent + \fundingHeading\ifx\authoranonymous\relax\textcolor{red}{Anonymous funding}\else\@funding\fi + \fi + \ifx\@acknowledgements\@empty\else + \vskip\topmattervskip\baselineskip\noindent + \acknowledgementsHeading\ifx\authoranonymous\relax\textcolor{red}{Anonymous acknowledgements} \else\@acknowledgements\fi + \fi + \protected@write\@auxout{}{\string\gdef\string\@pageNumberEndAbstract{\thepage}}% + }% end abstract +\renewenvironment{thebibliography}[1] + {\if@noskipsec \leavevmode \fi + \par + \@tempskipa-3.5ex \@plus -1ex \@minus -.2ex\relax + \@afterindenttrue + \@tempskipa -\@tempskipa \@afterindentfalse + \if@nobreak + \everypar{}% + \else + \addpenalty\@secpenalty\addvspace\@tempskipa + \fi + \noindent + \rlap{\color{lipicsLineGray}\vrule\@width\textwidth\@height1\p@}% + \hspace*{7mm}\fboxsep1.5mm\colorbox[rgb]{1,1,1}{\raisebox{-0.4ex}{% + \normalsize\sffamily\bfseries\refname}}% + \@xsect{1ex \@plus.2ex}% + \list{\@biblabel{\@arabic\c@enumiv}}% + {\leftmargin8.5mm + \labelsep\leftmargin + \settowidth\labelwidth{\@biblabel{#1}}% + \advance\labelsep-\labelwidth + \usecounter{enumiv}% + \let\p@enumiv\@empty + \renewcommand\theenumiv{\@arabic\c@enumiv}}% + \fontsize{9}{12}\selectfont + \sloppy + \clubpenalty4000 + \@clubpenalty \clubpenalty + \widowpenalty4000% + \sfcode`\.\@m\protected@write\@auxout{}{\string\gdef\string\@pageNumberStartBibliography{\thepage}}} + {\def\@noitemerr + {\@latex@warning{Empty `thebibliography' environment}}% + \protected@write\@auxout{}{\string\gdef\string\@pageNumberEndBibliography{\thepage}}% + \endlist} +\g@addto@macro\appendix{\immediate\write\@auxout{\string\gdef\string\@pageNumberStartAppendix{\thepage}}}% +\renewcommand\footnoterule{% + \kern-8\p@ + {\color{lipicsBulletGray}\hrule\@width40mm\@height1\p@}% + \kern6.6\p@} +\renewcommand\@makefntext[1]{% + \parindent\z@\hangindent1em + \leavevmode + \hb@xt@1em{\@makefnmark\hss}#1} +\usepackage{microtype} +\usepackage[utf8]{inputenc} +\ifx\pdfa\relax% + \IfFileExists{glyphtounicode.tex}{ + \input glyphtounicode + \pdfgentounicode=1 + }{}% +\fi +\IfFileExists{lmodern.sty}{\RequirePackage{lmodern}}{} +\IfFileExists{fontawesome5.sty}{% +\RequirePackage{fontawesome5}% +\IfFileExists{orcid.pdf}{% +\def\orcidsymbol{\includegraphics[height=9\p@]{orcid}} +}{ +\def\orcidsymbol{\textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries \faOrcid}}% +} +\def\mailsymbol{\textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries \faIcon[regular]{envelope}}}% +\def\homesymbol{\textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries \faHome}}% +}{% +\ClassWarning{Package fontawesome5 not installed}{Please install package fontawesome5} +\def\orcidsymbol{\textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries ORCID}} +\def\mailsymbol{\textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries @}}% +\def\homesymbol{\textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries H}}% +}% +\RequirePackage[T1]{fontenc} +\RequirePackage{textcomp} +\RequirePackage[mathscr]{eucal} +\RequirePackage{amssymb} +\PassOptionsToPackage{retainmissing}{MnSymbol} +\AtBeginDocument{\@ifpackageloaded{MnSymbol}% + {\expandafter\let\csname ver@amssymb.sty\endcsname\relax + \let\complement\@undefined + \RequirePackage{amssymb}}{}} +\RequirePackage{soul} +\sodef\textsolittle{}{.12em}{.5em\@plus.08em\@minus.06em}% + {.4em\@plus.275em\@minus.183em} +\RequirePackage{color} %kept for backward compatibility +\AtBeginDocument{ + \@ifpackageloaded{xcolor}{ + }{ + \RequirePackage{xcolor} + } + \definecolor{darkgray}{rgb}{0.31,0.31,0.33} + \definecolor[named]{lipicsGray}{rgb}{0.31,0.31,0.33} + \definecolor[named]{lipicsBulletGray}{rgb}{0.60,0.60,0.61} + \definecolor[named]{lipicsLineGray}{rgb}{0.51,0.50,0.52} + \definecolor[named]{lipicsLightGray}{rgb}{0.85,0.85,0.86} + \definecolor[named]{lipicsYellow}{rgb}{0.99,0.78,0.07} +} +\RequirePackage{babel} +\RequirePackage[tbtags,fleqn]{amsmath} +\AtBeginDocument{ + \@ifpackageloaded{enumitem}{\ClassWarning{Package 'enumitem' incompatible}{Don't use package 'enumitem'; Package enumerate preloaded!}}{} + \@ifpackageloaded{paralist}{\ClassWarning{Package 'paralist' incompatible}{Don't use package 'paralist'; Package enumerate preloaded!}}{} +} +\RequirePackage{enumerate} +\def\@enum@{\list{\textcolor{lipicsGray}{\sffamily\bfseries\upshape\mathversion{bold}\csname label\@enumctr\endcsname}}% + {\advance\partopsep\topsep + \topsep\z@\@plus\p@ + \usecounter{\@enumctr}\def\makelabel##1{\hss\llap{##1}}}} +\def\romanenumerate{\enumerate[(i)]} +\let\endromanenumerate\endenumerate +\def\alphaenumerate{\enumerate[(a)]} +\let\endalphaenumerate\endenumerate +\def\bracketenumerate{\enumerate[(1)]} +\let\endbracketenumerate\endenumerate +\RequirePackage{graphicx} +\RequirePackage{array} +\let\@classzold\@classz +\def\@classz{% + \expandafter\ifx\d@llarbegin\begingroup + \toks \count@ = + \expandafter{\expandafter\small\the\toks\count@}% + \fi + \@classzold} +\RequirePackage{multirow} +\RequirePackage{tabularx} +\RequirePackage[online]{threeparttable} +\def\TPTtagStyle#1{#1)} +\def\tablenotes{\small\TPT@defaults + \@ifnextchar[\TPT@setuptnotes\TPTdoTablenotes} % ] +\RequirePackage{listings} +\lstset{basicstyle=\small\ttfamily,% + backgroundcolor=\color{lipicsLightGray},% + frame=single,framerule=0pt,xleftmargin=\fboxsep,xrightmargin=\fboxsep} +\RequirePackage[left,mathlines]{lineno} +\linenumbers +\renewcommand\linenumberfont{\normalfont\tiny\sffamily} +%%%% patch to cope with amsmath +%%%% http://phaseportrait.blogspot.de/2007/08/lineno-and-amsmath-compatibility.html +\newcommand*\patchAmsMathEnvironmentForLineno[1]{% + \expandafter\let\csname old#1\expandafter\endcsname\csname #1\endcsname + \expandafter\let\csname oldend#1\expandafter\endcsname\csname end#1\endcsname + \renewenvironment{#1}% + {\linenomath\csname old#1\endcsname}% + {\csname oldend#1\endcsname\endlinenomath}}% +\newcommand*\patchBothAmsMathEnvironmentsForLineno[1]{% + \patchAmsMathEnvironmentForLineno{#1}% + \patchAmsMathEnvironmentForLineno{#1*}}% +\AtBeginDocument{% + \patchBothAmsMathEnvironmentsForLineno{equation}% + \patchBothAmsMathEnvironmentsForLineno{align}% + \patchBothAmsMathEnvironmentsForLineno{flalign}% + \patchBothAmsMathEnvironmentsForLineno{alignat}% + \patchBothAmsMathEnvironmentsForLineno{gather}% + \patchBothAmsMathEnvironmentsForLineno{multline}} +\ifx\pdfa\relax% + \RequirePackage[pdfa,unicode]{hyperref}% +\else% + \RequirePackage[unicode]{hyperref}% +\fi% +\let\usehyperxmp\@empty% +\ifx\pdfa\relax% + \IfFileExists{hyperxmp.sty}{% + \RequirePackage{hyperxmp}% + \@ifpackagelater{hyperxmp}{2019/04/05}{% + \let\usehyperxmp\relax% + }{% + \ClassWarning{Package hyperxmp outdated}{You are using an outdated version of the package hyperxmp. Please update!}% + }}{}% +\fi% +\IfFileExists{totpages.sty}{ + \RequirePackage{totpages} +}{ + \ClassWarning{Package totpages not installed}{Please install package totpages} + \newcounter{TotPages} + \setcounter{TotPages}{99} +} +\let\C\relax% +\let\G\relax% +\let\F\relax% +\let\U\relax% +\pdfstringdefDisableCommands{% + \let\thanks\@gobble% + \let\footnote\@gobble% + \def\footnotemark{}% + \def\cs#1{\textbackslash #1}% + \let\normalfont\@empty% + \let\scshape\@empty% + \def\and{and }% + \def\,{ }% + \def\textrightarrow{ -> }% + \let\mathsf\@empty% +}% +\hypersetup{ + breaklinks=true, + pdfencoding=unicode, + bookmarksnumbered, + pdfborder={0 0 0}, + pdfauthor={ } +}% +\AtBeginDocument{ +\ifx\usehyperxmp\relax +\hypersetup{ +pdftitle={\@title \if!\@subtitle!\else\subtitleseperator \@subtitle\fi}, +pdfauthor={\ifx\authoranonymous\relax Anonymous author(s) \else \@authorsforpdf \fi}, +pdfkeywords={\@keywords}, +pdfproducer={LaTeX with lipics-v2021.cls}, +pdfsubject={LIPIcs, Vol.\@SeriesVolume, \@EventShortTitle}, +pdfcopyright = { Copyright (C) \ifx\authoranonymous\relax Anonymous author(s) \else \@copyrightholder; \fi licensed under Creative Commons License CC-BY 4.0}, +pdflang={en}, +pdfmetalang={en}, +pdfpublisher={Schloss Dagstuhl -- Leibniz-Zentrum für Informatik, Dagstuhl Publishing, Germany}, +pdflicenseurl={https://creativecommons.org/licenses/by/4.0/}, +pdfpubtype={LIPIcs}, +pdfvolumenum={\@SeriesVolume}, +pdfpagerange={\@ArticleNo:\thepage-\@ArticleNo:\theTotPages}, +pdfdoi={\@lipicsdoi}, +pdfapart=3, +pdfaconformance=B +} +\else% +\hypersetup{ +pdftitle={\@title \if!\@subtitle!\else\subtitleseperator \@subtitle\fi}, +pdfauthor={\ifx\authoranonymous\relax Anonymous author(s) \else \@authorsforpdf \fi}, +pdfkeywords={\@keywords}, +pdfcreator={LaTeX with lipics-v2021.cls}, +pdfsubject={LIPIcs, Vol.\@SeriesVolume, \@EventShortTitle; Copyright (C) \ifx\authoranonymous\relax Anonymous author(s) \else \@copyrightholder; \fi licensed under Creative Commons License CC-BY 4.0} +}% +\fi % +} +\ifx\usehyperxmp\relax +\pdfobjcompresslevel=0 +\pdfinclusioncopyfonts=1 +\IfFileExists{colorprofiles.tex}{ +\RequirePackage{colorprofiles}% +\IfFileExists{sRGB.icc}{ +\immediate\pdfobj stream attr{/N 3} file{sRGB.icc} +\pdfcatalog{% +/OutputIntents [ +<< +/Type /OutputIntent +/S /GTS_PDFA1 +/DestOutputProfile \the\pdflastobj\space 0 R +/OutputConditionIdentifier (sRGB) +/Info (sRGB) +>> +] +}}{} +}{\ClassWarning{Package colorprofiles not installed}{Please install package colorprofiles}} +\fi +\RequirePackage[labelsep=space,singlelinecheck=false,% + font={up,small},labelfont={sf,bf},% + listof=false]{caption}%"listof" instead of "list" for backward compatibility +\@ifpackagelater{hyperref}{2009/12/09} + {\captionsetup{compatibility=false}}%cf. http://groups.google.de/group/comp.text.tex/browse_thread/thread/db9310eb540fbbd8/42e30f3b7b3aa17a?lnk=raot + {} +\DeclareCaptionLabelFormat{boxed}{% + \kern0.05em{\color[rgb]{0.99,0.78,0.07}\rule{0.73em}{0.73em}}% + \hspace*{0.67em}\bothIfFirst{#1}{~}#2} +\captionsetup{labelformat=boxed} +\captionsetup[table]{position=top} +\RequirePackage[figuresright]{rotating} +\caption@AtBeginDocument{\@ifpackageloaded{subfig}{\ClassError{lipics}{% + Do not load the subfig package}{The more recent subcaption package is already loaded}}{}} +\RequirePackage{subcaption} +\def\titlerunning#1{\gdef\@titlerunning{{\let\footnote\@gobble\markboth{#1}{#1}}}} +\def\authorrunning#1{% + \gdef\@authorrunning{\markright{\ifx\authoranonymous\relax\textcolor{red}{Anonymous author(s)} \else\if!#1!\textcolor{red}{Author: Please fill in the \string\authorrunning\space macro}\else#1\fi\fi}}} +\titlerunning{\@title \if!\@subtitle!\else\subtitleseperator \@subtitle\fi} +\authorrunning{\textcolor{red}{Author: Please use the \string\authorrunning\space macro}} +\def\EventLongTitle#1{\gdef\@EventLongTitle{#1}} +\EventLongTitle{} +\def\EventShortTitle#1{\gdef\@EventShortTitle{#1}} +\EventShortTitle{} +\def\EventEditors#1{\gdef\@EventEditors{#1}} +\EventEditors{} +\def\EventNoEds#1{\gdef\@EventNoEds{#1}\xdef\@Eds{Editor\ifnum#1>1s\fi}} +\EventNoEds{1} +\def\EventLogo#1{\gdef\@EventLogo{#1}} +\EventLogo{} +\def\EventAcronym#1{\gdef\@EventAcronym{#1}} +\EventAcronym{} +\def\EventYear#1{\gdef\@EventYear{#1}} +\EventYear{} +\def\EventDate#1{\gdef\@EventDate{#1}} +\EventDate{} +\def\EventLocation#1{\gdef\@EventLocation{#1}} +\EventLocation{} +\def\SeriesVolume#1{\gdef\@SeriesVolume{#1}} +\SeriesVolume{} +\def\ArticleNo#1{\gdef\@ArticleNo{#1}} +\ArticleNo{} +\def\DOIPrefix#1{\gdef\@DOIPrefix{#1}} +\DOIPrefix{10.4230/LIPIcs} +\def\@lipicsdoi{\@DOIPrefix.\@EventAcronym.\@EventYear.\@ArticleNo} +\def\and{\newline} +\let\orig@author\@author +\let\@authorsfortoc\@empty +\let\@authorsforpdf\@empty +\newcount\c@author +\newcounter{currentauthor} +\def\authorcolumnsMin{6} +\def\@authornum{0} +\def\author#1#2#3#4#5{% + \ifx\@author\orig@author\let\@author\@empty\fi + \g@addto@macro\@author{% + \noexpandarg\StrBehind{#2}{\and \url}[\homepageTemp]\IfSubStr{#2}{\and \url}{\StrBefore{#2}{\and \url}[\affiliation]}{\def\affiliation{#2}}% + \expandarg\exploregroups\StrRemoveBraces{\homepageTemp}[\homepage]% + \ifx\authorcolumns\relax + \ifnum\c@author>\authorcolumnsMin + \stepcounter{currentauthor} + \ifodd\value{currentauthor} + \begin{minipage}[t]{\textwidth} + \begin{minipage}[t]{0.49\textwidth} + \else + \hfill \begin{minipage}[t]{0.49\textwidth} + \fi + \else + \ClassWarning{Option 'authorcolumns' only applicable for > 6 authors}{Option 'authorcolumns' only applicable for >6 authors!} + \addvspace{0.5\baselineskip} + \fi + \else + \addvspace{0.5\baselineskip} + \fi + {\Large\bfseries + \if!#1! + \textcolor{red}{Author: Please enter author name}% + \else + \ifx\authoranonymous\relax + \textcolor{red}{Anonymous author} + \else + #1\,% + \ifx\compactauthor\relax\if!#3!\else{\,\href{mailto:#3}{\mailsymbol}}\fi% + \ifx\homepage\@empty\else{\,\href{\homepage}{\homesymbol}}\fi\fi% + \if!#4!\else{\,\href{#4}{\orcidsymbol}}\fi% + \if!#5!\else + \ifx\@funding\@empty + \expandafter\g@addto@macro\expandafter\@funding{\textit{\expandafter{\let\footnote\@gobble #1}}:\space{#5}} + \else + \expandafter\g@addto@macro\expandafter\@funding{\\\textit{\expandafter{\let\footnote\@gobble #1}}:\space{#5}} + \fi + \fi + \fi + \fi + } + {\small + \if!#2!\textcolor{red}{Author: Please enter affiliation as second parameter of the author macro}\else{\\* \ifx\authoranonymous\relax\textcolor{red}{Anonymous affiliation}\else\ifx\compactauthor\relax \affiliation \else#2\fi\fi}\fi + \ifx\compactauthor\relax\else\if!#3!\else{\ifx\authoranonymous\relax\else\\*\href{mailto:#3}{#3}\fi}\fi\fi + }\par + \ifx\authorcolumns\relax + \ifnum\c@author>\authorcolumnsMin + \end{minipage} + \ifnum\c@author=\value{currentauthor} + \end{minipage} + \else + \ifodd\value{currentauthor} + \else + \end{minipage}% + \medskip + \fi + \fi + \fi + \fi}% + \global\advance\c@author\@ne + \protected@write\@auxout{}{\string\gdef\string\@authornum{\the\c@author}} + \ifnum\c@author=\@ne + \gdef\@authorsfortoc{#1}% + \gdef\@authorsforpdf{#1} + \else + \expandafter\g@addto@macro\expandafter\@authorsforpdf\expandafter{, #1} + \expandafter\g@addto@macro\expandafter\@authorsfortoc\expandafter{\expandafter\csname\the\c@author authand\endcsname#1}% + \@namedef{\the\c@author authand}{,\space}% + \AtBeginDocument{% + \expandafter\ifnum\@authornum=2 + \@namedef{2authand}{\space and\space}% + \else + \@namedef{\@authornum authand}{,\space and\space}% + \fi} + \fi} +\newcommand*\affil[2][]{% + \ClassError{lipics} + {\string\affil\space deprecated: Please enter affiliation as second parameter of the author macro} + {Since 2017, \string\affil\space is obsolete in lipics.}} +\newcommand*\Copyright[1]{% + \def\@copyrightholder{#1} + \def\@Copyright{% + \setbox\@tempboxa\hbox{\IfFileExists{cc-by.pdf}{\includegraphics[height=14\p@,clip]{cc-by}}{\includegraphics[height=14\p@, width=40pt]{example-image-plain}}}% + \@rightskip\@flushglue \rightskip\@rightskip + \hangindent\dimexpr\wd\@tempboxa+0.5em\relax + \href{https://creativecommons.org/licenses/by/4.0/}% + {\smash{\lower\baselineskip\hbox{\unhcopy\@tempboxa}}}\enskip + \textcopyright\ % + \ifx!#1!\textcolor{red}{Author: Please fill in the \string\Copyright\space macro}\else\ifx\authoranonymous\relax\textcolor{red}{Anonymous author(s)}\else#1\fi\fi + ;\\% + licensed under Creative Commons License CC-BY 4.0\ifx!#1!\\\null\fi\par}} +\Copyright{\textcolor{red}{Author: Please provide a copyright holder}} +\let\@copyrightholder\@empty +\def\hideLIPIcs{\let\@hideLIPIcs\relax} +\usepackage{xstring} +\def\keywords#1{\def\@keywords{#1}} +\let\@keywords\@empty +\def\keywordsHeading{% + \textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries + Keywords and phrases\enskip}} +\RequirePackage{comment} +\excludecomment{CCSXML} +% inspired by https://tex.stackexchange.com/questions/12810/how-do-i-split-a-string +\global\newcommand\ccsdesc[2][100]{\@ccsdesc#1~#2~~\relax} +\let\orig@ccsdesc\@ccsdesc +\let\@ccsdesc\@empty +\let\@ccsdescString\@empty +\gdef\@ccsdesc#1~#2~#3~{ + \ifx\@ccsdesc\orig@ccsdesc\let\@ccsdesc\@empty\fi + \ifx!#3! + \ifx\@ccsdescString\@empty + \g@addto@macro\@ccsdescString{{#2}} + \else + \g@addto@macro\@ccsdescString{; {#2}} + \fi + \else + \ifx\@ccsdescString\@empty + \g@addto@macro\@ccsdescString{{#2} $\rightarrow$ {#3}} + \else + \g@addto@macro\@ccsdescString{; {#2} $\rightarrow$ {#3}} + \fi + \fi +\ccsdescEnd +} +\def\ccsdescEnd#1\relax{} +\def\subjclass#1{ + \ClassError{lipics} + {\string\subjclass\space deprecated: Please enter subject classification in 1 or more ccsdesc macros} + {Since 2019, \string\subjclass\space is obsolete in lipics.}} +\let\@subjclass\@empty +\def\subjclassHeading{% + \textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries + 2012 ACM Subject Classification\enskip}} +\def\doiHeading{% + \textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries + Digital Object Identifier\enskip}} +\def\category#1{\def\@category{#1}} +\let\@category\@empty +\def\categoryHeading{% + \textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries + Category\enskip}} +\def\relatedversion#1{\def\@relatedversion{#1}} +\let\@relatedversion\@empty +\define@key{relatedversiondetails}{linktext}{\def\relatedversiondetails@linktext{#1}} +\define@key{relatedversiondetails}{cite}{\def\relatedversiondetails@cite{#1}} +\newcommand*\addtorelatedversionmacro[2]{% + \ifx\@relatedversion\@empty% + \g@addto@macro\@relatedversion{#1}% + \else% + \g@addto@macro\@relatedversion{\\#1}% + \fi% +}% +\newcommand{\relatedversiondetails}[3][]{% + \begingroup% + \let\relatedversiondetails@linktext\@empty + \let\relatedversiondetails@cite\@empty + \setkeys{relatedversiondetails}{#1}% + \ifx\relatedversiondetails@linktext\@empty% + \protected@edef\tmp{\textit{#2}:\space{\url{#3}}}% + \else% + \protected@edef\tmp{\textit{#2}:\space{\href{#3}{\texttt{\relatedversiondetails@linktext}}}}% + \fi% + \ifx\relatedversiondetails@cite\@empty% + \else% + \protected@edef\tmp{\tmp\nobreakspace\cite{\relatedversiondetails@cite}}% + \fi% + \expandafter\addtorelatedversionmacro\expandafter{\tmp}{#1}% + \endgroup% +}% +\def\relatedversionHeading{% + \textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries + Related Version\enskip}} +\def\supplement#1{\def\@supplement{#1}} +\let\@supplement\@empty +\define@key{supplementdetails}{linktext}{\def\supplementdetails@linktext{#1}} +\define@key{supplementdetails}{cite}{\def\supplementdetails@cite{#1}} +\define@key{supplementdetails}{subcategory}{\def\supplementdetails@subcategory{#1}} +\define@key{supplementdetails}{swhlinktext}{\def\supplementdetails@swhlinktext{#1}} +\let\supplementdetails@swhlinktext\@empty +\define@key{supplementdetails}{swhid}{ + \ifx\supplementdetails@swhlinktext\@empty% + \StrBefore{#1}{;}[\supplementdetails@swhlinktext]% + \fi% + \def\supplementdetails@swhid{#1}% +} + +\define@key{supplementdetails}{swhdelimiter}{\def\supplementdetails@swhdelimiter{#1}} +\def\supplementdetails@swhdelimiter{\\ \hspace*{1.2em}} +\newcommand*\addtosupplementmacro[2]{% + \ifx\@supplement\@empty% + \g@addto@macro\@supplement{#1}% + \else% + \g@addto@macro\@supplement{\\#1}% + \fi% +}% +\newcommand{\supplementdetails}[3][]{% + \begingroup% + \let\supplementdetails@linktext\@empty + \let\supplementdetails@cite\@empty + \let\supplementdetails@subcategory\@empty + \let\supplementdetails@swhid\@empty + \setkeys{supplementdetails}{#1}% + \ifx\supplementdetails@subcategory\@empty% + \protected@edef\tmp{\textit{#2}} + \else + \protected@edef\tmp{\textit{#2\,\,(\supplementdetails@subcategory)}}% + \fi + \ifx\supplementdetails@linktext\@empty% + \protected@edef\tmp{\tmp:\space{\url{#3}}}% + \else% + \protected@edef\tmp{\tmp:\space{\href{#3}{\texttt{\supplementdetails@linktext}}}}% + \fi% + \ifx\supplementdetails@cite\@empty% + \else% + \protected@edef\tmp{\tmp\nobreakspace\cite{\supplementdetails@cite}}% + \fi + \ifx\supplementdetails@swhid\@empty% + \else% + \ifx\supplementdetails@swhlinktext\@empty% + \protected@edef\tmp{\tmp \supplementdetails@swhdelimiter{} archived at % + \href{https://archive.softwareheritage.org/\supplementdetails@swhid}{\nolinkurl{\supplementdetails@swhid}}}% + \else% + \protected@edef\tmp{\tmp \supplementdetails@swhdelimiter{} archived at % + \href{https://archive.softwareheritage.org/\supplementdetails@swhid}{\nolinkurl{\supplementdetails@swhlinktext}}}% + \fi% + \fi% + \expandafter\addtosupplementmacro\expandafter{\tmp}{#1}% + \endgroup% +}% +\def\supplementHeading{% + \textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries + Supplementary Material\enskip}} +\newcommand\flag[2][0.9cm]{% + \leavevmode\marginpar{% + \raisebox{\dimexpr-\totalheight+\ht\strutbox\relax}% + [\dimexpr\ht\strutbox+3mm][\dp\strutbox]{\expandafter\includegraphics[width=#1]{#2}}% +}} +\def\funding#1{\def\@funding{#1}} +\let\@funding\@empty +\def\fundingHeading{% + \textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries + Funding\enskip}} +\def\acknowledgements#1{\def\@acknowledgements{#1}} +\let\@acknowledgements\@empty +\def\acknowledgementsHeading{% + \textcolor{lipicsGray}{\fontsize{9}{12}\sffamily\bfseries + Acknowledgements\enskip}} +\RequirePackage{amsthm} +\ifx\usethmrestate\relax + \RequirePackage{thm-restate} +\fi +\thm@headfont{% + \textcolor{lipicsGray}{$\blacktriangleright$}\nobreakspace\sffamily\bfseries} +\def\th@remark{% + \thm@headfont{% + \textcolor{lipicsGray}{$\blacktriangleright$}\nobreakspace\sffamily}% + \normalfont % body font + \thm@preskip\topsep \divide\thm@preskip\tw@ + \thm@postskip\thm@preskip +} +\def\@endtheorem{\endtrivlist}%\@endpefalse +\renewcommand\qedsymbol{\textcolor{lipicsGray}{\ensuremath{\blacktriangleleft}}} +\renewenvironment{proof}[1][\proofname]{\par + \pushQED{\qed}% + \normalfont \topsep6\p@\@plus6\p@\relax + \trivlist + \item[\hskip\labelsep + \color{lipicsGray}\sffamily\bfseries + #1\@addpunct{.}]\ignorespaces +}{% + \popQED\endtrivlist%\@endpefalse +} +\newcommand{\claimqedhere}{\renewcommand\qedsymbol{\textcolor{lipicsGray}{\ensuremath{\vartriangleleft}}}% +\qedhere% +\renewcommand\qedsymbol{\textcolor{lipicsGray}{\ensuremath{\blacktriangleleft}}}} +\newenvironment{claimproof}[1][\proofname]{ + \pushQED{\qed}% + \normalfont \topsep6\p@\@plus6\p@\relax + \trivlist + \item[\hskip\labelsep + \color{lipicsGray}\sffamily + #1\@addpunct{.}]\ignorespaces +}{% + \renewcommand\qedsymbol{\textcolor{lipicsGray}{\ensuremath{\vartriangleleft}}} + \popQED\endtrivlist%\@endpefalse + \renewcommand\qedsymbol{\textcolor{lipicsGray}{\ensuremath{\blacktriangleleft}}} +} +% inspired by qed of amsthm class +\DeclareRobustCommand{\lipicsEnd}{% + \leavevmode\unskip\penalty9999 \hbox{}\nobreak\hfill + \quad\hbox{$\lrcorner$}% +} +\AtBeginDocument{ + \@ifpackageloaded{algorithm2e}{ + \@ifpackagelater{algorithm2e}{2009/11/17}{ + \renewcommand{\algorithmcfname}{\sffamily\bfseries{}Algorithm}% + \renewcommand{\@algocf@procname}{\sffamily\bfseries{}Procedure}% + \SetAlgoCaptionSeparator{~} + \SetAlCapHSkip{0pt} + \renewcommand{\algocf@captiontext}[2]{% + \kern0.05em{\color{lipicsYellow}\rule{0.73em}{0.73em}}% + \hspace*{0.67em}\small #1\algocf@capseparator\nobreakspace#2} + \renewcommand{\algocf@makecaption}[2]{% + \parbox[t]{\textwidth}{\algocf@captiontext{#1}{#2}}% + }% + \renewcommand{\algocf@captionproctext}[2]{% + {% + \kern0.05em{\color{lipicsYellow}\rule{0.73em}{0.73em}}% + \hspace*{0.67em}\small% +\ProcSty{\ProcFnt\algocf@procname\ifthenelse{\boolean{algocf@procnumbered}}{\nobreakspace\thealgocf\algocf@typo\algocf@capseparator}{\relax}}% + \nobreakspace\ProcNameSty{\ProcNameFnt\algocf@captname #2@}% Name of the procedure in ProcName Style. + \ifthenelse{\equal{\algocf@captparam #2@}{\arg@e}}{}{% if no argument, write nothing + \ProcNameSty{\ProcNameFnt(}\ProcArgSty{\ProcArgFnt\algocf@captparam #2@}\ProcNameSty{\ProcNameFnt)}%else put arguments in ProcArgSty: + }% endif + \algocf@captother #2@% + }% +}% + \renewcommand{\@algocf@capt@boxed}{above} + \renewcommand{\@algocf@capt@ruled}{above} + \setlength\algotitleheightrule{0pt} + }{\ClassWarning{% + Package algorithm2e outdated}{You are using an outdated version of the package algorithm2e. Please update!}} + }{} + \@ifpackageloaded{algorithm}{ + \captionsetup[algorithm]{name=Algorithm, labelformat=boxed, position=top} + \newcommand\fs@ruled@notop{\def\@fs@cfont{\bfseries}\let\@fs@capt\floatc@ruled + \def\@fs@pre{}% + \def\@fs@post{\kern2pt\hrule\relax}% + \def\@fs@mid{\kern2pt\hrule\kern2pt}% + \let\@fs@iftopcapt\iftrue} + \@ifundefined{fst@algorithm}{}{ + \renewcommand\fst@algorithm{\fs@ruled@notop} + } + }{} + \ifx\usecleveref\relax\else + \@ifpackageloaded{cleveref}{\ClassWarning{Use document option 'cleveref' instead}{Use document option 'cleveref' instead directly loading package 'cleveref'}}{} + \fi + \ifx\usethmrestate\relax\else + \@ifpackageloaded{thm-restate}{\ClassWarning{Use document option 'thm-restate' instead}{Use document option 'thm-restate' instead directly loading package 'thm-restate'}}{} + \fi + \ifx\useautoref\relax + \@ifundefined{algorithmautorefname}{\newcommand{\algorithmautorefname}{Algorithm}}{\renewcommand{\algorithmautorefname}{Algorithm}}% + \fi +} + +\ifx\usecleveref\relax + \RequirePackage[capitalise, noabbrev]{cleveref} + \crefname{algocf}{Algorithm}{Algorithms} + \Crefname{algocf}{Algorithm}{Algorithms} + \newcommand{\crefrangeconjunction}{--} + \newcommand{\creflastconjunction}{, and\nobreakspace} +\fi +\ifx\useautoref\relax + \RequirePackage{aliascnt} +\fi +\newtheoremstyle{claimstyle}{\topsep}{\topsep}{}{0pt}{\sffamily}{. }{5pt plus 1pt minus 1pt}% + {$\vartriangleright$ \thmname{#1}\thmnumber{ #2}\thmnote{ (#3)}} +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\ifx\numberwithinsect\relax + \numberwithin{theorem}{section} +\fi +\ifx\useautoref\relax + \addto\extrasenglish{% + \def\chapterautorefname{Chapter}% + \def\sectionautorefname{Section}% + \def\subsectionautorefname{Subsection}% + \def\subsubsectionautorefname{Subsubsection}% + \def\paragraphautorefname{Paragraph}% + \def\subparagraphautorefname{Subparagraph}% + } + \addto\extrasUKenglish{% + \def\chapterautorefname{Chapter}% + \def\sectionautorefname{Section}% + \def\subsectionautorefname{Subsection}% + \def\subsubsectionautorefname{Subsubsection}% + \def\paragraphautorefname{Paragraph}% + \def\subparagraphautorefname{Subparagraph}% + } + \addto\extrasUSenglish{% + \def\chapterautorefname{Chapter}% + \def\sectionautorefname{Section}% + \def\subsectionautorefname{Subsection}% + \def\subsubsectionautorefname{Subsubsection}% + \def\paragraphautorefname{Paragraph}% + \def\subparagraphautorefname{Subparagraph}% + } + \ifx\usethmrestate\relax + \newtheorem{lemma}[theorem]{Lemma} + \newtheorem{corollary}[theorem]{Corollary} + \newtheorem{proposition}[theorem]{Proposition} + \newtheorem{exercise}[theorem]{Exercise} + \newtheorem{definition}[theorem]{Definition} + \newtheorem{conjecture}[theorem]{Conjecture} + \newtheorem{observation}[theorem]{Observation} + \theoremstyle{definition} + \newtheorem{example}[theorem]{Example} + \theoremstyle{remark} + \newtheorem{note}[theorem]{Note} + \newtheorem*{note*}{Note} + \newtheorem{remark}[theorem]{Remark} + \newtheorem*{remark*}{Remark} + \theoremstyle{claimstyle} + \newtheorem{claim}[theorem]{Claim} + \newtheorem*{claim*}{Claim} + \else + \newaliascnt{lemma}{theorem} + \newtheorem{lemma}[lemma]{Lemma} + \aliascntresetthe{lemma} + \newcommand{\lemmaautorefname}{Lemma} + \newaliascnt{corollary}{theorem} + \newtheorem{corollary}[corollary]{Corollary} + \aliascntresetthe{corollary} + \newcommand{\corollaryautorefname}{Corollary} + \newaliascnt{proposition}{theorem} + \newtheorem{proposition}[proposition]{Proposition} + \aliascntresetthe{proposition} + \newcommand{\propositionautorefname}{Proposition} + \newaliascnt{exercise}{theorem} + \newtheorem{exercise}[exercise]{Exercise} + \aliascntresetthe{exercise} + \newcommand{\exerciseautorefname}{Exercise} + \newaliascnt{definition}{theorem} + \newtheorem{definition}[definition]{Definition} + \aliascntresetthe{definition} + \newcommand{\definitionautorefname}{Definition} + \newaliascnt{conjecture}{theorem} + \newtheorem{conjecture}[conjecture]{Conjecture} + \aliascntresetthe{conjecture} + \newcommand{\conjectureautorefname}{Conjecture} + \newaliascnt{observation}{theorem} + \newtheorem{observation}[observation]{Observation} + \aliascntresetthe{observation} + \newcommand{\observationautorefname}{Observation} + \theoremstyle{definition} + \newaliascnt{example}{theorem} + \newtheorem{example}[example]{Example} + \aliascntresetthe{example} + \newcommand{\exampleautorefname}{Example} + \theoremstyle{remark} + \newaliascnt{note}{theorem} + \newtheorem{note}[note]{Note} + \aliascntresetthe{note} + \newcommand{\noteautorefname}{Note} + \newtheorem*{note*}{Note} + \newaliascnt{remark}{theorem} + \newtheorem{remark}[remark]{Remark} + \aliascntresetthe{remark} + \newcommand{\remarkautorefname}{Remark} + \newtheorem*{remark*}{Remark} + \theoremstyle{claimstyle} + \newaliascnt{claim}{theorem} + \newtheorem{claim}[claim]{Claim} + \aliascntresetthe{claim} + \newcommand{\claimautorefname}{Claim} + \newtheorem*{claim*}{Claim} + \ifx\numberwithinsect\relax + \numberwithin{theorem}{section} + \numberwithin{lemma}{section} + \numberwithin{corollary}{section} + \numberwithin{proposition}{section} + \numberwithin{exercise}{section} + \numberwithin{definition}{section} + \numberwithin{conjecture}{section} + \numberwithin{observation}{section} + \numberwithin{example}{section} + \numberwithin{note}{section} + \numberwithin{remark}{section} + \numberwithin{claim}{section} + \fi + \fi +\else + \newtheorem{lemma}[theorem]{Lemma} + \newtheorem{corollary}[theorem]{Corollary} + \newtheorem{proposition}[theorem]{Proposition} + \newtheorem{exercise}[theorem]{Exercise} + \newtheorem{definition}[theorem]{Definition} + \newtheorem{conjecture}[theorem]{Conjecture} + \newtheorem{observation}[theorem]{Observation} + \theoremstyle{definition} + \newtheorem{example}[theorem]{Example} + \theoremstyle{remark} + \newtheorem{note}[theorem]{Note} + \newtheorem*{note*}{Note} + \newtheorem{remark}[theorem]{Remark} + \newtheorem*{remark*}{Remark} + \theoremstyle{claimstyle} + \newtheorem{claim}[theorem]{Claim} + \newtheorem*{claim*}{Claim} +\fi +\theoremstyle{plain} +\endinput +%% +%% End of file `lipics-v2021.cls'. diff --git a/martin.bib b/martin.bib new file mode 100644 index 0000000..2417828 --- /dev/null +++ b/martin.bib @@ -0,0 +1,310 @@ +@article{10.1145/3409006, +author = {Parreaux, Lionel}, +title = {The Simple Essence of Algebraic Subtyping: Principal Type Inference with Subtyping Made Easy (Functional Pearl)}, +year = {2020}, +issue_date = {August 2020}, +publisher = {Association for Computing Machinery}, +address = {New York, NY, USA}, +volume = {4}, +number = {ICFP}, +url = {https://doi.org/10.1145/3409006}, +doi = {10.1145/3409006}, +abstract = {MLsub extends traditional Hindley-Milner type inference with subtyping while preserving compact principal types, an exciting new development. However, its specification in terms of biunification is difficult to understand, relying on the new concepts of bisubstitution and polar types, and making use of advanced notions from abstract algebra. In this paper, we show that these are in fact not essential to understanding the mechanisms at play in MLsub. We propose an alternative algorithm called Simple-sub, which can be implemented efficiently in under 500 lines of code (including parsing, simplification, and pretty-printing), looks more familiar, and is easier to understand. We present an experimental evaluation of Simple-sub against MLsub on a million randomly-generated well-scoped expressions, showing that the two systems agree. The mutable automaton-based implementation of MLsub is quite far from its algebraic specification, leaving a lot of space for errors; in fact, our evaluation uncovered several bugs in it. We sketch more straightforward soundness and completeness arguments for Simple-sub, based on a syntactic specification of the type system. This paper is meant to be light in formalism, rich in insights, and easy to consume for prospective designers of new type systems and programming languages. In particular, no abstract algebra is inflicted on readers.}, +journal = {Proc. ACM Program. Lang.}, +month = {aug}, +articleno = {124}, +numpages = {28}, +keywords = {subtyping, type inference, principal types} +} + +@inproceedings{PT98, + author = {Pierce, Benjamin C. and Turner, David N.}, + title = {Local type inference}, + booktitle = {Proceedings of the 25th ACM SIGPLAN-SIGACT symposium on Principles of programming languages}, + series = {POPL '98}, + year = {1998}, + location = {San Diego, California, United States}, + pages = {252--265} +} + +@article{OZZ01, + author = "Martin Odersky and Matthias Zenger and Christoph Zenger", + title = "Colored local type inference", + journal = "Proc. 28th ACM Symposium on Principles of Programming Languages", + volume = "36", + number = "3", + pages = "41--53", + year = "2001", + xnote = "citeseer.ist.psu.edu/article/odersky01colored.html" } + + +@InProceedings{plue09_1, + author = {Martin Pl{\"u}micke}, + title = {Java type unification with wildcards}, + booktitle = {17th International Conference, INAP 2007, and 21st Workshop on Logic Programming, WLP 2007, W\"urzburg, Germany, October 4-6, 2007, Revised Selected Papers}, + year = {2009}, + editor = {Dietmar Seipel and Michael Hanus and Armin Wolf}, + Volume = {5437}, + publisher = {Springer-Verlag Heidelberg}, + pages = {223--240}, + SERIES = {Lecture Notes in Artificial Intelligence} +} + +@article{DM82, + author={Luis Damas and Robin Milner}, + title={Principal type-schemes for functional programs}, + journal={Proc. 9th Symposium on Principles of Programming Languages}, + year={1982} +} + +@article{Rob65, + author={J. A. Robinson}, + title={A Machine-Oriented Logic Based on the Resolution Principle}, + journal={Journal of ACM}, + volume={12(1)}, + pages={23-41}, + month=Jan, + year={1965}} + +@article{MM82, + author={A. Martelli and U. Montanari}, + title={An Efficient Unification Algorithm}, + journal={ACM Transactions on Programming Languages and Systems}, + volume={4}, + pages={258-282}, + year={1982}} + +@InProceedings{Plue07_3, + author = {Martin Pl{\"u}micke}, + title = {Typeless {P}rogramming in \textsf{{J}ava 5.0} with {W}ildcards}, + booktitle = {5th {I}nternational {C}onference on {P}rinciples and {P}ractices of {P}rogramming in {J}ava}, + pages = {73--82}, + year = {2007}, + editor = {Vasco Amaral and Lu\'is Veiga and Lu\'is Marcelino and H. Conrad Cunningham}, + series = {ACM International Conference Proceeding Series}, + volume = {272}, + month = {September} +} + +@inproceedings{plue15_2, + author = {Martin Pl{\"{u}}micke}, + title = {More Type Inference in {J}ava 8}, + booktitle = {Perspectives of System Informatics - 9th International Ershov Informatics + Conference, {PSI} 2014, St. Petersburg, Russia, June 24-27, 2014. + Revised Selected Papers}, + editor = {Andrei Voronkov and Irina Virbitskaite}, + volume = {8974}, + series = {Lecture Notes in Computer Science}, + pages = {248--256}, + year = {2015}, + publisher = {Springer} +} + +@phdthesis{GS89, + author = "Gert Smolka", + title = "Logic Programming over Polymorphically Order-Sorted Types", + school = {Department Informatik, University of Kaisers\-lautern}, + address = {Kaiserslautern, Germany}, + month = may, + year = 1989 +} + +@Article{MH91, + author = "Michael Hanus", + title = "Parametric order-sorted types in logic programming", + journal = "Proc. TAPSOFT 1991", + year = "1991", + volume = "LNCS", + number = "394", + pages = "181--200" +} + +@inproceedings{CB95, + author = "Christoph Beierle", + title = "Type Inferencing for Polymorphic Order-Sorted Logic Programs", + booktitle = "International Conference on Logic Programming", + pages = "765-779", + year = "1995", + OPturl = "citeseer.ist.psu.edu/beierle95type.html" } + +@incollection{HiTo92, + author = {Patricia M. Hill and Rodney W. Topor}, + editor = {Frank Pfenning}, + title = {A {S}emantics for {T}yped {L}ogic {P}rograms}, + booktitle = {Types in Logic Programming}, + year = {1992}, + pages = {1-62}, + publisher = {MIT Press}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + + +@inproceedings{TEP05, + author = "Torgersen, Mads and Ernst, Erik and + Hansen, Christian Plesner", + title = "Wild {F}{J}", + booktitle = "Proceedings of FOOL 12", + year = 2005, + editor = "Wadler, Philip", + address = "Long Beach, California, USA", + month = Jan, + organization = "ACM", + publisher = "School of Informatics, University of + Edinburgh", + anote = "Electronic publication, at the URL given + below", + abstract = "This paper presents a formalization of + wildcards, which is one of the new features of + the Java programming language in version + JDK5.0. Wildcards help alleviating the + impedance mismatch between generics, or + parametric polymorphism, and traditional + object-oriented subtype polymorphism. They do + this by quantifying over parameterized types + with different type arguments. Wildcards take + inspiration from several sources including + use-site variance, and they could be considered + as a way to introduce a syntactically + light-weight kind of existential types into a + main-stream language. This formalization + describes the mechanism, in particular the + wildcard capture process where the existential + nature of wildcards becomes evident.", + url = "http://homepages.inf.ed.ac.uk/wadler/fool/", + annote = "wild-fj.pdf" +} + +@Article{BBDGV18, + author = {Lorenzo Bettini and Viviana Bono and Mariangiola Dezani-Ciancaglini and Paola Giannini and Betti, Venneri}, + title = {Java \& Lambda: A Featherweight Story}, + journal = {Logical Methods in Computer Science}, + year = {2018}, + OPTkey = {}, + volume = {14(3:17)}, + OPTnumber = {}, + pages = {1--24}, + OPTmonth = {}, + OPTnote = {}, + OPTannote = {} +} + +@inproceedings{plue17_2, + author = {Pl\"{u}micke, Martin and Stadelmeier, Andreas}, + title = {Introducing {S}cala-like Function Types into {J}ava-{TX}}, + booktitle = {Proceedings of the 14th International Conference on Managed Languages and Runtimes}, + series = {ManLang 2017}, + year = {2017}, + isbn = {978-1-4503-5340-3}, + location = {Prague, Czech Republic}, + pages = {23--34}, + numpages = {12}, + url_ = {http://doi.acm.org/10.1145/3132190.3132203}, + doi = {10.1145/3132190.3132203}, + acmid = {3132203}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {Java, function types, lambda expressions, type inference}, +} + +@InProceedings{Plue04_1, + author = {Martin Pl{\"u}micke}, + title = {Type {U}nification in \textsf{Generic--Java}}, + booktitle = {Proceedings of 18th {I}nternational {W}orkshop on {U}nification ({U}{N}{I}{F}'04)}, + year = {2004}, + address = {Cork}, + editor = {Michael Kohlhase}, + month = {July}, + OPturl = {http://www.lsv.ens-cachan.fr/unif/} +} + +@INPROCEEDINGS{AZ04, + author = {Davide Ancona and Elena Zucca}, + title = {Principal typings for {J}ava-like languages}, + booktitle = {In ACM Symp. on Principles of Programming Languages 2004}, + year = {2004}, + pages = {306--317}, + publisher = {ACM Press} +} + +@inproceedings{plue16_1, + author = {Martin Pl{\"{u}}micke}, + title = {Structural Type Inference in Java-like Languages}, + booktitle = {Gemeinsamer Tagungsband der Workshops der Tagung Software Engineering + 2016 {(SE} 2016), Wien, 23.-26. Februar 2016.}, + pages = {109--113}, + year = {2016}, + Optcrossref = {DBLP:conf/se/2016w}, + url = {http://ceur-ws.org/Vol-1559/paper09.pdf}, + timestamp = {Mon, 07 Mar 2016 13:17:33 +0100}, + biburl = {http://dblp.uni-trier.de/rec/bib/conf/se/Plumicke16}, + bibsource = {dblp computer science bibliography, http://dblp.org} +} + +@inproceedings{ADDZ05, + author = {Ancona, Davide and Damiani, Ferruccio and Drossopoulou, Sophia and Zucca, Elena}, + title = {Polymorphic Bytecode: Compositional Compilation for {J}ava-like Languages}, + booktitle = {Proceedings of the 32nd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages}, + series = {POPL '05}, + year = {2005}, + isbn = {1-58113-830-X}, + location = {Long Beach, California, USA}, + pages = {26--37}, + numpages = {12}, + url = {http://doi.acm.org/10.1145/1040305.1040308}, + doi = {10.1145/1040305.1040308}, + acmid = {1040308}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {compositional analysis, type systems}, +} + +@InProceedings{aModelForJavaWithWildcards, +author="Cameron, Nicholas +and Drossopoulou, Sophia +and Ernst, Erik", +editor="Vitek, Jan", +title="A Model for Java with Wildcards", +booktitle="ECOOP 2008 -- Object-Oriented Programming", +year="2008", +publisher="Springer Berlin Heidelberg", +address="Berlin, Heidelberg", +pages="2--26", +abstract="Wildcards are a complex and subtle part of the Java type system, present since version 5.0. Although there have been various formalisations and partial type soundness results concerning wildcards, to the best of our knowledge, no system that includes all the key aspects of Java wildcards has been proven type sound. This paper establishes that Java wildcards are type sound. We describe a new formal model based on explicit existential types whose pack and unpack operations are handled implicitly, and prove it type sound. Moreover, we specify a translation from a subset of Java to our formal model, and discuss how several interesting aspects of the Java type system are handled.", +isbn="978-3-540-70592-5" +} +@article{WildcardsNeedWitnessProtection, +author = {Bierhoff, Kevin}, +title = {Wildcards Need Witness Protection}, +year = {2022}, +issue_date = {October 2022}, +publisher = {Association for Computing Machinery}, +address = {New York, NY, USA}, +volume = {6}, +number = {OOPSLA2}, +url = {https://doi.org/10.1145/3563301}, +doi = {10.1145/3563301}, +abstract = {In this paper, we show that the unsoundness discovered by Amin and Tate (2016) in Java’s wildcards is avoidable, even in the absence of a nullness-aware type system. The key insight of this paper is that soundness in type systems that implicitly introduce existential types through subtyping hinges on still making sure there are suitable witness types when introducing existentially quantified type variables. To show that this approach is viable, this paper formalizes a core calculus and proves it sound. We used a static analysis based on our approach to look for potential issues in a vast corpus of Java code and found none (with 1 false positive). This confirms both that Java's unsoundness has minimal practical consequence, and that our approach can avoid it entirely with minimal false positives.}, +journal = {Proc. ACM Program. Lang.}, +month = {oct}, +articleno = {138}, +numpages = {22}, +keywords = {Null, Java Wildcards, Existential Types} +} +@InProceedings{TIforFGJ, + author = {Stadelmeier, Andreas and Pl\"{u}micke, Martin and Thiemann, Peter}, + title = {{Global Type Inference for Featherweight Generic Java}}, + booktitle = {36th European Conference on Object-Oriented Programming (ECOOP 2022)}, + pages = {28:1--28:27}, + series = {Leibniz International Proceedings in Informatics (LIPIcs)}, + ISBN = {978-3-95977-225-9}, + ISSN = {1868-8969}, + year = {2022}, + volume = {222}, + editor = {Ali, Karim and Vitek, Jan}, + publisher = {Schloss Dagstuhl -- Leibniz-Zentrum f{\"u}r Informatik}, + address = {Dagstuhl, Germany}, + URL = {https://drops.dagstuhl.de/opus/volltexte/2022/16256}, + URN = {urn:nbn:de:0030-drops-162560}, + doi = {10.4230/LIPIcs.ECOOP.2022.28}, + annote = {Keywords: type inference, Java, subtyping, generics} +} diff --git a/orcid.pdf b/orcid.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c31b0393efd556887c0cd1a595de7be764a6a168 GIT binary patch literal 88694 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