zapashcanon 5 months ago
parent
commit
29b72b684a
Signed by: zapashcanon GPG Key ID: 8981C3C62D1D28F1
  1. 173
      src/article.tex
  2. 38
      src/bib.bib
  3. 122
      src/dune
  4. 28
      src/layout.wast
  5. 45
      src/main.tex
  6. 32
      src/packages.tex

173
src/article.tex

@ -1,95 +1,64 @@
\section{Introduction}
\paragraph{} A function is said to be \emph{polymorphic} when a single implementation of this function can be used with several different types. A polymorphic function may accept types that need to be treated differently at runtime. It could be because they have different memory representation, use different calling conventions or need to be discriminated by the garbage collector. It is thus necessary to keep track of these information at runtime in order to interpret or to compile a polymorphic function.
A function is said to be \emph{polymorphic} when a single implementation of this function can be used with several different types. A polymorphic function may accept types that need to be treated differently at runtime. It could be because they have different memory representation, use different calling conventions or need to be discriminated by the garbage collector. It is thus necessary to keep track of these information at runtime in order to interpret or to compile a polymorphic function.
% TODO: exemples
\paragraph{} Many polymorphism implementation techniques exist but only some of them have been described in research papers. We describe these techniques extensively, list their advantages and limitations, and compare all of them.
\section{By hand: meta-programming}
In this section, we discuss techniques used when a language does not properly support polymorphism.
\paragraph{Source code duplication by hand} Some programming languages do not provide means to write polymorphic code. In this cases it is still possible to duplicate code by hand to handle different types.
\paragraph{Source code generation} It is possible to avoid having to do this duplication by hand. This is done by writing a program that will generate the duplicated source code for each type.
\paragraph{Source code transformation} It is possible to generate source code using a preprocessor. This is described in~\cite{SY74} under the name \emph{syntax-macro extension}. It is used~\cite{EBN02} in the C programming language through its preprocessor~\cite{SW87}. The technique is described in~\cite{Reb17}. For instance, given the \commandbox{list.c} file:
\begin{tcolorbox}[breakable]
\input{list.c.tex}
\end{tcolorbox}
Running \commandbox*{cpp -P list.c} will give:
\begin{tcolorbox}[breakable]
\input{list.preprocessed.c.tex}
\end{tcolorbox}
In practice one would put the generic code in its own file. Then, defining \commandbox{TYPE} and \commandbox{TYPED(X)} before including the file is enough to get a specialised version.
Many polymorphism implementation techniques exist but only some of them have been described in research papers. We describe these techniques extensively, list their advantages and limitations, and compare all of them.
\paragraph{String mixins} See D's \emph{String mixins}~\cite{Fou22}.
For instance, givent the \commandbox{list.d} file:
\begin{tcolorbox}[breakable]
\input{list.d.tex}
\end{tcolorbox}
Running \commandbox*{gdc -c list.d -fsave-mixins=/dev/stdout} will give:
\begin{tcolorbox}[breakable]
\input{list_int.d.tex}
\end{tcolorbox}
\paragraph{Token stream transformation} See Rust's \emph{procedural macros}~\cite{Dev22}.
\paragraph{AST transformation} See OCaml's PPXs~\cite{Con22ppx}.
\paragraph{} For more metaprogramming techniques, see~\cite{LS19}.
\section{By hand: meta-programming}
In this section, we discuss techniques used when a language does not properly support polymorphism.
\paragraph{Source code duplication by hand}
Some programming languages do not provide means to write polymorphic code. In this cases it is still possible to duplicate code by hand to handle different types.
\paragraph{Source code generation}
It is possible to avoid having to do this duplication by hand. This is done by writing a program that will generate the duplicated source code for each type.
\paragraph{Source code transformation}
It is possible to generate source code using a preprocessor. This is described in~\cite{SY74} under the name \emph{syntax-macro extension}. It is used~\cite{EBN02} in the C programming language through its preprocessor~\cite{SW87}. The technique is described in~\cite{Reb17}. For instance, given the \texttt{list.c} file:
\inputminted{c}{list.c}
Running \texttt{cpp -P list.c} will give:
\inputminted{c}{list.preprocessed.c}
In practice one would put the generic code in its own file. Then, defining \texttt{TYPE} and \texttt{TYPED(X)} before including the file is enough to get a specialised version.
\paragraph{String mixins}
See D's \emph{String mixins}~\cite{Fou22}. For instance, givent the \texttt{list.d} file:
\inputminted{d}{list.d}
Running \texttt{gdc -c list.d -fsave-mixins=/dev/stdout} will give:
\inputminted{d}{list_int.d}
\paragraph{Token stream transformation}
See Rust's \emph{procedural macros}~\cite{Dev22}.
\paragraph{AST transformation}
See OCaml's PPXs~\cite{Con22ppx}.
For more metaprogramming techniques, see~\cite{LS19}.
\section{Monomorphization}
Given a polymorphic function, it is (sometimes) possible to \emph{statically} collect all the type combinations it is going to be used with. The \emph{monomorphization} technique consists in producing a different \emph{specialised} function for each combination. This results in having only \emph{monomorphic} functions, hence the name monomorphization.
Given a polymorphic function, it is (sometimes) possible to \emph{statically} collect all the type combinations it is going to be used with. The \emph{monomorphization} technique consists in producing a different \emph{specialised} function for each combination. This results in having only \emph{monomorphic} functions, hence the name monomorphization.
To build the set of type combinations for a given function, we iterate on the program's \emph{call graph}. At each \emph{call site}, the type combination of the current call is added to the set of the function being called.
To build the set of type combinations for a given function, we iterate on the program's \emph{call graph}. At each \emph{call site}, the type combination of the current call is added to the set of the function being called.
Once the set is computed, the original polymorphic function is removed. All the monomorphic functions are generated and added to the program. Finally, each call site is updated to use the right function.
Monomorphization is used by Rust's generics~\cite{Con18}, C++'s templates~\cite{Str88}, Ada's generic packages and subprograms~\cite{ND79}\cite{Bar80} and Coq's extraction~\cite{TAG18}.
Once the set is computed, the original polymorphic function is removed. All the monomorphic functions are generated and added to the program. Finally, each call site is updated to use the right function.
Monomorphization is used by Rust's generics~\cite{Con18}, C++'s templates~\cite{Str88}, Ada's generic packages and subprograms~\cite{ND79}\cite{Bar80} and Coq's extraction~\cite{TAG18}.
% Why3~\cite{BP11}
Monomorphization may seem similar to the various techniques described in the previous section. The difference lies in the fact that monomorphization is dedicated to handle polymorphism, whereas metaprogramming only allows polymorphism incidentally. Even though C has macros, C is not considered to be a polymorphic language. In the same vein, even if C++, D and Rust respectively have macros, String mixins and procedural macros; they also have a templates/generics system dedicated to polymorphism. The term monomorphization should be used to talk about techniques designed to handle polymorphism.
Monomorphization may seem similar to the various techniques described in the previous section. The difference lies in the fact that monomorphization is dedicated to handle polymorphism, whereas metaprogramming only allows polymorphism incidentally. Even though C has macros, C is not considered to be a polymorphic language. In the same vein, even if C++, D and Rust respectively have macros, String mixins and procedural macros; they also have a templates/generics system dedicated to polymorphism. The term monomorphization should be used to talk about techniques designed to handle polymorphism.
\subsection{Advantages}
\paragraph{Code specialisation} The code produced by monomorphization is usually very efficient. Indeed, as the types are known precisely, it is possible to generate machine code fully specialised for a given type. This includes the usage of dedicated assembly instructions or calling conventions. Moreover, there is no need for any kind of runtime support as there is no need to act differently depending on the type.
\paragraph{Memory usage} Heap memory usage is optimal as we only store the values we need and no runtime metadata.
\paragraph{Implementation} Implementing monomorphization is straightforward. As described above, only three steps are needed: collection, generation and call site update.
\paragraph{Code specialisation}
The code produced by monomorphization is usually very efficient. Indeed, as the types are known precisely, it is possible to generate machine code fully specialised for a given type. This includes the usage of dedicated assembly instructions or calling conventions. Moreover, there is no need for any kind of runtime support as there is no need to act differently depending on the type.
\paragraph{Memory usage}
Heap memory usage is optimal as we only store the values we need and no runtime metadata.
\paragraph{Implementation}
Implementing monomorphization is quite straightforward. As described above, only three steps are needed: collection, generation and call site update.
\subsection{Disadvantages}
\paragraph{Compilation cost} Compilation time and memory usage grow as the number of specialised functions per polymorphic function increases. Which can become quite costly.
\paragraph{Binary size} For the same reason, the compiled binary can be quite huge. Each source polymorphic function potentially leading to a lot of assembly monomorphic functions.
\paragraph{Dynamic languages} Monomorphization doesn't work for dynamic languages. TODO: explain a little bit more, with an example.
\paragraph{Modularity} Monomorphization is not modular as it requires either access to the full source code, or to keep a representation of polymorphic code until linking in order to support separate compilation. TODO: explain more, with an example
\subsubsection{Polymorphic recursion}
Monomorphization is impossible in presence of polymorphic recursion, that is, a recursive function calling itself with a potentially different type each time.
It is quite easy to show with non-uniform recursive types, as they permit to write functions whose type can grow indefinitely depending on their input.
For instance, this implementation of \emph{Revisited Binary Random-Access Lists}~\cite{Oka99} in Rust:
\begin{tcolorbox}[breakable]
\input{ral.rs.tex}
\end{tcolorbox}
\paragraph{Compilation cost}
Compilation time and memory usage grow as the number of specialised functions per polymorphic function increases. Which can become quite costly.
\paragraph{Binary size}
For the same reason, the compiled binary can be quite huge. Each source polymorphic function potentially leading to a lot of assembly monomorphic functions.
\paragraph{Dynamic languages}
Monomorphization doesn't work for dynamic languages. TODO: explain a little bit more, with an example.
\paragraph{Modularity}
Monomorphization is not modular as it requires either access to the full source code, or to keep a representation of polymorphic code until linking in order to support separate compilation. TODO: explain more, with an example
\subsubsection{Polymorphic recursion}
Monomorphization is impossible in presence of polymorphic recursion, that is, a recursive function calling itself with a potentially different type each time. It is quite easy to show with non-uniform recursive types, as they permit to write functions whose type can grow indefinitely depending on their input. For instance, this implementation of \emph{Revisited Binary Random-Access Lists}~\cite{Oka99} in Rust:
\inputminted{rust}{ral.rs}
The Rust compiler loops indefinitely on this file as it tries to generate an infinite number of specialised versions of the \texttt{len} function. Note that without the \texttt{main} function, the compiler succeeds. That's because monomorphization can only happen at linking. Without a main function, the \texttt{len} function can not be specialised as its call sites are still partly unknown.
TODO: cutoff C++
@ -121,9 +90,7 @@ All values being pointers, polymorphic functions can deal with any type paramete
It is used by the CPython implementation of Python, where blocks are named \texttt{PyObject}~\cite{pyobject}. Consider the following code:
\begin{tcolorbox}[breakable]
\input{layout.py.tex}
\end{tcolorbox}
\inputminted{python}{layout.py}
The memory layout would be the following:
@ -167,17 +134,13 @@ TODO: link ; TODO: explain difference with python (Java has some unboxed scalar
It is used in Java~\cite{Bra+98}. The difference with Python being that only values that are used inside generics need to be boxed. Java thus has \texttt{int} values that are unboxed 32 bits integers and \texttt{Integer} values that are boxed 32 bits values. Only \texttt{Integer} can be used inside generics such as \texttt{ArrayList}. Java also has some arrays that can only contain unboxed values such as \texttt{int}.
\begin{tcolorbox}[breakable]
\input{layout.java.tex}
\end{tcolorbox}
\inputminted{java}{layout.java}
\begin{center}
\includegraphics[width=15em]{figure_java_layout.mps}
\end{center}
\begin{tcolorbox}[breakable]
\input{forbidden.java.tex}
\end{tcolorbox}
\inputminted{java}{forbidden.java}
\subsection{Advantages}
@ -211,9 +174,7 @@ In the second case, we talk about \emph{small scalars} instead of scalars becaus
This technique is used by SML/NJ and OCaml:
\begin{tcolorbox}[breakable]
\input{layout.ml.tex}
\end{tcolorbox}
\inputminted{ocaml}{layout.ml}
\begin{center}
\includegraphics[width=13em]{figure_ocaml_layout.mps}
@ -224,11 +185,11 @@ This technique is used by SML/NJ and OCaml:
\subsection{Disadvantages}
\paragraph{No full scalars}
This allows to unbox $2^{n - 1}$ scalars but not the $2^n$ full scalar range. This is why \commandbox{int} in OCaml are $63$ bits (on $64$ bits platforms). In practice this is not a problem for two reasons: it is still possible to have \emph{boxed} values covering the full range, in OCaml this is done through the \commandbox{Int64} module on 64 bits platforms. Moreover, when the programmer needs values that do not fit in small scalars, it is likely that they will not fit in full scalars either and that a boxed representation for big values is going to be needed anyway, e.g. Zarith in OCaml.
This allows to unbox $2^{n - 1}$ scalars but not the $2^n$ full scalar range. This is why \texttt{int} in OCaml are $63$ bits (on $64$ bits platforms). In practice this is not a problem for two reasons: it is still possible to have \emph{boxed} values covering the full range, in OCaml this is done through the \texttt{Int64} module on 64 bits platforms. Moreover, when the programmer needs values that do not fit in small scalars, it is likely that they will not fit in full scalars either and that a boxed representation for big values is going to be needed anyway, e.g. Zarith in OCaml.
\paragraph{Boxed floats}
There is no standard for 63 bits \commandbox{float} and processors don't have instructions to operate on them. Due to the way they are represented, it is not possible to simply truncate and shift one bit as it is done with integers. Thus, floats need to be represented as 64 bits boxed values.
There is no standard for 63 bits \texttt{float} and processors don't have instructions to operate on them. Due to the way they are represented, it is not possible to simply truncate and shift one bit as it is done with integers. Thus, floats need to be represented as 64 bits boxed values.
\subsection{Optimisations}
@ -251,9 +212,7 @@ But it is possible to use a special tag in the metadatas of the block of the arr
TODO: explain that Java could have i31 in generics
TODO: explain the Wasm way
\begin{tcolorbox}[breakable]
\input{layout.wast.tex}
\end{tcolorbox}
\inputminted{wast}{layout.wast}
\begin{center}
\includegraphics[width=13em]{figure_wasm_layout.mps}
@ -261,15 +220,19 @@ TODO: explain the Wasm way
\section{Tagged union}
Used by Lua. See~\cite{IDC05}
\section{Type-passing}
TODO: CLOS (Common Lisp Object System)
xo.m(x1, x2, ....)
m(x0, x1, x2)
TO, t1, t2 ---
Described in~\cite{HM95}. Used in the TIL compiler~\cite{TMCSHL96} and in AliceML~\cite{RLTBS04}.
int, int, int, ===== f1
int, int, float ==== f2
TODO: CLOS (Common Lisp Object System)
% xo.m(x1, x2, ....)
% m(x0, x1, x2)
% TO, t1, t2 ---
%
% int, int, int, ===== f1
% int, int, float ==== f2
\subsection{Disadvantages}
@ -277,17 +240,15 @@ TODO: it's really slow
\section{Runtime monomorphization}
Prevent empty bib~\cite{KS01}
Used in .NET~\cite{KS01}.
\subsection{Polymorphic recursion}
Runtime monomorphization supports polymorphic recursion. Even if a function may statically be called with an unbounded number of types, this number is bounded at runtime. Each time a function is called with a new type, the JIT will monomorphize it.
\begin{tcolorbox}[breakable]
\input{ral.fsx.tex}
\end{tcolorbox}
\inputminted{fsharp}{ral.fsx}
When running the above code with \commandbox{fsharpc ral.fsx && chmod +x ral.exe && ./ral.exe}, the JIT is noticeable. Each time the length of the list doubles, the type of its leaves grows. This triggers the JIT and pauses the execution. This is noticeable only on the first call to \commandbox{loop Nil}. On the second call, the functions have already been monomorphized and the execution is fast and no pause happens.
When running the above code with \texttt{fsharpc ral.fsx \&\& chmod +x ral.exe \&\& ./ral.exe}, the JIT is noticeable. Each time the length of the list doubles, the type of its leaves grows. This triggers the JIT and pauses the execution. This is noticeable only on the first call to \texttt{loop Nil}. On the second call, the functions have already been monomorphized and the execution is fast and no pause happens.
\section{Comparison}

38
src/bib.bib

@ -42,6 +42,25 @@
year={1988}
}
@inproceedings{HM95,
title={Compiling polymorphism using intensional type analysis},
author={Harper, Robert and Morrisett, Greg},
booktitle={Proceedings of the 22nd ACM SIGPLAN-SIGACT symposium on Principles of programming languages},
pages={130--141},
year={1995}
}
@article{TMCSHL96,
title={TIL: A type-directed optimizing compiler for ML},
author={Tarditi, David and Morrisett, Greg and Cheng, Perry and Stone, Chris and Harper, Robert and Lee, Peter},
journal={ACM Sigplan Notices},
volume={31},
number={5},
pages={181--192},
year={1996},
publisher={ACM New York, NY, USA}
}
@article{Bra+98,
title={Making the future safe for the past: Adding genericity to the Java programming language},
author={Bracha, Gilad and Odersky, Martin and Stoutamire, David and Wadler, Philip},
@ -85,6 +104,25 @@
publisher={IEEE}
}
@article{RLTBS04,
title={Alice through the looking glass.},
author={Rossberg, Andreas and Le Botlan, Didier and Tack, Guido and Brunklaus, Thorsten and Smolka, Gert},
journal={Trends in functional programming},
volume={5},
pages={79--96},
year={2004}
}
@article{IDC05,
title={The Implementation of Lua 5.0.},
author={Ierusalimschy, Roberto and De Figueiredo, Luiz Henrique and Celes Filho, Waldemar},
journal={J. Univers. Comput. Sci.},
volume={11},
number={7},
pages={1159--1176},
year={2005}
}
@techreport{BP11,
title = {Expressing Polymorphic Types in a Many-Sorted Language},
author = {Bobot, François and Paskevich, Andrei},

122
src/dune

@ -14,20 +14,18 @@
figure_python_block2.mps
figure_ocaml_float1.mps
figure_ocaml_float2.mps
forbidden.java.tex
layout.java.tex
layout.ml.tex
layout.py.tex
layout.wast.tex
list.c.tex
list.preprocessed.c.tex
list.d.tex
list_int.d.tex
forbidden.java
layout.java
layout.ml
layout.py
layout.wast
list.preprocessed.c
list.d
list_int.d
main.bbl
main.tex
packages.tex
ral.fsx.tex
ral.rs.tex
ral.fsx
ral.rs
styledef.tex)
(action
(progn
@ -70,35 +68,21 @@
figure_wasm_layout.mps
figure_python_block1.mps
figure_python_block2.mps
forbidden.java.tex
layout.java.tex
layout.ml.tex
layout.py.tex
layout.wast.tex
list.c.tex
list.preprocessed.c.tex
list.d.tex
list_int.d.tex
forbidden.java
layout.java
layout.ml
layout.py
layout.wast
list.preprocessed.c
list.d
list_int.d
main.tex
packages.tex
ral.fsx.tex
ral.rs.tex
ral.fsx
ral.rs
styledef.tex)
(action
(progn
(pipe-outputs
(run texfot xelatex -halt-on-error -shell-escape main.tex)
(run sed "/\\/usr\\/bin\\/texfot:/d")
(run sed "/This is XeTeX/d")
(run sed "/Package hyperref/d")
(run sed "/LaTeX Font Warning:/d")
(run sed "/(Font)/d")
(run sed "/LaTeX Warning: Empty bibliography/d")
(run sed "/LaTeX Warning: There were undefined citations/d")
(run sed "/LaTeX Warning: Citation/d")
(run sed "/Package rerunfilecheck/d")
(run sed "/Package biblatex Warning:/d")
(run sed "/Output written/d"))
(pipe-outputs
(run texfot xelatex -halt-on-error -shell-escape main.tex)
(run sed "/\\/usr\\/bin\\/texfot:/d")
@ -113,12 +97,6 @@
(run sed "/Package biblatex Warning:/d")
(run sed "/Output written/d")))))
(rule
(targets list.c.tex)
(deps styledef.tex list.c)
(action
(run pygmentize -O envname=BVerbatim list.c -o %{targets})))
(rule
(targets styledef.tex)
(deps get_style_def.py)
@ -127,12 +105,6 @@
%{targets}
(run python get_style_def.py))))
(rule
(targets list.preprocessed.c.tex)
(deps styledef.tex list.preprocessed.c)
(action
(run pygmentize -O envname=BVerbatim list.preprocessed.c -o %{targets})))
(rule
(targets list.preprocessed.c)
(deps list.c)
@ -141,42 +113,12 @@
%{targets}
(run cpp -P list.c))))
(rule
(targets list_int.d.tex)
(deps styledef.tex list_int.d)
(action
(run pygmentize -O envname=BVerbatim list_int.d -o %{targets})))
(rule
(targets list_int.d)
(deps list.d)
(action
(run gdc -c %{deps} -fsave-mixins=list_int.d)))
(rule
(targets list.d.tex)
(deps styledef.tex list.d)
(action
(run pygmentize -O envname=BVerbatim list.d -o %{targets})))
(rule
(targets ral.rs.tex)
(deps styledef.tex ral.rs)
(action
(run pygmentize -O envname=BVerbatim ral.rs -o %{targets})))
(rule
(targets ral.fsx.tex)
(deps styledef.tex ral.fsx)
(action
(run pygmentize -O envname=BVerbatim ral.fsx -o %{targets})))
(rule
(targets layout.py.tex)
(deps styledef.tex layout.py)
(action
(run pygmentize -O envname=BVerbatim layout.py -o %{targets})))
(library
(name figures)
(modules figures)
@ -203,27 +145,3 @@
(library
(name layout)
(modules layout))
(rule
(targets layout.ml.tex)
(deps styledef.tex layout.ml)
(action
(run pygmentize -O envname=BVerbatim layout.ml -o %{targets})))
(rule
(targets layout.java.tex)
(deps styledef.tex layout.java)
(action
(run pygmentize -O envname=BVerbatim layout.java -o %{targets})))
(rule
(targets layout.wast.tex)
(deps styledef.tex layout.wast)
(action
(run pygmentize -O envname=BVerbatim layout.wast -o %{targets})))
(rule
(targets forbidden.java.tex)
(deps styledef.tex forbidden.java)
(action
(run pygmentize -O envname=BVerbatim forbidden.java -o %{targets})))

28
src/layout.wast

@ -1,22 +1,26 @@
(module
(type $t1 (array (mut i32)))
(type $t2 (array (mut (ref i31))))
(type $t2 (array (mut i31ref)))
(type $tpair (struct
(field $left (ref $t1))
(field $right (ref $t2))))
(func $f
(local $array1 (ref $t1)) (local $array2 (ref $t2))
(local $array1 (ref $t1))
(local $array2 (ref $t2))
(local $pair (ref $tpair)) (local $x i32)
(array.new_canon $t1 (i32.const 0) (i32.const 3))
(array.new $t1 (i32.const 0) (i32.const 3))
(local.set $array1)
(array.set $t1 (local.get $array1) (i32.const 0) (i32.const 1))
(array.set $t1 (local.get $array1) (i32.const 1) (i32.const 2))
(array.set $t1 (local.get $array1) (i32.const 2) (i32.const 3))
(array.set $t1 (local.get $array1)
(i32.const 0) (i32.const 1))
(array.set $t1 (local.get $array1)
(i32.const 1) (i32.const 2))
(array.set $t1 (local.get $array1)
(i32.const 2) (i32.const 3))
(array.new_canon $t2 (i31.new (i32.const 0)) (i32.const 3))
(array.new $t2 (i31.new (i32.const 0)) (i32.const 3))
(local.set $array2)
(array.set $t2 (local.get $array2) (i32.const 0)
(i31.new (i32.const 42)))
@ -25,13 +29,11 @@
(array.set $t2 (local.get $array2) (i32.const 2)
(i31.new (i32.const 666)))
(struct.new_canon $tpair
(local.get $array1) (local.get $array2))
(struct.new $tpair
(local.get $array1) (local.get $array2))
(local.set $pair)
(i32.const 42)
(local.set $x)
)
(local.set $x))
(start $f)
)
(start $f))

