codegen improvements
This commit is contained in:
@@ -46,5 +46,12 @@ not = \ v => case v of
|
|||||||
True => False
|
True => False
|
||||||
False => True
|
False => True
|
||||||
|
|
||||||
|
|
||||||
|
not2 : Bool -> Bool
|
||||||
|
not2 = \ v => case v of
|
||||||
|
True => False
|
||||||
|
x => True
|
||||||
|
|
||||||
|
|
||||||
data Void : U where
|
data Void : U where
|
||||||
|
|
||||||
|
|||||||
@@ -176,6 +176,11 @@ checkAlt scty ctx ty (MkAlt ptm body) = do
|
|||||||
(con, args) <- getArgs ptm []
|
(con, args) <- getArgs ptm []
|
||||||
debug "ALT con \{con} args \{show args}"
|
debug "ALT con \{con} args \{show args}"
|
||||||
let Just (MkEntry _ dcty (DCon arity _)) = lookup con !(get)
|
let Just (MkEntry _ dcty (DCon arity _)) = lookup con !(get)
|
||||||
|
| Nothing => do
|
||||||
|
-- check body with con bound at scty against ty
|
||||||
|
let ctx' = extend ctx con scty
|
||||||
|
body' <- check ctx' body ty
|
||||||
|
pure $ CaseDefault body'
|
||||||
| _ => error emptyFC "expected datacon, got \{con}"
|
| _ => error emptyFC "expected datacon, got \{con}"
|
||||||
|
|
||||||
-- arity is wrong, but we actually need the type anyway
|
-- arity is wrong, but we actually need the type anyway
|
||||||
@@ -218,7 +223,8 @@ checkAlt scty ctx ty (MkAlt ptm body) = do
|
|||||||
let var = VVar emptyFC (length ctx.env) [<]
|
let var = VVar emptyFC (length ctx.env) [<]
|
||||||
let ctx' = extend ctx nm a
|
let ctx' = extend ctx nm a
|
||||||
Lam emptyFC nm <$> go !(b $$ var) rest ctx'
|
Lam emptyFC nm <$> go !(b $$ var) rest ctx'
|
||||||
go (VPi fc str Implicit a b) args ctx = do
|
|
||||||
|
go (VPi _ str Implicit a b) args ctx = do
|
||||||
debug "*** insert \{str}"
|
debug "*** insert \{str}"
|
||||||
let fc' = argsFC args
|
let fc' = argsFC args
|
||||||
let var = VVar fc' (length ctx.env) [<]
|
let var = VVar fc' (length ctx.env) [<]
|
||||||
@@ -226,7 +232,7 @@ checkAlt scty ctx ty (MkAlt ptm body) = do
|
|||||||
Lam fc' "_" <$> go !(b $$ var) args ctx'
|
Lam fc' "_" <$> go !(b $$ var) args ctx'
|
||||||
-- same deal with _ for name
|
-- same deal with _ for name
|
||||||
go (VPi fc str Explicit a b) ((fc', Implicit, nm) :: rest) ctx = do
|
go (VPi fc str Explicit a b) ((fc', Implicit, nm) :: rest) ctx = do
|
||||||
error fc' "Implicit/Explicit mismatch \{show str} \{show nm}"
|
error fc' "Implicit/Explicit mismatch \{show str} at \{show nm}"
|
||||||
go (VPi fc str icit x y) [] ctx = error emptyFC "Not enough arguments"
|
go (VPi fc str icit x y) [] ctx = error emptyFC "Not enough arguments"
|
||||||
|
|
||||||
-- nameless variable
|
-- nameless variable
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
-- TODO fresh names
|
||||||
|
|
||||||
module Lib.Compile
|
module Lib.Compile
|
||||||
|
|
||||||
import Lib.Types
|
import Lib.Types
|
||||||
@@ -9,6 +11,10 @@ data Kind = Plain | Return | Assign String
|
|||||||
|
|
||||||
data JSStmt : Kind -> Type
|
data JSStmt : Kind -> Type
|
||||||
|
|
||||||
|
data JAlt : Type where
|
||||||
|
JConAlt : String -> JSStmt e -> JAlt
|
||||||
|
JDefAlt : JSStmt e -> JAlt
|
||||||
|
|
||||||
data JSExp : Type where
|
data JSExp : Type where
|
||||||
LitArray : List JSExp -> JSExp
|
LitArray : List JSExp -> JSExp
|
||||||
LitObject : List (String, JSExp) -> JSExp
|
LitObject : List (String, JSExp) -> JSExp
|
||||||
@@ -28,7 +34,8 @@ data JSStmt : Kind -> Type where
|
|||||||
JReturn : JSExp -> JSStmt Return
|
JReturn : JSExp -> JSStmt Return
|
||||||
-- JAssign : (nm : String) -> JSExp -> JSStmt (Assign nm)
|
-- JAssign : (nm : String) -> JSExp -> JSStmt (Assign nm)
|
||||||
-- TODO - switch to Nat tags
|
-- TODO - switch to Nat tags
|
||||||
JCase : JSExp -> List (String, JSStmt a) -> Maybe (JSStmt a) -> JSStmt a
|
-- FIXME add e to JAlt (or just drop it?)
|
||||||
|
JCase : JSExp -> List JAlt -> JSStmt a
|
||||||
-- throw can't be used
|
-- throw can't be used
|
||||||
JError : String -> JSStmt a
|
JError : String -> JSStmt a
|
||||||
|
|
||||||
@@ -70,22 +77,26 @@ termToJS env (CApp t args) f = termToJS env t (\ t' => argsToJS args [<] (\ args
|
|||||||
argsToJS (x :: xs) acc k = termToJS env x (\ x' => argsToJS xs (acc :< x') k)
|
argsToJS (x :: xs) acc k = termToJS env x (\ x' => argsToJS xs (acc :< x') k)
|
||||||
|
|
||||||
|
|
||||||
termToJS env (CCase t alts def) f =
|
termToJS env (CCase t alts) f =
|
||||||
-- need to assign the scrutinee to a variable (unless it is a var already?)
|
-- need to assign the scrutinee to a variable (unless it is a var already?)
|
||||||
-- and add (Bnd -> JSExpr map)
|
-- and add (Bnd -> JSExpr map)
|
||||||
-- TODO default case, let's drop the extra field.
|
-- TODO default case, let's drop the extra field.
|
||||||
|
|
||||||
termToJS env t $ \case
|
termToJS env t $ \case
|
||||||
(Var nm) => (JCase (Dot (Var nm) "tag") (map (termToJSAlt nm) alts) Nothing)
|
(Var nm) => (JCase (Dot (Var nm) "tag") (map (termToJSAlt nm) alts))
|
||||||
t' =>
|
t' =>
|
||||||
let nm = "sc$\{show $ length env}" in
|
let nm = "sc$\{show $ length env}" in
|
||||||
JSnoc (JConst nm t')
|
JSnoc (JConst nm t')
|
||||||
(JCase (Dot (Var nm) "tag") (map (termToJSAlt nm) alts) Nothing)
|
(JCase (Dot (Var nm) "tag") (map (termToJSAlt nm) alts))
|
||||||
where
|
where
|
||||||
termToJSAlt : String -> CAlt -> (String, JSStmt e)
|
termToJSAlt : String -> CAlt -> JAlt
|
||||||
termToJSAlt nm (CConAlt name args u) =
|
termToJSAlt nm (CConAlt name args u) = JConAlt name (termToJS (mkEnv nm 0 env args) u f)
|
||||||
let env' = mkEnv nm 0 env args in
|
-- intentially reusing scrutinee name here
|
||||||
(name, termToJS env' u f)
|
termToJSAlt nm (CDefAlt u) = JDefAlt (termToJS (Var nm :: env) u f)
|
||||||
|
label : JSExp -> (String -> JSStmt e) -> JSStmt e
|
||||||
|
label (Var nm) f = f nm
|
||||||
|
label t f = ?label_rhs
|
||||||
|
|
||||||
|
|
||||||
-- FIXME escape
|
-- FIXME escape
|
||||||
jsString : String -> Doc
|
jsString : String -> Doc
|
||||||
@@ -110,25 +121,22 @@ expToDoc JUndefined = text "undefined"
|
|||||||
expToDoc (Index obj ix) = expToDoc obj ++ "[" ++ expToDoc ix ++ "]"
|
expToDoc (Index obj ix) = expToDoc obj ++ "[" ++ expToDoc ix ++ "]"
|
||||||
expToDoc (Dot obj nm) = expToDoc obj ++ "." ++ text nm
|
expToDoc (Dot obj nm) = expToDoc obj ++ "." ++ text nm
|
||||||
|
|
||||||
altToDoc : (String, JSStmt e) -> Doc
|
caseBody : JSStmt e -> Doc
|
||||||
-- line is an extra newline, but nest seems borken
|
caseBody stmt@(JReturn x) = nest 2 (line ++ stmtToDoc stmt)
|
||||||
altToDoc (nm, (JReturn exp)) = text "case" <+> jsString nm ++ ":" </> nest 2 (line ++ "return" <+> expToDoc exp)
|
caseBody stmt = nest 2 (line ++ stmtToDoc stmt </> text "break;")
|
||||||
altToDoc (nm, stmt) = text "case" <+> jsString nm ++ ":" </> nest 2 (line ++ stmtToDoc stmt </> text "break;")
|
|
||||||
|
altToDoc : JAlt -> Doc
|
||||||
|
altToDoc (JConAlt nm stmt) = text "case" <+> jsString nm ++ ":" ++ caseBody stmt
|
||||||
|
altToDoc (JDefAlt stmt) = text "default" ++ ":" ++ caseBody stmt
|
||||||
|
|
||||||
stmtToDoc (JSnoc x y) = stmtToDoc x </> stmtToDoc y
|
stmtToDoc (JSnoc x y) = stmtToDoc x </> stmtToDoc y
|
||||||
stmtToDoc (JPlain x) = expToDoc x
|
stmtToDoc (JPlain x) = expToDoc x ++ ";"
|
||||||
stmtToDoc (JConst nm x) = text "const" <+> text nm <+> "=" <+/> expToDoc x
|
stmtToDoc (JConst nm x) = text "const" <+> text nm <+> "=" <+/> expToDoc x ++ ";"
|
||||||
stmtToDoc (JReturn x) = text "return" <+> expToDoc x
|
stmtToDoc (JReturn x) = text "return" <+> expToDoc x ++ ";"
|
||||||
stmtToDoc (JError str) = text "throw new Error(" ++ text str ++ ")"
|
stmtToDoc (JError str) = text "throw new Error(" ++ text str ++ ");"
|
||||||
stmtToDoc (JCase sc alts y) =
|
stmtToDoc (JCase sc alts) =
|
||||||
text "switch (" ++ expToDoc sc ++ ")" <+> bracket "{" (stack $ map altToDoc alts) "}"
|
text "switch (" ++ expToDoc sc ++ ")" <+> bracket "{" (stack $ map altToDoc alts) "}"
|
||||||
|
|
||||||
-- FIXME - if the result is JSnoc, we get extra top level code
|
|
||||||
-- If we make top level 0-arity values lazy, this won't happen
|
|
||||||
-- function : String -> Tm -> Doc
|
|
||||||
-- function nm tm = stmtToDoc $ termToJS [] tm (JConst nm)
|
|
||||||
|
|
||||||
|
|
||||||
mkArgs : Nat -> List String -> List String
|
mkArgs : Nat -> List String -> List String
|
||||||
mkArgs Z acc = acc
|
mkArgs Z acc = acc
|
||||||
mkArgs (S k) acc = mkArgs k ("h\{show k}" :: acc)
|
mkArgs (S k) acc = mkArgs k ("h\{show k}" :: acc)
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ data CExp : Type
|
|||||||
public export
|
public export
|
||||||
data CAlt : Type where
|
data CAlt : Type where
|
||||||
CConAlt : String -> List String -> CExp -> CAlt
|
CConAlt : String -> List String -> CExp -> CAlt
|
||||||
|
-- REVIEW keep var name?
|
||||||
|
CDefAlt : CExp -> CAlt
|
||||||
-- literal
|
-- literal
|
||||||
|
|
||||||
data CExp : Type where
|
data CExp : Type where
|
||||||
@@ -25,7 +27,7 @@ data CExp : Type where
|
|||||||
CApp : CExp -> List CExp -> CExp
|
CApp : CExp -> List CExp -> CExp
|
||||||
-- TODO make DCon/TCon app separate so we can specialize
|
-- TODO make DCon/TCon app separate so we can specialize
|
||||||
-- U / Pi are compiled to type constructors
|
-- U / Pi are compiled to type constructors
|
||||||
CCase : CExp -> List CAlt -> Maybe CExp -> CExp
|
CCase : CExp -> List CAlt -> CExp
|
||||||
CRef : Name -> CExp
|
CRef : Name -> CExp
|
||||||
CMeta : Nat -> CExp
|
CMeta : Nat -> CExp
|
||||||
|
|
||||||
@@ -100,16 +102,10 @@ compileTerm (U _) = pure $ CRef "U"
|
|||||||
compileTerm (Pi _ nm icit t u) = pure $ CApp (CRef "PiType") [ !(compileTerm t), CLam nm !(compileTerm u)]
|
compileTerm (Pi _ nm icit t u) = pure $ CApp (CRef "PiType") [ !(compileTerm t), CLam nm !(compileTerm u)]
|
||||||
compileTerm (Case _ t alts) = do
|
compileTerm (Case _ t alts) = do
|
||||||
t' <- compileTerm t
|
t' <- compileTerm t
|
||||||
alts' <- catMaybes <$> traverse (\case
|
alts' <- traverse (\case
|
||||||
CaseDefault tm => pure Nothing
|
CaseDefault tm => pure $ CDefAlt !(compileTerm tm)
|
||||||
CaseCons nm args tm => pure $ Just $ CConAlt nm args !(compileTerm tm)) alts
|
CaseCons nm args tm => pure $ CConAlt nm args !(compileTerm tm)) alts
|
||||||
def <- getDefault alts
|
pure $ CCase t' alts'
|
||||||
pure $ CCase t' alts' def
|
|
||||||
where
|
|
||||||
getDefault : List CaseAlt -> M (Maybe CExp)
|
|
||||||
getDefault [] = pure Nothing
|
|
||||||
getDefault (CaseDefault u :: _) = Just <$> compileTerm u
|
|
||||||
getDefault (_ :: xs) = getDefault xs
|
|
||||||
|
|
||||||
|
|
||||||
export
|
export
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ Pretty Tm where
|
|||||||
pretty (App _ t u) = text "(" <+> pretty t <+> pretty u <+> ")"
|
pretty (App _ t u) = text "(" <+> pretty t <+> pretty u <+> ")"
|
||||||
pretty (U _) = "U"
|
pretty (U _) = "U"
|
||||||
pretty (Pi _ str icit t u) = text "(" <+> text str <+> ":" <+> pretty t <+> ")" <+> "=>" <+> pretty u <+> ")"
|
pretty (Pi _ str icit t u) = text "(" <+> text str <+> ":" <+> pretty t <+> ")" <+> "=>" <+> pretty u <+> ")"
|
||||||
pretty (Case _ _ _) = text "FIXME CASE"
|
pretty (Case _ _ _) = text "FIXME PRETTY CASE"
|
||||||
|
|
||||||
-- public export
|
-- public export
|
||||||
-- data Closure : Nat -> Type
|
-- data Closure : Nat -> Type
|
||||||
|
|||||||
Reference in New Issue
Block a user