writinggggggg

This commit is contained in:
2024-07-09 15:54:35 +00:00
parent 7419a4d836
commit 5da03f07f1
2 changed files with 68 additions and 4 deletions

View File

@@ -224,9 +224,9 @@ Two terms are added in addition to the usual simply-typed lambda calculus, $dela
\subsection{Syntactic sugar of the feedback expression in mimium}
\label{sec:mimium}
\begin{lstlisting}[label=lst:onepole,language=Rust,caption=Example of the code of one-pole filter in mimium.]
\begin{lstlisting}[label=lst:onepole,language=Rust,caption=\it Example of the code of one-pole filter in mimium.]
fn onepole(x,g){
return x*(1.0-g) + self*g
x*(1.0-g) + self*g
}
\end{lstlisting}
@@ -300,7 +300,7 @@ The list of instructions is shown in Fig.\ref{fig:instruction} (basic arithmetic
In pseudo-code describing an functionality, \texttt{R(A)} means that data is moved in and out through the register (call stack) according to the numerical value of the operand \texttt{A}. \texttt{K(A)} means that it retrieves the \texttt{A}-th number in the static variable field of the compiled programm. \texttt{U(A)} means that referring \texttt{A}-th Upvalue of the current function.
In addition to Lua's Upvalue operation, 3 operations related to internal state variables over time, \texttt{GETSTATE}, \texttt{SETSTATE}, \texttt{SHIFTSTATE} are added.
In addition to Lua's Upvalue operation, 4 operations related to internal state variables over time, \texttt{GETSTATE}, \texttt{SETSTATE}, \\ \texttt{SHIFTSTATE} and \texttt{DELAY} are added.
\begin{figure*}[ht]
\tt
@@ -331,12 +331,76 @@ DIVF & A B C & R(A) := R(B) as float / R(C) as float\\
\caption{\label{fig:instruction}{\it Instruction sets for VM to run $\lambda_{mmm}$.}}
\end{figure*}
\subsection{Compilation to the VM instructions}
Listing.\ref{lst:bytecodes_onepole} shows an basic example when the mimium code in Listing.\ref{lst:onepole} is compiled into VM bytecode. When \texttt{self} is referenced, the value is obtained with the \texttt{GETSTATE} instruction, and the internal state is updated by storing the return value with the \\ \texttt{SETSTATE} instruction before returning the value with \texttt{RETURN} from the function. Here, the actual return value is obtained by the second GETSTATE instruction in order to return the initial value of the internal state when time=0.
For example, when a time counter is written as \texttt{| | \{self + 1\}}, it is the compiler's design choice whether the return value of time=0 should be 0 or 1. but at present the author think it is more intuitive to return 0. If the design is to return 1 when time = 0, the second \texttt{GETSTATE} instruction can be removed and the value for the \texttt{RETURN} instruction should be \texttt{R(2)}.
\begin{lstlisting}[float,floatplacement=H,label=lst:bytecodes_onepole,caption=\it Compiled VM instructions of one-pole filter example in Listing.\ref{lst:onepole}]
CONSTANTS:[1.0]
fn onepole(x,g) state_size:1
MOVECONST 2 0 // load 1.0
MOVE 3 1 // load g
SUBF 2 2 3 // 1.0 - g
MOVE 3 0 // load x
MULF 2 2 3 // x * (1.0-g)
GETSTATE 3 // load self
MOVE 4 1 // load g
MULF 3 3 4 // self * g
ADDF 2 2 3 // compute result
GETSTATE 3 // prepare return value
SETSTATE 2 // store to self
RETURN 3 1
\end{lstlisting}
\section{Discussion}
\label{sec:discussion}
\subsection{Internal State}
\subsection{Different behaviour depending on the position of \texttt{let} binding}
Because mimium treats functions that have internal states which change over time, when higher-order functions are used, there is a counterintuitive behavior compared to general functional programming languages.
An example is the higher-order function \texttt{filterbank}, which duplicates \texttt{filter} function \texttt{N} times parametrically, and mix them together. Listing.\ref{lst:filterbank_bad} is an example of an incorrect code, and Listing.\ref{lst:filterbank_good} is an example of the code that behave correctly. The difference between Listing.\ref{lst:filterbank_bad} and Listing.\ref{lst:filterbank_good} is that the recursive calls in the filterbank function are written directly in the inner function to be returned, and the recursive calls in the filterbank function are written with \texttt{let} binding out of the inner function\footnote[2]{In the previous specification of mimium in \cite{matsuura2021a}, the binding of new variable and destructive assignment were the same syntax(\texttt{x = a}) but the syntax for the variable binding has changed to use \texttt{let} keyword.}. Similarly, in the \texttt{dsp} function that will be called by the audio driver, the difference is whether the filterbank function is executed inside \texttt{dsp} or bound with \texttt{let} once in the global context.
In the case of normal functional language, if all the functions used in a composition do not contain destructive assignments, the calculation process will not change even if the variable bound by let is manually replaced with its term(Beta reduction), as in the conversion from Listing.\ref{lst:filterbank_good} to Listing.\ref{lst:filterbank_bad}.
But in mimium, there are two major stages of evaluation: the code is evaluated in the global environment (finalization of the signal processing graph) at first, then the dsp function is repeatedly executed (actual signal processing), and the function may involve implicit internal state updates. Therefore, even though the code does not include destructive assignments, the recursive execution of the \texttt{filterbank} function is performed only once in Listing.\ref{lst:filterbank_good} for the evaluation of the global environment, whereas in Listing.\ref{lst:filterbank_bad}, every sample the dsp function is executed, the recursive function is executed and a closure is generated. Since the initialization of the internal state in the closure is performed at the time of closure allocation, in the example of Listing\ref{lst:filterbank_bad}, the internal state of the closure after the evaluation of \texttt{filterbank} is reset at each time step.
\begin{lstlisting}[float,floatplacement=H,label=lst:filterbank_bad,language=Rust,caption=\it Wrong example of the code that duplicate filter parametrically.]
fn bandpass(x,freq){
//...
}
fn filterbank(n,filter){
if (n>0){
|x,freq| filter(x,freq+n*100)
+ filterbank(n-1,filter)(x,freq)
}else{
0
}
}
fn dsp(){
filterbank(3,bandpass)
}
\end{lstlisting}
\begin{lstlisting}[float,floatplacement=H,label=lst:filterbank_good,language=Rust,caption=\it Corrected example of the code that duplicate filter parametrically.]
fn filterbank(n,filter){
let next = filterbank(n-1,filter)
if (n>0){
|x,freq| filter(x,freq+n*100)
+ next(x,freq)
}else{
0
}
}
let myfilter = filterbank(3,bandpass)
fn dsp(){
myfilter(x,1000)
}
\end{lstlisting}
\section{Conclusions}

View File

@@ -33,5 +33,5 @@
}
\end{tabular}
\caption{\label{fig:semantics}{\it Big-step Semantics of $\lambda_{mmm}$.}}
\caption{\label{fig:semantics}{\it Excerpt of the big-step semantics of $\lambda_{mmm}$.}}
\end{figure*}