45
src/main.tex

@ -1,28 +1,45 @@
\documentclass[nonacm]{acmart}
\documentclass[sigplan,screen,nonacm]{acmart}
\input{packages.tex}
%acmtog, acmengage, sigconf, or sigplan format.
\title{Value representation and memory layout\\in presence of polymorphism:\\a survey and critical review}
\usepackage{graphicx} % to include img
\usepackage[notransparent]{svg}
\usepackage{minted}
\author[1,2]{Léo Andrès}
\affil[1]{OCamlPro SAS, 21 rue de Châtillon, 75014 Paris, France}
\affil[2]{Université Paris-Saclay, CNRS, ENS Paris-Saclay, Inria, Laboratoire Méthodes Formelles, 91190 Gif-sur-Yvette, France}
\setmainfont{Linux Libertine O}
\setsansfont{Linux Biolinum O}
\setmonofont[Scale=MatchLowercase]{RobotoMono Nerd Font}
\begin{document}
\bibliography{bib}
\bibliographystyle{plainnat}
\maketitle
\title{Value representation and memory layout in presence of polymorphism: a survey and critical review}
\author{Léo Andrès}
\email{l@ndrs.fr}
\orcid{0000-0003-2940-6605}
\affiliation{
\institution{Université Paris-Saclay, CNRS, ENS Paris-Saclay, Inria, Laboratoire Méthodes Formelles}
\postcode{91190}
\city{Gif-sur-Yvette}
\country{France}
}
\affiliation{
\institution{OCamlPro SAS}
\streetaddress{21 rue de Châtillon}
\postcode{75014}
\city{Paris}
\country{France}
}
\begin{abstract}
Lorem ipsum et dolor sit amet.
TODO: abstract
\end{abstract}
\tableofcontents
\maketitle
\input{article.tex}
\bibliography{bib}
\bibliographystyle{plainnat}
\end{document}

