Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added inner lambdas (\x : Type . e) and a lambda lifter

  • Loading branch information...
commit fd64d9e99e4f3f3bc2d180e16ac1a07d5ff0036f 1 parent d1e4656
Edwin Brady authored
View
31 Epic/Epic.lhs
@@ -156,18 +156,18 @@ Remaining expression constructs
> (<$>) nm args = apply_ (R (UN nm)) args
-> data EpicTm = forall e. Epic e => Epic e
-> | Extern Name Type [Type]
-> | Include String
-> | Link String
-> | CType String
+> data EpicDecl = forall e. Epic e => Epic e
+> | Extern Name Type [Type]
+> | Include String
+> | Link String
+> | CType String
-> type Program = [(Name, EpicTm)]
+> type Program = [(Name, EpicDecl)]
> name :: String -> Name
> name = UN
-> mkDecl :: (Name, EpicTm) -> Decl
+> mkDecl :: (Name, EpicDecl) -> Decl
> mkDecl (n, Epic e) = Decl n TyAny (mkFunc e) Nothing []
> mkDecl (n, Epic.Epic.Extern nm ty tys) = Epic.Language.Extern nm ty tys
> mkDecl (n, Epic.Epic.Include f) = Epic.Language.Include f
@@ -182,7 +182,8 @@ Remaining expression constructs
> compileObj :: Program -> FilePath -> IO ()
> compileObj tms outf = compileDecls outf Nothing (map mkDecl tms) []
-> -- |Link a collection of object files
+> -- |Link a collection of object files. By convention, the entry point is
+> -- the function called "main".
> link :: [FilePath] -> FilePath -> IO ()
> link fs outf = Epic.Compiler.link fs [] outf True []
@@ -193,3 +194,17 @@ Remaining expression constructs
> system tmpn
> return ()
+Some useful functions
+
+> putStr_ x = foreign_ tyUnit "putStr" [(x, tyString)]
+> putStrLn_ x = "putStr" <$> ["append" <$> [x, str "\n"]]
+
+> readStr_ = foreign_ tyString "readStr" []
+
+> append_ x y = foreign_ tyString "append" [(x, tyString), (y, tyString)]
+
+> -- |Some default definitions: putStr, putStrLn, readStr, append
+> basic_defs = [(name "putStr", Epic putStr_),
+> (name "putStrLn", Epic putStrLn_),
+> (name "readStr", Epic readStr_),
+> (name "append", Epic append_)]
View
1  Epic/Language.lhs
@@ -106,6 +106,7 @@ Get the arity of a definition in the context
> | WhileAcc Expr Expr Expr
> | Op Op Expr Expr -- Infix operator
> | Let Name Type Expr Expr -- Let binding
+> | Lam Name Type Expr -- inner lambda
> | Error String -- Exit with error message
> | Impossible -- Claimed impossible to reach code
> | WithMem Allocator Expr Expr -- evaluate with manual allocation
View
4 Epic/Lexer.lhs
@@ -121,6 +121,8 @@
> | TokenSemi
> | TokenComma
> | TokenBar
+> | TokenLam
+> | TokenDot
> | TokenExtern
> | TokenMemory
> | TokenFixed
@@ -175,6 +177,8 @@
> lexer cont (';':cs) = cont TokenSemi cs
> lexer cont (',':cs) = cont TokenComma cs
> lexer cont ('|':cs) = cont TokenBar cs
+> lexer cont ('.':cs) = cont TokenDot cs
+> lexer cont ('\\':cs) = cont TokenLam cs
> lexer cont ('%':cs) = lexSpecial cont cs
> lexer cont (c:cs) = lexError c cs
View
5 Epic/Parser.y
@@ -93,8 +93,10 @@ import Epic.Lexer
';' { TokenSemi }
',' { TokenComma }
'|' { TokenBar }
+ '.' { TokenDot }
+ '\\' { TokenLam }
arrow { TokenArrow }
- cinclude { TokenCInclude }
+ cinclude { TokenCInclude }
extern { TokenExtern }
export { TokenExport }
ctype { TokenCType }
@@ -180,6 +182,7 @@ Expr : name { R $1 }
| Const { Const $1 }
| Expr '!' int { Proj $1 $3 }
| let name ':' Type '=' Expr in Expr %prec LET { Let $2 $4 $6 $8 }
+ | '\\' name ':' Type '.' Expr %prec LET { Lam $2 $4 $6 }
| Expr ';' Expr { Let (MN "unused" 0) TyUnit $1 $3 }
| if Expr then Expr else Expr %prec IF { If $2 $4 $6 }
| while '(' Expr ',' Expr ')' { While $3 $5 }
View
21 Epic/Scopecheck.lhs
@@ -30,10 +30,13 @@ checking we do (for now).
> (nm,(args, rt)):(mkContext xs)
> mkContext (_:xs) = mkContext xs
-Check all names are in scope in a function, and convert global references (R) to local names
-(V). Also, if any lazy expressions are not already applications, lift them out and make
-a new function. Returns the modified function, and a list of new declarations. The new
-declarations will *not* have been scopechecked.
+Check all names are in scope in a function, and convert global
+references (R) to local names (V). Also, if any lazy expressions are
+not already applications, lift them out and make a new
+function. Returns the modified function, and a list of new
+declarations. The new declarations will *not* have been scopechecked.
+
+Do Lambda Lifting here too
> scopecheck :: Monad m => Int -> Context -> Name -> Func -> m (Func, [Decl])
> scopecheck checking ctxt nm (Bind args locs exp fl) = do
@@ -93,6 +96,16 @@ Make a new function, with current env as arguments, and add as a decl
> put (maxlen, nextn+1, newd:decls)
> return $ Lazy (App (R newname) (map V (map snd env)))
+> tc env (Lam n ty e) = lift e [(n,ty)] where
+> lift (Lam n ty e) args = lift e ((n,ty):args)
+> lift e args = do (maxlen, nextn, decls) <- get
+> let newname = MN (getRoot nm) nextn
+> let newargs = zip (map fst env) (repeat TyAny)
+> ++ reverse args
+> let newfn = Bind newargs 0 e []
+> let newd = Decl newname TyAny newfn Nothing []
+> put (maxlen, nextn+1, newd:decls)
+> return $ App (R newname) (map V (map snd env))
> tc env (Effect e) = do
> e' <- tc env e
> return $ Effect e'
View
14 examples/listy.e
@@ -1,6 +1,18 @@
include "Prelude.e"
-main () -> Unit = printList(take(3,ones))
+main () -> Unit = printList(maintake(10,4))
+
+maintake (x:Int, y:Int) -> Data
+ = zip ( \a : Any . \b : Any . y+a*2+b , take(x, ones()), take(x, testList()))
+
+zip (f:Any, xs:Data, ys:Data) -> Data
+ = case xs of {
+ Con 0 () -> Con 0 ()
+ | Con 1 (x:Data, xs0:Data) -> case ys of {
+ Con 0 () -> Con 0 ()
+ | Con 1 (y:Data, ys0:Data) -> Con 1 (f(x,y), zip(f, xs0, ys0))
+ }
+ }
take (i:Int, x:Data) -> Data
= if (i==0) then Con 0 () else
View
2  tests/expected
@@ -4,6 +4,6 @@
6689502913449127057588118054090372586752746333138029810295671352301633557244962989366874165271984981308157637893214090552534408589408121859898481114389650005964960521256960000000000000000000000000000
Hello world!
362880
-1, 1, 1, nil
+7, 8, 9, 10, 11, nil
40320
40320
View
14 tests/listy.e
@@ -1,6 +1,18 @@
include "Prelude.e"
-main () -> Unit = printList(%memory(%fixed, 100000, take(3,ones)))
+main () -> Unit = printList(maintake(10,4))
+
+maintake (x:Int, y:Int) -> Data
+ = zip ( \a : Any . \b : Any . y+a*2+b , take(x, ones()), take(x, testList()))
+
+zip (f:Any, xs:Data, ys:Data) -> Data
+ = case xs of {
+ Con 0 () -> Con 0 ()
+ | Con 1 (x:Data, xs0:Data) -> case ys of {
+ Con 0 () -> Con 0 ()
+ | Con 1 (y:Data, ys0:Data) -> Con 1 (f(x,y), zip(f, xs0, ys0))
+ }
+ }
take (i:Int, x:Data) -> Data
= if (i==0) then Con 0 () else
Please sign in to comment.
Something went wrong with that request. Please try again.