report comments processed

This commit is contained in:
User 2018-03-01 23:53:49 +01:00
parent ecd3072e17
commit e20ed8472b
3 changed files with 42 additions and 39 deletions

View File

@ -12,7 +12,7 @@ This section describes the language features of Boppi. The tokens used in the sy
At the heart of the language are basic arithmetic, logic and compound expressions and literals. These support basic operations for boolean, integer and character types. At the heart of the language are basic arithmetic, logic and compound expressions and literals. These support basic operations for boolean, integer and character types.
\paragraph{Syntax} \paragraph{Syntax}
The basic expression language consists of a \verb|program| that contains a sequence of statements separated by semicolons, \verb|stats|. A single \verb|stat|ement in the basic language can only be an expression, which can be an arithmetic or logical expression, an integer, a character, a boolean or another sequence of statements. The ANTLR parser tree can be seen in \cref{basic-syntax}. The basic expression language consists of a \verb|program| that contains a sequence of statements, \verb|stats|, separated by semicolons. A single \verb|stat|ement in the basic language can only be an expression, which can be an arithmetic or logical expression, an integer, a character, a boolean or another sequence of statements. The ANTLR parser tree can be seen in \cref{basic-syntax}.
\begin{figure} \begin{figure}
\caption{ANTLR4 code of the basic expression language of Boppi} \caption{ANTLR4 code of the basic expression language of Boppi}
\label{basic-syntax} \label{basic-syntax}
@ -62,11 +62,11 @@ See \cref{basic-examples} for a few examples of basic expressions. Since input a
\end{figure} \end{figure}
\paragraph{Use} \paragraph{Use}
\verb|#prefix1|, \verb|#infix1| and \verb|#infix2| restrict their operand types and result type to integers. \verb|#infix3| restricts its operands to integers and sets the result type to boolean. However, when the operator is \verb|EQ| or \verb|NEQ|, the operands can be of any type as long as both have the same type. The resulting type will still be a boolean. \verb|#infix4| and \verb|#infix5| only allow booleans as operands and, again, returns a boolean. \verb|#prefix1|, \verb|#infix1| and \verb|#infix2| (negation, multiplication and division, addition and subtraction) restrict their operand types and result type to integers, except for the \verb|#prefix| \emph{NOT}, which only allows a boolean as its operand and results in a boolean. \verb|#infix3| (comparison) restricts its operands to integers and sets the result type to boolean. However, when the operator is \verb|EQ| or \verb|NEQ|, the operands can be of any type as long as both have the same type. The resulting type will still be a boolean. \verb|#infix4| (logical and) and \verb|#infix5| (logical or) only allow booleans as operands and, again, return a boolean.
\paragraph{Semantics} \paragraph{Semantics}
A program consists of one compound expression. A program consists of one compound expression.
\verb|COMPOUND| separates single expressions and evaluates them left to right. The rightmost expression is the return value of the expression and other return values are discarded. \verb|COMPOUND| separates single expressions and evaluates them left to right. The rightmost expression is the return value of the expression. For any other expressions that result in a value, this value is discarded.
Both \verb|#parens| and \verb|#block| contain a compound expression, however \verb|#block| introduces a deeper scope for the expression within, as clarified in \cref{variables-section}. Both \verb|#parens| and \verb|#block| contain a compound expression, however \verb|#block| introduces a deeper scope for the expression within, as clarified in \cref{variables-section}.
\paragraph{Code generation} \paragraph{Code generation}
@ -75,6 +75,8 @@ Operators first generate their operands, locking the result register, then gener
The compound expression simply generates its inner expressions in order. See \cref{basic-codegen} for an example of generated code. The compound expression simply generates its inner expressions in order. See \cref{basic-codegen} for an example of generated code.
\begin{figure} \begin{figure}
\caption{Generated code for basic expressions in Boppi.}
\label{basic-codegen}
\begin{subfigure}{0.2\textwidth} \begin{subfigure}{0.2\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -115,8 +117,6 @@ loadI 4 => __2 // 4
add __1,__2 => __1 // + add __1,__2 => __1 // +
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Generated code for basic expressions in Boppi.}
\label{basic-codegen}
\end{figure} \end{figure}
@ -189,14 +189,19 @@ A variable must be declared before it can be used and its type must be given in
Regarding lexical scopes, a variable only exists in the scope in which it is declared and deeper scopes. A variable can be redeclared, effectively hiding the original variable, in a deeper scope, linking the name to a new variable. The type of the redeclared variable does not have to match the original type. Regarding lexical scopes, a variable only exists in the scope in which it is declared and deeper scopes. A variable can be redeclared, effectively hiding the original variable, in a deeper scope, linking the name to a new variable. The type of the redeclared variable does not have to match the original type.
\paragraph{Semantics} \paragraph{Semantics}
\verb|#declare| introduces a new variable to the current scope. It does not perform any action during runtime, but the identifier and its type are recorded in a symbol table during compilation. Moreover, the compiler allocates a space for the variable in the local data segment of the main AR. The identifier and its allocated space will be freed once the current scope is closed.\\ \verb|#declare| introduces a new variable to the current scope. It does not perform any action during runtime, but the identifier and its type are recorded and the variable can be assigned and used from this point onwards.\\
\verb|#assign| first evaluates the expression on the right hand side and then stores the result at the space allocated for that variable.\\ \verb|#assign| first evaluates the expression on the right hand side, then stores the result in the variable on the left hand and finally passes the result on.\\
\verb|#getVariable| retrieves the value of a variable from the allocates space. \verb|#getVariable| retrieves the value of a variable.\\
\paragraph{Code generation} \paragraph{Code generation}
Declarations do not generate any code. An assignment generates \verb|addI r_arp,k => r| followed by \verb|store r => r| (\verb|cstore r => r| for characters) for some register \verb|r|. The local offset, \verb|k|, is decided by the symbol table. The reason for calculating an address and using a plain \verb|store| instead of using \verb|storeAI| directly, is because the address is calculated differently for different kinds of variables. Likewise, a \emph{use} of a simple variable generates \verb|addI r_arp,k => r| followed by \verb|load r => r| (\verb|cload r => r| for characters).\\ Declarations do not generate any code.\\
A \verb|#variableSimple| calculates the address of a simple variable using \verb|addI r_arp,c_offset => r_address|, where the \verb|c_offset| is decided by the symbol table. Note that, with the addition of functions, see \cref{functions}, the \verb|r_arp| becomes a temporary variable \verb|i2i r_arp => r_temp|. This is followed by a \verb|loadAI r_temp,OFFSET_CALLER_ARP => r_temp| for each lexical scope between the current scope and where the variable is declared.\\
An assignment (\verb|#assign|) first visits the expression on the left hand and keeps track of it in a \verb|r_result| register. Then the variable address is retrieved as above. And finally it generates a \verb|store r_result => r_address| (\verb|cstore r_result => r_address| for characters) to store the result.\\
Likewise, a use of a variable (\verb|#getVariable|) first retrieves the address as above, and then loads the variable using \verb|load r_address => r_result| (\verb|cload r_address => r_result| for characters).\\
An example of (chained) assignments, uses and offsets can be seen in \cref{variables-code}. As can be seen in de generated ILOC code, the variables x, y, unused, b and c have the respective offsets of 0, 4, 8, 9 and 13. An example of (chained) assignments, uses and offsets can be seen in \cref{variables-code}. As can be seen in de generated ILOC code, the variables x, y, unused, b and c have the respective offsets of 0, 4, 8, 9 and 13.
\begin{figure} \begin{figure}
\caption{Generated code for basic variable use in Boppi.}
\label{variables-code}
\begin{subfigure}{0.2\textwidth} \begin{subfigure}{0.2\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -238,8 +243,6 @@ addI r_arp,13 => __2 // add offset
store __1 => __2 // to c store __1 => __2 // to c
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Generated code for basic variable use in Boppi.}
\label{variables-code}
\end{figure} \end{figure}
@ -264,6 +267,8 @@ I/O introduces two expression types: input and output. In an input expression, a
\paragraph{Examples} \paragraph{Examples}
See \cref{io-example} for the basic use of input and output expressions. See \cref{io-example} for the basic use of input and output expressions.
\begin{figure} \begin{figure}
\caption{Example code for I/O in Boppi.}
\label{io-example}
\begin{subfigure}{0.5\textwidth} \begin{subfigure}{0.5\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -287,8 +292,6 @@ print(aBool);
<<< true <<< true
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Example code for I/O in Boppi.}
\label{io-example}
\end{figure} \end{figure}
\paragraph{Use} \paragraph{Use}
@ -380,6 +383,8 @@ expr
\paragraph{Examples} \paragraph{Examples}
A few examples of \emph{if} and \emph{while} expressions can be seen in \cref{conditional-example}. The first \emph{if} construction shows how it can be used as an expression with a result, in this case either the character \verb|T| or \verb|F|. Next is an \emph{if} construction with only a consequent and no alternative. Lastly two \emph{while} constructions are presented to show the use of scoped variables and looping. A few examples of \emph{if} and \emph{while} expressions can be seen in \cref{conditional-example}. The first \emph{if} construction shows how it can be used as an expression with a result, in this case either the character \verb|T| or \verb|F|. Next is an \emph{if} construction with only a consequent and no alternative. Lastly two \emph{while} constructions are presented to show the use of scoped variables and looping.
\begin{figure} \begin{figure}
\caption{Example of conditionals in Boppi.}
\label{conditional-example}
\begin{subfigure}{0.6\textwidth} \begin{subfigure}{0.6\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -423,8 +428,6 @@ print(n);
<<< 496 <<< 496
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Example of conditionals in Boppi.}
\label{conditional-example}
\end{figure} \end{figure}
\paragraph{Use} \paragraph{Use}
@ -443,6 +446,8 @@ When an alternative is present, the \verb|cbr| jumps to either the \verb|if_t| o
The \emph{while} loop has three jump targets, one for evaluating the condition, one for executing the body of the loop and one for breaking out of the loop. The compiler first produces a \verb|jumpI -> while_f| to jump to the condition. Then a \verb|while_t: nop| is produced as a jump target followed by the loop body. Next, a jump target for the condition, \verb|while_f: nop|, and the condition and \verb|cbr r_k -> while_t,while_e| are produced, where \verb|r_k| is the register that holds the result of the condition. Finally, the breaking jump target \verb|while_e: nop| is produced. See \cref{while-code} for an example. The \emph{while} loop has three jump targets, one for evaluating the condition, one for executing the body of the loop and one for breaking out of the loop. The compiler first produces a \verb|jumpI -> while_f| to jump to the condition. Then a \verb|while_t: nop| is produced as a jump target followed by the loop body. Next, a jump target for the condition, \verb|while_f: nop|, and the condition and \verb|cbr r_k -> while_t,while_e| are produced, where \verb|r_k| is the register that holds the result of the condition. Finally, the breaking jump target \verb|while_e: nop| is produced. See \cref{while-code} for an example.
\begin{figure} \begin{figure}
\caption{Generated code for an if expression in Boppi.}
\label{if-code}
\begin{subfigure}{0.2\textwidth} \begin{subfigure}{0.2\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -472,11 +477,11 @@ if_f1: nop //
i2i __2 => __1 // result i2i __2 => __1 // result
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Generated code for an if expression in Boppi.}
\label{if-code}
\end{figure} \end{figure}
\begin{figure} \begin{figure}
\caption{Generated code for a while expression in Boppi.}
\label{while-code}
\begin{subfigure}{0.2\textwidth} \begin{subfigure}{0.2\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -498,8 +503,6 @@ while_f1: nop // condition target
while_e2: nop // end target while_e2: nop // end target
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Generated code for a while expression in Boppi.}
\label{while-code}
\end{figure} \end{figure}
@ -540,6 +543,8 @@ type
Functions can be used in many ways in Boppi. They can have any number of arguments and a return value is optional. Since Boppi allows for side effects, functions without a return value have their use. One example is shown in \cref{functions-example}: \verb|logPrint| counts the number of times the function has been called by incrementing the non-local variable \verb|numCalls|. A function with a return value can used in an expression, as can be seen in the same example with the function \verb|add|. Functions can be used in many ways in Boppi. They can have any number of arguments and a return value is optional. Since Boppi allows for side effects, functions without a return value have their use. One example is shown in \cref{functions-example}: \verb|logPrint| counts the number of times the function has been called by incrementing the non-local variable \verb|numCalls|. A function with a return value can used in an expression, as can be seen in the same example with the function \verb|add|.
\begin{figure} \begin{figure}
\caption{Example of functions in Boppi.}
\label{functions-example}
\begin{subfigure}{0.6\textwidth} \begin{subfigure}{0.6\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -570,8 +575,6 @@ print(10*add(3, 4));
<<< 70 <<< 70
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Example of functions in Boppi.}
\label{functions-example}
\end{figure} \end{figure}
\paragraph{Use} \paragraph{Use}
@ -599,8 +602,8 @@ In a function declaration, the generator performs the following steps:
\item Store the address of the tuple in the function variable's offset. \item Store the address of the tuple in the function variable's offset.
\item Increment the reference count of the current AR and its parents. \item Increment the reference count of the current AR and its parents.
\end{enumerate} \end{enumerate}
The tuple is required for two reasons. Firstly, because the current AR is relevant in case the function uses non-local variables and is used outside the current function. Secondly, because the AR size is relevant due to \cref{problems-reassigned-closures}. The tuple is referenced rather than stored in place because it is easier to move around a single integer.\\ The tuple is required for two reasons. Firstly, the current AR is relevant in case the function uses non-local variables and is used outside the current function. Secondly, the AR size is relevant due to the way ARs are constructed, see \cref{problems-reassigned-closures}. The tuple is referenced rather than stored in place because it is easier to move around a single integer.\\
The references to the AR's parents are incremented because of \cref{problem-closures}.\\ The references to the AR's parents are incremented as one solution to implementing closures, see \cref{problem-closures}.\\
Freeing local reference variables at the end of the function is done as a simple mechanism to clean up memory. A better approach would be to generate cleanup procedures, as discussed in \cref{future-work}.\\ Freeing local reference variables at the end of the function is done as a simple mechanism to clean up memory. A better approach would be to generate cleanup procedures, as discussed in \cref{future-work}.\\
In a function call, the generator performs a number of steps: In a function call, the generator performs a number of steps:
@ -628,6 +631,8 @@ Note there is no particular reason why the registers are saved to the stack, whi
For a simple example of a function declaration and call, see \cref{functions-code}. Because the generated ILOC spans more than 100 lines, it can be found as a separate file. For a simple example of a function declaration and call, see \cref{functions-code}. Because the generated ILOC spans more than 100 lines, it can be found as a separate file.
\begin{figure} \begin{figure}
\caption{Generated code for functions in Boppi.}
\label{functions-code}
\begin{subfigure}{0.5\textwidth} \begin{subfigure}{0.5\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -644,8 +649,6 @@ print(successor(x));
\caption{Generated ILOC} \caption{Generated ILOC}
See \emph{doc/successor.iloc.txt}. Instructions 178-193 form the body of \verb|successor| with 180-183 generated by the expression in the body, 194-217 form the allocation of \verb|successor| as a variable, 222-270 form a call to \verb|successor| and 272-293 form the deallocation of \verb|successor|. See \emph{doc/successor.iloc.txt}. Instructions 178-193 form the body of \verb|successor| with 180-183 generated by the expression in the body, 194-217 form the allocation of \verb|successor| as a variable, 222-270 form a call to \verb|successor| and 272-293 form the deallocation of \verb|successor|.
\end{subfigure} \end{subfigure}
\caption{Generated code for functions in Boppi.}
\label{functions-code}
\end{figure} \end{figure}
@ -685,6 +688,8 @@ variable
An example of using arrays can be seen in \cref{arrays-example}. An example of using arrays can be seen in \cref{arrays-example}.
\begin{figure} \begin{figure}
\caption{Example of arrays in Boppi.}
\label{arrays-example}
\begin{subfigure}{0.6\textwidth} \begin{subfigure}{0.6\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -708,8 +713,6 @@ od
<<< 8 <<< 8
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Example of arrays in Boppi.}
\label{arrays-example}
\end{figure} \end{figure}
\paragraph{Use} \paragraph{Use}
@ -768,6 +771,8 @@ See \cref{arrays-code} for a simple example of a nested array. Because the gener
\begin{figure} \begin{figure}
\caption{Generated code for arrays in Boppi.}
\label{arrays-code}
\begin{subfigure}{0.2\textwidth} \begin{subfigure}{0.2\textwidth}
\caption{Boppi code} \caption{Boppi code}
\begin{minted}{boppi} \begin{minted}{boppi}
@ -784,8 +789,6 @@ print(matrix[0][1]);
\caption{Generated ILOC} \caption{Generated ILOC}
See \emph{doc/nestedArray.iloc.txt}. Lines 178-183 allocate the top-level array, whereas 184-189 and 196-200 allocate the second-level arrays. Lines 206-215 try to decrement the reference to the current array of \verb|matrix| if assigned, which it isn't. Lines 217-229 increment and decrement the reference count of the outer array because of the assignment expression and the statement ending. Lines 230-253 retrieve the matrix's element (0,1), which is the two. See \emph{doc/nestedArray.iloc.txt}. Lines 178-183 allocate the top-level array, whereas 184-189 and 196-200 allocate the second-level arrays. Lines 206-215 try to decrement the reference to the current array of \verb|matrix| if assigned, which it isn't. Lines 217-229 increment and decrement the reference count of the outer array because of the assignment expression and the statement ending. Lines 230-253 retrieve the matrix's element (0,1), which is the two.
\end{subfigure} \end{subfigure}
\caption{Generated code for arrays in Boppi.}
\label{arrays-code}
\end{figure} \end{figure}

View File

@ -45,6 +45,8 @@ While building a program, the generator reserves and uses registers drawn from a
\begin{figure} \begin{figure}
\caption{Java code for generating an addition expression and code example of 32+10.}
\label{generator-sum}
\begin{subfigure}{0.7\textwidth} \begin{subfigure}{0.7\textwidth}
\begin{minted}{java} \begin{minted}{java}
@Override @Override
@ -66,12 +68,10 @@ loadI 10 => g
add r, g => r add r, g => r
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Java code for generating an addition expression and code example of 32+10.}
\label{generator-sum}
\end{figure} \end{figure}
The generator has a number of helper methods to generate calls to \emph{memlib} functions. These methods take a number of registers and produce a sequence of ILOC instructions. Moreover, it has a few helper methods to increment and decrement AR references because of \cref{problem-closures}.\\ The generator has a number of helper methods to generate calls to \emph{memlib} functions. These methods take a number of registers and produce a sequence of ILOC instructions. Moreover, it has a few helper methods to increment and decrement AR references because of the solution to closures (\cref{problem-closures}).\\
The generator has a few scenarios for which it produces \verb|haltI| instructions with the appropriate \verb|ERROR_x| value. They may either be generated due to forcing an incorrect program to compile or due to a runtime error. Currently negative array sizes and array out-of-bounds errors are the only runtime errors that lead to a \verb|haltI| instruction.\\ The generator has a few scenarios for which it produces \verb|haltI| instructions with the appropriate \verb|ERROR_x| value. They may either be generated due to forcing an incorrect program to compile or due to a runtime error. Currently negative array sizes and array out-of-bounds errors are the only runtime errors that lead to a \verb|haltI| instruction.\\
@ -84,7 +84,7 @@ Lastly, the generator prepends a program with \emph{memlib} and \emph{stdlib} to
\section{Symbol table} \section{Symbol table}
The symbol table \emph{pp.s1184725.boppi.CachingSymbolTable} keeps track of existing symbols (variables) while the checker traverses a Boppi program. It is generic for the type system. The symbol table also manages lexical scope objects (\emph{pp.s1184725.boppi.FunctionScope.java}) to decide variable offsets and local data sizes.\\ The symbol table \emph{pp.s1184725.boppi.CachingSymbolTable} keeps track of existing symbols (variables) while the checker traverses a Boppi program. It is generic for the type system. The symbol table also manages lexical scope objects (\emph{pp.s1184725.boppi.FunctionScope.java}) to decide variable offsets and local data sizes.\\
The symbol table has three methods for variable symbols and act analogous to dictionaries: \verb|get|, \verb|put| and \verb|has|. Furthermore, there are six methods for opening and closing scopes, of which two are \"safe\" as they both open and close a scope. \verb|withFunctionScope| opens a lexical scope for a function, runs the provided function and then closes the scope. \verb|withScope| also opens a scope, runs the provided function and closes the scope, however variables will be produced by an enclosing function scope.\\ The symbol table has three methods for variable symbols and act analogous to dictionaries: \verb|get|, \verb|put| and \verb|has|. Furthermore, there are six methods for opening and closing scopes, of which two are ``safe'' as they both open and close a scope. \verb|withFunctionScope| opens a lexical scope for a function, runs the provided function and then closes the scope. \verb|withScope| also opens a scope, runs the provided function and closes the scope, however variables will be produced by an enclosing function scope.\\
For example, in \cref{symbol-table-scopes} x, y, nested x and z are all given offsets in the same \verb|FunctionScope|. However, the nested x and z are defined in a deeper lexical scope, so they only exist within those scopes and their name may override a variable name in the same function scope (but a higher lexical scope). Moreover, since nested x and z are in unrelated scopes, they may have the same offset in the function. For example, in \cref{symbol-table-scopes} x, y, nested x and z are all given offsets in the same \verb|FunctionScope|. However, the nested x and z are defined in a deeper lexical scope, so they only exist within those scopes and their name may override a variable name in the same function scope (but a higher lexical scope). Moreover, since nested x and z are in unrelated scopes, they may have the same offset in the function.
\begin{figure} \begin{figure}
@ -143,22 +143,22 @@ The calling convention for \emph{memlib} and other internal subroutines consists
For example, \emph{memalloc} requires one argument, the requested size, and returns the allocated address. Firstly, the return address is pushed, which is either loaded from a label or calculated from the current address. Secondly, the size is pushed to the stack. Thirdly, the jump to \verb|memalloc| is made and the subroutine is executed. After execution of malloc, the object's location is popped from the stack. For example, \emph{memalloc} requires one argument, the requested size, and returns the allocated address. Firstly, the return address is pushed, which is either loaded from a label or calculated from the current address. Secondly, the size is pushed to the stack. Thirdly, the jump to \verb|memalloc| is made and the subroutine is executed. After execution of malloc, the object's location is popped from the stack.
\begin{figure} \begin{figure}
\includegraphics{memlib-objects}
\caption{Structure of objects and free blocks with \emph{memlib}. A free block either points to the next free block or to \emph{null}.} \caption{Structure of objects and free blocks with \emph{memlib}. A free block either points to the next free block or to \emph{null}.}
\label{memlib-objects} \label{memlib-objects}
\includegraphics{memlib-objects}
\end{figure} \end{figure}
\begin{figure} \begin{figure}
\includegraphics[width=\textwidth]{memlib-start}
\caption{Structure of the memory after initialisation by \emph{memlib}.} \caption{Structure of the memory after initialisation by \emph{memlib}.}
\label{memlib-start} \label{memlib-start}
\includegraphics[width=\textwidth]{memlib-start}
\end{figure} \end{figure}
\begin{figure} \begin{figure}
\includegraphics[width=\textwidth]{memlib-onealloc}
\caption{Structure of the memory after allocating a single object of size 8 with \emph{memlib}.} \caption{Structure of the memory after allocating a single object of size 8 with \emph{memlib}.}
\label{memlib-onealloc} \label{memlib-onealloc}
\includegraphics[width=\textwidth]{memlib-onealloc}
\end{figure} \end{figure}
\begin{figure} \begin{figure}
\includegraphics[width=\textwidth]{memlib-runtime}
\caption{Structure of the memory after allocating objects of sizes 8, 4 and 12 respectively and deallocating the object of size 4.} \caption{Structure of the memory after allocating objects of sizes 8, 4 and 12 respectively and deallocating the object of size 4.}
\label{memlib-runtime} \label{memlib-runtime}
\includegraphics[width=\textwidth]{memlib-runtime}
\end{figure} \end{figure}

View File

@ -43,6 +43,8 @@ od;
\begin{figure} \begin{figure}
\caption{Examples of input and output on \emph{fibonacciRecursive}.}
\label{test-example-runs}
\begin{subfigure}{0.2\textwidth} \begin{subfigure}{0.2\textwidth}
\begin{minted}{boppi} \begin{minted}{boppi}
> 1 > 1
@ -80,6 +82,4 @@ od;
> -1337 > -1337
\end{minted} \end{minted}
\end{subfigure} \end{subfigure}
\caption{Examples of input and output on \emph{fibonacciRecursive}.}
\label{test-example-runs}
\end{figure} \end{figure}