Skip to content

Commit

Permalink
Added swap, dip, i, nullary, step, fold, concat. Also added aspiratio…
Browse files Browse the repository at this point in the history
…ns to the README
  • Loading branch information
stevej committed Oct 5, 2012
1 parent c15f32e commit 4d245e3
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 13 deletions.
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,34 @@
[![Build Status](https://secure.travis-ci.org/stevej/stackist.png?branch=master)](http://travis-ci.org/stevej/stackist)

`stackist` is a series of experiments in building a stack-based
programming language.
programming language, starting with Manfred von Thun's Joy language.

What we have today:
What I have today:
* A basic interpreter for an arithmetic language.
* Literals
* Operators
* A basic stdandard library
* Quotations
* Most of the base combinators


What I'm working on next:
* Aggregates
* All combinators (primrec, linrec, binrec, fold, ifte)
* Critical: verify that my stack semantics agree with von Thun's.
* More stdlib (working down this list: http://www.latrobe.edu.au/phimvt/joy/html-manual.html)
* Named functions
* I/O
* stack operators (newstack, clear, stack, cons, swons, uncons, unswons)
* better interpretor error handling

Future directions:
* Documenting a type system for Joy
* Can we encode Joy with a fragment of System F? (rank-2?)
* Type reconstructor applicable to all original Joy programs
* Retargetable compiler
* Compile to C
* Compile to LLVM IR
* Compile to Native code
* Applying Linear types to Joy
* Linear type reconstruction
90 changes: 79 additions & 11 deletions src/Stackist/Interpreter1.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ import Text.Show.Functions

data Expr = Numeric Integer
| Literal String
| Quote Expr
| JString String -- is "quoted"
| Quote [Expr]
deriving (Show, Eq)


-- Ladies and Gentlemen, the standard library
-- All functions are typed: [Expr] -> [Expr]

-- | i : [P] -> ... Executes P. So, [P] i == P.
--
-- >> redex [] [JString "a", JString "b", Quote [Literal "concat"], Literal "i"]
-- [JString "ab"]
_i (Quote q : xs) = redex xs q

-- | Adds two numbers on bottom of the stack
--
-- >>> redex [] [Numeric 1, Numeric 2, Literal "+"]
-- >> redex [] [Numeric 1, Numeric 2, Literal "+"]
-- [Numeric 3]
_add (Numeric m : Numeric n : xs) = Numeric (m + n) : xs

Expand All @@ -27,7 +33,7 @@ _add (Numeric m : Numeric n : xs) = Numeric (m + n) : xs
-- [Numeric 2]
_subtract (Numeric m : Numeric n : xs) = Numeric (n - m) : xs

-- | Multiples the bottom two numbers on the stack together
-- | Multiplies the bottom two numbers on the stack together
--
-- >>> redex [] [Numeric 2, Numeric 3, Literal "*"]
-- [Numeric 6]
Expand All @@ -48,36 +54,98 @@ _dup (m : xs) = m : m : xs
-- | Swaps the two top items on the stack
--
-- >>> redex [] [Numeric 3, Numeric 2, Literal "swap"]
-- [Numeric 2,Numeric 3]
_swap (m : n : xs) = m : n : xs -- note they're already in reverse order
-- [Numeric 3,Numeric 2]
_swap (m : n : xs) = n : m : xs

-- | dip : X [P] -> ... X
-- Saves X, executes P, pushes X back.
--
-- >> redex [] [Numeric 1, Quote [Numeric 2, Numeric 2, Literal "+"], Literal "dip"]
-- [Numeric 4, Numeric 1]
_dip (m : Quote q : xs) = r ++ (m : xs)
where r = _i (Quote q : xs)

-- | [P] -> R Executes P, which leaves R on top of the stack. No matter
-- how many parameters this consumes, none are removed from the stack.
--
-- >>> redex [] [Quote [Numeric 1, Numeric 2, Literal "+"], Literal "nullary"]
-- [Numeric 3]
_nullary (Quote q : xs) = (redex [] q) ++ xs
-- how to keep the rest of the stack from being affected?

-- | S T -> U Sequence U is the concatenation of sequences S and T.
--
-- >> redex [] [JString "a", JString "b", Literal "concat"]
-- [JString "ab"]
_concat (JString s : JString t : xs) = JString (s ++ t) : xs

-- | fold : A V0 [P] -> V Starting with value V0, sequentially pushes
-- members of aggregate A and combines with binary operator P to produce value V.
-- (SJ: I assumed this would be a foldRight but is left)
-- List("b", "c", "d").foldLeft("a")((a,b) => a + b)
-- res1: java.lang.String = abcd
--
-- >> redex [] [Quote [JString "b", JString "c", JString "d"], JString "a", Quote [Literal "concat"], Literal "fold"]
-- [JString "abcd"]
_fold = _swapd . _step


-- | swapd : X Y Z -> Y X Z
-- As if defined by: swapd == [swap] dip
--
-- >> redex [] [Literal "x", Literal "y", Literal "z", Literal "swapd"]
-- [Literal "z", Literal "x", Literal "y"]
_swapd (z : y : x : xs) = z : x : y : xs


-- | step : A [P] -> ...
-- Sequentially putting members of aggregate A onto stack, executes
-- P for each member of A.
--
-- >> redex [] [Quote [Numeric 1, Numeric 2], Quote [Numeric 2, Literal "*"], Literal "step"]
-- [Numeric 4, Numeric 1]
_step (Quote qs : Quote f : xs) = (concat (map f' qs)) ++ xs
where f' q = redex [q] f

preludeMap :: Map.Map String ([Expr] -> [Expr])
preludeMap = Map.fromList
[("+", _add),
("-", _subtract),
("*", _multiply),
("/", _divide),
("dup", _dup),
("swap", _swap)
("swap", _swap),
("nullary", _nullary),
("concat", _concat),
("fold", _fold),
("dip", _dip),
("i", _i),
("swapd", _swapd),
("step", _step)
]

-- If the user is looking for a function we don't have, throw an error.
preludeLookup s = Map.findWithDefault (\_ -> error ("function not found in library: " ++ s)) s preludeMap

-- the first [Expr] is the work-in-progress stack, which will be in reverse order
-- from the program list to faciliate pattern matching on the head.
-- the first [Expr] is the data stack, which will be in reverse order
-- from the program list to faciliate pattern matching on the head. The second [Expr] is
-- what we haven't processed yet.
redex :: [Expr] -> [Expr] -> [Expr]
-- | we're out of commands to run, we've finished reducing the stack.
-- | we're out of commands to run, we've finished reducing the program stack.
--
-- >>> redex [] []
-- []
redex stack [] = stack
-- | push a quotation onto the stack
--
-- >>> redex [] [Quote [Literal 1]]
-- [Quote [Literal 1]]
redex stack (q @ (Quote _) : xs) = redex (q : stack) xs
-- | push a number onto stack.
--
-- >>> redex [] [Numeric 1]
-- [Numeric 1]
redex stack (n @ (Numeric m) : xs) = redex (n : stack) xs
redex stack (n @ (Numeric _) : xs) = redex (n : stack) xs
-- | Lookup the function named s, and run it against the stack.
redex stack (Literal f : xs) = redex result xs
where result = preludeLookup f stack

0 comments on commit 4d245e3

Please sign in to comment.