aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCamil Staps2017-11-21 23:11:06 +0100
committerCamil Staps2017-11-21 23:11:06 +0100
commit6e6170cbccf35dc184183e061b723f66951b17fe (patch)
treee72ab88e1d444ed7086e3f35fc98ee2b3eae830b
Initial commit
-rw-r--r--.gitignore2
-rw-r--r--Makefile15
-rw-r--r--README.md11
-rw-r--r--pf.icl86
4 files changed, 114 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0a2d380
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Clean System Files/
+pf
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8b2f87f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+BIN:=pf
+CLM:=clm
+CLMFLAGS:=-b -IL Platform -IL Generics
+
+.PHONY: all clean
+
+all: $(BIN)
+
+$(BIN): .FORCE
+ $(CLM) $(CLMFLAGS) $@ -o $@
+
+clean:
+ $(RM) -r 'Clean System Files' $(BIN)
+
+.FORCE:
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bb7b0c4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,11 @@
+# pf
+
+The aim of this project is to transform arbitrary [Clean][] function
+expressions to [point-free][hswiki] versions.
+See that link for similar projects for [Haskell][].
+This project is inspired by those projects, but does not aim to rewrite Haskell
+code.
+
+[Clean]: http://clean.cs.ru.nl
+[Haskell]: https://haskell.org
+[hswiki]: https://wiki.haskell.org/Pointfree
diff --git a/pf.icl b/pf.icl
new file mode 100644
index 0000000..c2e0ccb
--- /dev/null
+++ b/pf.icl
@@ -0,0 +1,86 @@
+module pf
+
+import StdEnv
+import Data.List
+
+:: Expr
+ = Lambda Ident Expr
+ | Ident Ident
+ | Literal Literal
+ | App Expr Expr
+
+:: Literal
+ = LitInt Int
+ | LitBool Bool
+
+:: Ident :== String
+
+hasIdent :: Ident Expr -> Bool
+hasIdent id (Ident n) = id == n
+hasIdent id (Literal _) = False
+hasIdent id (Lambda n e) = id <> n && hasIdent id e
+hasIdent id (App f x) = hasIdent id f || hasIdent id x
+
+print :: Expr -> String
+print e = foldl (+++) "" (pr False e [])
+where
+ pr :: Bool Expr [String] -> [String]
+ pr p l=:(Lambda _ _) st =
+ [if p "(\\" "\\":intersperse " " vars] ++
+ [" -> ":pr False rhs [if p ")" "":st]]
+ where
+ (vars,rhs) = getLambdas l
+
+ getLambdas :: Expr -> ([Ident], Expr)
+ getLambdas (Lambda x rhs) = let (is,e) = getLambdas rhs in ([x:is],e)
+ getLambdas e = ([], e)
+
+ pr _ (Ident id) st = [id:st]
+ pr _ (Literal l) st = pLit l st
+ pr p (App f x) st = [if p "(" "":pr False f [" ":pr True x [if p ")" "":st]]]
+
+ pLit :: Literal [String] -> [String]
+ pLit (LitInt i) st = [toString i:st]
+ pLit (LitBool b) st = [toString b:st]
+
+optim :: Expr -> Expr
+optim (Lambda id e)
+| hasIdent id e = case optim e of
+ Ident id` -> if (id == id`) (Ident "id") (App (Ident "const") e)
+ App f x -> case moveOutside id (App f x) of
+ a=:(App f (Ident id`)) -> if (id == id`) f (App (Ident "const") a)
+ a -> App (Ident "const") a
+ e -> Lambda id e
+| otherwise = App (Ident "const") (optim e)
+optim e = e
+
+moveOutside :: Ident Expr -> Expr
+moveOutside _ (Ident id) = Ident id
+moveOutside _ (Literal l) = Literal l
+moveOutside id (App f x)
+| hasIdent id f = case moveOutside id f of
+ Ident id -> App (App (App (Ident "flip") (Ident "id")) x) (Ident id)
+ App g (Ident id) -> App (App (App (Ident "flip") g) x) (Ident id)
+| hasIdent id x = case moveOutside id x of
+ e=:(Ident id) -> App f e
+ App g e=:(Ident id) -> App (App (App (Ident "(o)") f) g) e
+moveOutside _ (Lambda x e) = Lambda x e // TODO
+
+Start = map do
+ [ Lambda "x" (Literal (LitInt 5))
+ , Lambda "x" (Ident "x")
+ , Lambda "x" (Ident "y")
+ , Lambda "x" (Lambda "y" (Ident "x"))
+ , Lambda "x" (Lambda "y" (Ident "y"))
+ , Lambda "x" (Lambda "y" (Literal (LitInt 37)))
+ , Lambda "x" (Lambda "y" (Lambda "z" (Ident "x")))
+ , Lambda "x" (Lambda "y" (Lambda "z" (Ident "y")))
+ , Lambda "x" (Lambda "y" (Lambda "z" (Ident "z")))
+ , Lambda "x" (Lambda "y" (Lambda "z" (Literal (LitInt 37))))
+ , Lambda "x" (Lambda "y" (App (Ident "x") (Ident "y")))
+ , Lambda "x" (Lambda "y" (App (Ident "y") (Ident "x")))
+ , Lambda "x" (Lambda "y" (App (Ident "y") (Literal (LitInt 10))))
+ , Lambda "f" (Lambda "a" (Lambda "b" (Lambda "c" (Lambda "d" (App (App (App (App (Ident "f") (Ident "b")) (Ident "c")) (Ident "d")) (Ident "a"))))))
+ ]
+where
+ do e = (print e, " ==> ", print (optim e), "\n")