32
src/packages.tex

@ -1,32 +0,0 @@
\usepackage[english]{babel}
\usepackage{fontspec} % encoding
\usepackage{graphicx} % to include img
\usepackage[notransparent]{svg}
\usepackage{color} % color power
\usepackage{hyperref} % internal and external links (e.g. mail, www)
\usepackage{authblk} % author affiliation handling
\renewcommand\Affilfont{\itshape\small}
\usepackage{fancyvrb} % source code
\input{styledef.tex} % source code
\usepackage[most]{tcolorbox}
\definecolor{darkBackground}{HTML}{282c34} % source code background
\definecolor{lightBackground}{HTML}{D7D3CB} % source code background
\tcbset{colback=darkBackground}
\DeclareTotalTCBox{\commandbox}{ s v }
{verbatim,colupper=white,colback=black!75!white,colframe=black}
{\IfBooleanT{#1}{\textcolor{red}{\ttfamily\bfseries \$ }}%
\lstinline[language=sh,keywordstyle=\color{blue!35!white}\bfseries]^#2^}
\setmainfont{Linux Libertine O}
\setsansfont{Linux Biolinum O}
%\setsansfont{TeX Gyre Heros}
\setmonofont[Scale=MatchLowercase]{RobotoMono Nerd Font}
\hypersetup{colorlinks=true, pdfstartview=FitH}
Loading…
Cancel
Save