fix issue with SECD machine post
This commit is contained in:
parent
a21faac1e0
commit
f644309ae0
|
@ -3,9 +3,12 @@ layout: post
|
||||||
title: "A first look at SECD machines"
|
title: "A first look at SECD machines"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
The SECD machine is a virtual machine designed to evaluate lambda expressions. It's purpose is to be a more natural goal for compilers than assembly while maintaining reasonable execution speed. In this blog post you will get a quick intro to SECD machines and an overview of a simple implementation.
|
The SECD machine is a virtual machine designed to evaluate lambda expressions. It's purpose is to be a more natural goal for compilers than assembly while maintaining reasonable execution speed. In this blog post you will get a quick intro to SECD machines and an overview of a simple implementation.
|
||||||
<!--more-->
|
<!--more-->
|
||||||
|
|
||||||
|
{% katexmm %}
|
||||||
|
|
||||||
## The SECD Machine
|
## The SECD Machine
|
||||||
|
|
||||||
SECD stands for Stack Environment Control Dump, all of which but the environment are stacks in the SECD machine. The machine operates by reading instructions from the control stack which operate on itself and the other stacks. A lambda is implemented as its body coupled with its environment. Application is done with the "apply" instruction which pops a lambda off the stack and adds the next element of the stack to the lambdas environment environment, binding the variable of the lambda. The previous stacks are then pushed onto the dump stack. When the lambda has been fully reduced the return instruction is used to save the top of the stack, the result of the reduction, and restores the stacks from the dump stack.
|
SECD stands for Stack Environment Control Dump, all of which but the environment are stacks in the SECD machine. The machine operates by reading instructions from the control stack which operate on itself and the other stacks. A lambda is implemented as its body coupled with its environment. Application is done with the "apply" instruction which pops a lambda off the stack and adds the next element of the stack to the lambdas environment environment, binding the variable of the lambda. The previous stacks are then pushed onto the dump stack. When the lambda has been fully reduced the return instruction is used to save the top of the stack, the result of the reduction, and restores the stacks from the dump stack.
|
||||||
|
@ -33,14 +36,14 @@ In this section a SECD machine implemented in Haskell will be introduced bit by
|
||||||
### Data structures
|
### Data structures
|
||||||
|
|
||||||
The machine will only be able to recognise two types of values. Integers and Closures.
|
The machine will only be able to recognise two types of values. Integers and Closures.
|
||||||
```
|
```haskell
|
||||||
data Val
|
data Val
|
||||||
= I Int
|
= I Int
|
||||||
| Clo Int [Val] [Inst] -- number of arguments, environment, instructions
|
| Clo Int [Val] [Inst] -- number of arguments, environment, instructions
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
```
|
```
|
||||||
The machine comes with the following instruction set.
|
The machine comes with the following instruction set.
|
||||||
```
|
```haskell
|
||||||
data Inst
|
data Inst
|
||||||
= Const Int
|
= Const Int
|
||||||
| Global Int
|
| Global Int
|
||||||
|
@ -77,36 +80,37 @@ All stacks grow from right to left, that is, the left most element is at the top
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th align=center colspan="3">Before</th><th align=center colspan="3">After</th>
|
<th align=center colspan="3">Before</th><th align=center colspan="3">After</th>
|
||||||
<tr>
|
|
||||||
<th>Control</th><th>Env</th><th>Stack</th><th>Control</th><th>Env</th><th>Stack</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Const i : c</td><td>e</td><td>s</td><td>c</td><td>e</td><td>i : s</td>
|
<th>Control</th><th>Env</th><th>Stack</th><th>Control</th><th>Env</th><th>Stack</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Global i : c</td><td>e</td><td>s</td><td>c</td><td>e</td><td>Globals[i] : s</td>
|
<td>Const i : c</td><td>e</td><td>s</td><td>c</td><td>e</td><td>i : s</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Local i : c</td><td>e</td><td>s</td><td>c </td><td> e</td><td>e[i] : s</td>
|
<td>Global i : c</td><td>e</td><td>s</td><td>c</td><td>e</td><td>Globals[i] : s</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Closure n a : $c_1$ ... $c_n$ : c</td><td>e</td><td>s</td><td>c</td><td>e</td><td>Closure a {e} [$c_1$ ... $c_n$] : s</td>
|
<td>Local i : c</td><td>e</td><td>s</td><td>c </td><td> e</td><td>e[i] : s</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>App : c</td><td>e</td><td>Closure {e'} [c'] : v : s</td><td>c'</td><td>v : e'</td><td>Closure$^0$ {e} [c] : s</td>
|
<td>Closure n a : $c_1$ ... $c_n$ : c</td><td>e</td><td>s</td><td>c</td><td>e</td><td>Closure a {e} [$c_1$ ... $c_n$] : s</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>App : c</td><td>e</td><td>Closure$^n$ {e'} [c'] : v : s</td><td>c</td><td>e</td><td>Closure$^{n - 1}$ {v : e'} [c'] : s</td>
|
<td>App : c</td><td>e</td><td>Closure {e'} [c'] : v : s</td><td>c'</td><td>v : e'</td><td>Closure$^0$ {e} [c] : s</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Ret : c </td><td>e</td><td>v : Closure$^0$ \{e'\} [c'] : s </td><td> c'</td><td>e' </td><td> v : s</td>
|
<td>App : c</td><td>e</td><td>Closure$^n$ {e'} [c'] : v : s</td><td>c</td><td>e</td><td>Closure$^{n - 1}$ {v : e'} [c'] : s</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Dup : c</td><td>e</td><td>v : s</td><td>c</td><td>e</td><td>v : v : s</td>
|
<td>Ret : c </td><td>e</td><td>v : Closure$^0$ \{e'\} [c'] : s </td><td> c'</td><td>e' </td><td> v : s</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Add : c </td><td>e</td><td>v : s</td><td>c</td><td>e</td><td>v + v : s</td>
|
<td>Dup : c</td><td>e</td><td>v : s</td><td>c</td><td>e</td><td>v : v : s</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Add : c </td><td>e</td><td>v : s</td><td>c</td><td>e</td><td>v + v : s</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -129,14 +133,14 @@ Reading this (or one of the previous lambda expressions) backwards you should be
|
||||||
|
|
||||||
This can now directly be translated into a list of instructions for the Haskell machine implementation.
|
This can now directly be translated into a list of instructions for the Haskell machine implementation.
|
||||||
|
|
||||||
```
|
```haskell
|
||||||
[ Const 0, Closure 1 4, Const 1, Local 0, Add, Ret, Dup
|
[ Const 0, Closure 1 4, Const 1, Local 0, Add, Ret, Dup
|
||||||
, Closure 3 6, Local 0, Local 1, App, Local 2, App, Ret
|
, Closure 3 6, Local 0, Local 1, App, Local 2, App, Ret
|
||||||
, App, App, App]
|
, App, App, App]
|
||||||
```
|
```
|
||||||
|
|
||||||
Which can then be evaluated in order to yield the normalized expression.
|
Which can then be evaluated in order to yield the normalized expression.
|
||||||
```
|
```haskell
|
||||||
λ eval [] [ Const 0, Closure 1 4, Const 1, Local 0, Add, Ret, Dup
|
λ eval [] [ Const 0, Closure 1 4, Const 1, Local 0, Add, Ret, Dup
|
||||||
, Closure 3 6, Local 0, Local 1, App, Local 2, App, Ret
|
, Closure 3 6, Local 0, Local 1, App, Local 2, App, Ret
|
||||||
, App, App, App]
|
, App, App, App]
|
||||||
|
@ -154,7 +158,7 @@ In the future I plan to create a specification for an instruction set which allo
|
||||||
|
|
||||||
The implementation itself is trivial and is little more than a Haskell translation of the instruction table above. It's ugly, it doesn't do error handling and is little more than a demonstration piece.
|
The implementation itself is trivial and is little more than a Haskell translation of the instruction table above. It's ugly, it doesn't do error handling and is little more than a demonstration piece.
|
||||||
|
|
||||||
```
|
```haskell
|
||||||
module SECD where
|
module SECD where
|
||||||
|
|
||||||
data Inst
|
data Inst
|
||||||
|
@ -201,6 +205,8 @@ eval globals insts = go (SEC [] [] insts globals)
|
||||||
Add -> let (x1:x2:st) = stack in go (SEC (vadd x1 x2:st) env xs global)
|
Add -> let (x1:x2:st) = stack in go (SEC (vadd x1 x2:st) env xs global)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
{% endkatexmm %}
|
||||||
|
|
||||||
## Licensing Information
|
## Licensing Information
|
||||||
|
|
||||||
Feel free to use any of the code or concepts here in your own projects! The code can be considered free of copyright and all notions of liability and/or warranty.
|
Feel free to use any of the code or concepts here in your own projects! The code can be considered free of copyright and all notions of liability and/or warranty.
|
||||||
|
|
|
@ -76,10 +76,18 @@ pre code {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
p, li {
|
p, li, th, td {
|
||||||
color: $text;
|
color: $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.bigger {
|
.bigger {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user