compile data constructors (need to get arity in funcalls)

This commit is contained in:
2024-08-09 10:03:22 -07:00
parent 0058b6b724
commit c1c1cc0e0e
3 changed files with 40 additions and 17 deletions

View File

@@ -2,6 +2,7 @@ module Lib.Compile
import Lib.Types import Lib.Types
import Lib.Prettier import Lib.Prettier
import Data.String
-- return is in the wrong spot -- return is in the wrong spot
-- case is still FIXME -- case is still FIXME
@@ -18,14 +19,14 @@ data JSExp : Type where
LitString : String -> JSExp LitString : String -> JSExp
Apply : JSExp -> List JSExp -> JSExp Apply : JSExp -> List JSExp -> JSExp
Var : String -> JSExp Var : String -> JSExp
JLam : String -> JSStmt Return -> JSExp JLam : List String -> JSStmt Return -> JSExp
JUndefined : JSExp JUndefined : JSExp
Index : JSExp -> JSExp -> JSExp Index : JSExp -> JSExp -> JSExp
Dot : JSExp -> String -> JSExp Dot : JSExp -> String -> JSExp
data JSStmt : Kind -> Type where data JSStmt : Kind -> Type where
-- Maybe make this a snoc... -- Maybe make this a snoc...
JSeq : JSStmt Plain -> JSStmt a -> JSStmt a JSnoc : JSStmt Plain -> JSStmt a -> JSStmt a
JPlain : JSExp -> JSStmt Plain JPlain : JSExp -> JSStmt Plain
JConst : (nm : String) -> JSExp -> JSStmt Plain JConst : (nm : String) -> JSExp -> JSStmt Plain
JReturn : JSExp -> JSStmt Return JReturn : JSExp -> JSStmt Return
@@ -38,11 +39,11 @@ data JSStmt : Kind -> Type where
Cont e = JSExp -> JSStmt e Cont e = JSExp -> JSStmt e
-- This is inspired by A-normalization, look into the continuation monad -- This is inspired by A-normalization, look into the continuation monad
-- There is an index on JSStmt, adopted from Stefan's code. -- There is an index on JSStmt, adopted from Stefan Hoeck's code.
-- --
-- Here we turn a Term into a statement (which may be a sequence of statements), there -- Here we turn a Term into a statement (which may be a sequence of statements), there
-- is a continuation, which turns the final JSExpr into a JSStmt, and the function returns -- is a continuation, which turns the final JSExpr into a JSStmt, and the function returns
-- a JSStmt, possibly wrapping recursive calls with JSeq -- a JSStmt, wrapping recursive calls in JSnoc if necessary.
termToJS : List JSExp -> Tm -> Cont e -> JSStmt e termToJS : List JSExp -> Tm -> Cont e -> JSStmt e
termToJS env (Bnd _ k) f = case getAt k env of termToJS env (Bnd _ k) f = case getAt k env of
(Just e) => f e (Just e) => f e
@@ -52,7 +53,7 @@ termToJS env (Meta _ k) f = f $ LitString "META \{show k}"
termToJS env (Lam _ nm t) f = termToJS env (Lam _ nm t) f =
let nm' = "nm$\{show $ length env}" let nm' = "nm$\{show $ length env}"
env' = (Var nm' :: env) env' = (Var nm' :: env)
in f $ JLam nm' (termToJS env' t JReturn) in f $ JLam [nm'] (termToJS env' t JReturn)
termToJS env (App _ t u) f = termToJS env t (\ t' => termToJS env u (\ u' => f (Apply t' [u']))) termToJS env (App _ t u) f = termToJS env t (\ t' => termToJS env u (\ u' => f (Apply t' [u'])))
termToJS env (U _) f = f $ LitString "U" termToJS env (U _) f = f $ LitString "U"
termToJS env (Pi _ nm icit t u) f = f $ LitString "Pi \{nm}" termToJS env (Pi _ nm icit t u) f = f $ LitString "Pi \{nm}"
@@ -62,7 +63,7 @@ termToJS env (Case _ t alts) f =
termToJS env t (\ t' => termToJS env t (\ t' =>
let (l,c) = getFC t in let (l,c) = getFC t in
let nm = "sc$\{show l}$\{show c}" in let nm = "sc$\{show l}$\{show c}" in
JSeq (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) Nothing))
where where
-- Stuff nm.h1, nm.h2, ... into environment -- Stuff nm.h1, nm.h2, ... into environment
@@ -84,12 +85,17 @@ stmtToDoc : JSStmt e -> Doc
expToDoc : JSExp -> Doc expToDoc : JSExp -> Doc
expToDoc (LitArray xs) = ?expToDoc_rhs_0 expToDoc (LitArray xs) = ?expToDoc_rhs_0
expToDoc (LitObject xs) = ?expToDoc_rhs_1 expToDoc (LitObject xs) = text "{" <+> folddoc (\ a, e => a ++ ", " <+/> e) (map entry xs) <+> text "}"
where
entry : (String, JSExp) -> Doc
-- TODO quote if needed
entry (nm, exp) = text nm ++ ":" <+> expToDoc exp
expToDoc (LitString str) = jsString str expToDoc (LitString str) = jsString str
expToDoc (Apply x xs) = expToDoc x ++ "(" ++ spread (map expToDoc xs) ++ ")" expToDoc (Apply x xs) = expToDoc x ++ "(" ++ spread (map expToDoc xs) ++ ")"
expToDoc (Var nm) = text nm expToDoc (Var nm) = text nm
expToDoc (JLam nm (JReturn exp)) = text "(" <+> text nm <+> ") =>" <+> expToDoc exp expToDoc (JLam nms (JReturn exp)) = text "(" <+> text (joinBy ", " nms) <+> ") =>" <+> expToDoc exp
expToDoc (JLam nm body) = text "(" <+> text nm <+> ") =>" <+> bracket "{" (stmtToDoc body) "}" expToDoc (JLam nms body) = text "(" <+> text (joinBy ", " nms) <+> ") =>" <+> bracket "{" (stmtToDoc body) "}"
expToDoc JUndefined = text "undefined" 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
@@ -99,8 +105,7 @@ altToDoc : (String, JSStmt e) -> Doc
altToDoc (nm, (JReturn exp)) = text "case" <+> jsString nm ++ ":" </> nest 2 (line ++ "return" <+> expToDoc exp) altToDoc (nm, (JReturn exp)) = text "case" <+> jsString nm ++ ":" </> nest 2 (line ++ "return" <+> expToDoc exp)
altToDoc (nm, stmt) = text "case" <+> jsString nm ++ ":" </> nest 2 (line ++ stmtToDoc stmt </> text "break;") altToDoc (nm, stmt) = text "case" <+> jsString nm ++ ":" </> nest 2 (line ++ stmtToDoc stmt </> text "break;")
stmtToDoc (JSnoc x y) = stmtToDoc x </> stmtToDoc y
stmtToDoc (JSeq 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
@@ -108,10 +113,21 @@ stmtToDoc (JError str) = text "throw new Error(" ++ text str ++ ")"
stmtToDoc (JCase sc alts y) = stmtToDoc (JCase sc alts y) =
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 : String -> Tm -> Doc
function nm tm = function nm tm = stmtToDoc $ termToJS [] tm (JConst nm)
let body = stmtToDoc $ termToJS [] tm JReturn in
text "const" <+> text nm <+> "=" <+/> body dcon : String -> Nat -> Doc
dcon nm arity =
let args := mkArgs arity []
obj := ("tag", LitString nm) :: map (\x => (x, Var x)) args
in stmtToDoc $ JConst nm (JLam args (JReturn (LitObject obj)))
where
-- FIXME arity wrong
mkArgs : Nat -> List String -> List String
mkArgs Z acc = acc
mkArgs (S k) acc = mkArgs k ("h\{show k}" :: acc)
entryToDoc : TopEntry -> Maybe Doc entryToDoc : TopEntry -> Maybe Doc
entryToDoc (MkEntry name type (Fn tm)) = entryToDoc (MkEntry name type (Fn tm)) =
@@ -119,7 +135,7 @@ entryToDoc (MkEntry name type (Fn tm)) =
Just (text "const" <+> text name <+> "=" <+/> body) Just (text "const" <+> text name <+> "=" <+/> body)
entryToDoc (MkEntry name type Axiom) = Nothing entryToDoc (MkEntry name type Axiom) = Nothing
entryToDoc (MkEntry name type (TCon strs)) = Nothing entryToDoc (MkEntry name type (TCon strs)) = Nothing
entryToDoc (MkEntry name type (DCon k str)) = Nothing entryToDoc (MkEntry name type (DCon arity str)) = Just $ dcon name arity
export export
compile : M Doc compile : M Doc

View File

@@ -9,6 +9,12 @@ import Lib.TopContext
import Lib.Check import Lib.Check
import Lib.Syntax import Lib.Syntax
getArity : Tm -> Nat
getArity (Pi x str icit t u) = S (getArity u)
-- Ref or App (of type constructor) are valid
getArity _ = Z
export export
processDecl : Decl -> M () processDecl : Decl -> M ()
processDecl (TypeSig fc nm tm) = do processDecl (TypeSig fc nm tm) = do
@@ -77,7 +83,8 @@ processDecl (Data fc nm ty cons) = do
-- TODO check pi type ending in full tyty application -- TODO check pi type ending in full tyty application
-- TODO count arity -- TODO count arity
dty <- check (mkCtx ctx.metas) tm (VU fc) dty <- check (mkCtx ctx.metas) tm (VU fc)
modify $ defcon nm' 0 nm dty debug "dty \{nm'} is \{pprint [] dty}"
modify $ defcon nm' (getArity dty) nm dty
pure nm' pure nm'
_ => throwError $ E (0,0) "expected constructor declaration" _ => throwError $ E (0,0) "expected constructor declaration"
-- TODO check tm is VU or Pi ending in VU -- TODO check tm is VU or Pi ending in VU

View File

@@ -50,7 +50,7 @@ dumpContext top = do
dumpSource : M () dumpSource : M ()
dumpSource = do dumpSource = do
doc <- compile doc <- compile
putStrLn $ render 80 doc putStrLn $ render 90 doc
processFile : String -> M () processFile : String -> M ()
processFile fn = do processFile fn = do