---
bootstrap/Language/Sylvan/CST.hs | 4 ++++
bootstrap/Language/Sylvan/CST/Pretty.hs | 13 ++++++++----
bootstrap/Language/Sylvan/Env.hs | 8 +++++---
bootstrap/Language/Sylvan/Eval.hs | 3 +++
bootstrap/Language/Sylvan/Parser.y | 25 ++++++++++++++++++++++--
bootstrap/Language/Sylvan/Parser/Lexer.x | 7 +++++--
bootstrap/default.nix | 14 ++++++-------
bootstrap/sylvan-bootstrap.cabal | 2 ++
src/std/data/linked_list/linked_list.syl | 8 ++++++++
src/sylvan/driver/main.syl | 3 +++
10 files changed, 69 insertions(+), 18 deletions(-)
create mode 100644 bootstrap/Language/Sylvan/Eval.hs
create mode 100644 src/std/data/linked_list/linked_list.syl
diff --git a/bootstrap/Language/Sylvan/CST.hs b/bootstrap/Language/Sylvan/CST.hs
index cf16140..fbf8fe5 100644
--- a/bootstrap/Language/Sylvan/CST.hs
@@ -36,6 +36,9 @@ data ImportModifier
deriving (Show)
data Decl where
+ D'AttrInh :: ByteString -> GenericDeclArgs -> Type -> Decl
+ D'AttrSyn :: ByteString -> GenericDeclArgs -> Type -> Decl
+ D'Data :: ByteString -> GenericDeclArgs -> Seq (ByteString, GenericDeclArgs, Seq Type) -> Decl
D'ForeignGlobal :: ByteString -> GenericDeclArgs -> Type -> ForeignItems -> Decl
D'ForeignType :: ByteString -> GenericDeclArgs -> Kind -> ForeignItems -> Decl
D'Global :: ByteString -> GenericDeclArgs -> Type -> Expr -> Decl
@@ -52,6 +55,7 @@ data Expr where
E'App :: Expr -> Seq Expr -> Expr
E'Access :: Expr -> LName -> Expr
E'Inhs :: Seq (LName, Expr) -> Expr
+ E'Int :: Int -> Expr
E'Lam :: Seq (ByteString, Maybe Type) -> Expr -> Expr
E'String :: ByteString -> Expr
E'Var :: LName -> Expr
diff --git a/bootstrap/Language/Sylvan/CST/Pretty.hs b/bootstrap/Language/Sylvan/CST/Pretty.hs
index f43abeb..58cef93 100644
--- a/bootstrap/Language/Sylvan/CST/Pretty.hs
@@ -81,6 +81,7 @@ prettyDecl (D'Type name genericArgs kind ty) =
equals,
prettyType ty <> semi
]
+prettyDecl decl = pretty (show decl) -- TODO
-- Expressions
@@ -99,6 +100,7 @@ prettyExpr2 expr = prettyExpr3 expr
prettyExpr3 :: Expr -> Doc AnsiStyle
prettyExpr3 (E'Var name) = prettyVarName name
+prettyExpr3 (E'Int n) = prettyInt n
prettyExpr3 (E'String s) = prettyString s
prettyExpr3 (E'Inhs inhs) = group (braces (nest 2 (line <> prettyInhPairs inhs) <> line))
prettyExpr3 expr = parens (prettyExpr1 expr)
@@ -186,8 +188,11 @@ dcolon = annotate styleModuleName (colon <> colon)
-- Literals
+prettyInt :: Int -> Doc AnsiStyle
+prettyInt = annotate styleLiteral <<< pretty
+
prettyString :: ByteString -> Doc AnsiStyle
-prettyString = annotate styleString <<< dquotes <<< BS.foldr (\ch -> (helper ch <>)) emptyDoc
+prettyString = annotate styleLiteral <<< dquotes <<< BS.foldr (\ch -> (helper ch <>)) emptyDoc
where
helper ch =
pretty $
@@ -268,12 +273,12 @@ styleKeyword = color Magenta <> bold
styleKindName :: AnsiStyle
styleKindName = colorDull Magenta
+styleLiteral :: AnsiStyle
+styleLiteral = color Yellow
+
styleModuleName :: AnsiStyle
styleModuleName = colorDull Blue
-styleString :: AnsiStyle
-styleString = color Yellow
-
styleTypeName :: AnsiStyle
styleTypeName = color Green
diff --git a/bootstrap/Language/Sylvan/Env.hs b/bootstrap/Language/Sylvan/Env.hs
index b333cdf..5ec94ef 100644
--- a/bootstrap/Language/Sylvan/Env.hs
@@ -1,7 +1,9 @@
module Language.Sylvan.Env where
-data ModuleEnv = MkModuleEnv
- { module'globals :: (),
- module'types :: ()
+import Data.Trie (Trie)
+
+data Env = MkEnv
+ { env'globals :: Trie (),
+ env'nts :: Trie ()
}
deriving (Show)
diff --git a/bootstrap/Language/Sylvan/Eval.hs b/bootstrap/Language/Sylvan/Eval.hs
new file mode 100644
index 0000000..1485c03
--- /dev/null
@@ -0,0 +1,3 @@
+-- | An interpreter for Sylvan. Interpreting the language in the bootstrapper
+-- lets me put off needing to write a compiler backend!
+module Language.Sylvan.Eval where
diff --git a/bootstrap/Language/Sylvan/Parser.y b/bootstrap/Language/Sylvan/Parser.y
index 62e67ae..8510532 100644
--- a/bootstrap/Language/Sylvan/Parser.y
@@ -5,7 +5,7 @@
module Language.Sylvan.Parser (parse, parseLazy) where
import Control.Arrow (first)
-import Control.Category ((<<<))
+import Control.Category ((<<<), (>>>))
import Control.Monad ((<=<))
import Control.Monad.Error.Class (MonadError (..))
import Control.Monad.Reader.Class (MonadReader (..))
@@ -23,6 +23,7 @@ import Data.Sequence qualified as Seq
import Language.Sylvan.CST
import Language.Sylvan.Parser.Lexer (Token (..), lexer)
import Language.Sylvan.Parser.Utils (uncheckedParseLName, uncheckedParseModuleName, uncheckedParseUName)
+import Text.Read (readEither)
}
%name parser
@@ -38,6 +39,7 @@ import Language.Sylvan.Parser.Utils (uncheckedParseLName, uncheckedParseModuleNa
'-' { Just Token'Minus }
'*' { Just Token'Star }
'->' { Just Token'Arrow }
+ 'data' { Just Token'Data }
'fn' { Just Token'Fn }
'forall' { Just Token'Forall }
'foreign' { Just Token'Foreign }
@@ -86,7 +88,9 @@ ImportModifier :: { ImportModifier }
| 'renaming' '(' manyComma(pairSep(ID_L, 'to', ID_L)) ')' { Renaming $3 }
Decl :: { Decl }
- : 'fn' ID_L OptGenericDeclArgs '(' DeclFnArgs ')' ':' Type '=' Expr ';'
+ : 'data' ID_U OptGenericDeclArgs '{' manyComma(CtorDecl) '}'
+ { D'Data $2 $3 $5 }
+ | 'fn' ID_L OptGenericDeclArgs '(' DeclFnArgs ')' ':' Type '=' Expr ';'
{ D'Global $2 $3 (T'Arrow (fmap snd $5) $8) (E'Lam (fmap (second Just) $5) $10) }
| 'foreign' 'global' ID_L OptGenericDeclArgs ':' Type '=' '{' ForeignItems '}' ';'
{ D'ForeignGlobal $3 $4 $6 $9 }
@@ -94,11 +98,21 @@ Decl :: { Decl }
{ D'ForeignType $3 $4 $5 $8 }
| 'global' ID_L OptGenericDeclArgs ':' Type '=' Expr ';'
{ D'Global $2 $3 $5 $7 }
+ | 'inh' ID_L OptGenericDeclArgs ':' Type ';'
+ { D'AttrInh $2 $3 $5 }
| 'nt' ID_U OptGenericDeclArgs ';'
{ D'NT $2 $3 }
+ | 'syn' ID_L OptGenericDeclArgs ':' Type ';'
+ { D'AttrInh $2 $3 $5 }
| 'type' ID_U OptGenericDeclArgs OptKind '=' Type ';'
{ D'Type $2 $3 $4 $6 }
+CtorDecl :: { (ByteString, GenericDeclArgs, Seq Type) }
+ : ID_L OptGenericDeclArgs
+ { ($1, $2, Empty) }
+ | ID_L OptGenericDeclArgs '(' manyComma(Type) ')'
+ { ($1, $2, $4) }
+
-- Expressions
Expr1 :: { Expr }
@@ -112,6 +126,7 @@ Expr2 :: { Expr }
Expr3 :: { Expr }
: Name_L { E'Var $1 }
+ | Int { E'Int $1 }
| String { E'String $1 }
| '{' manyComma(pairSep(Name_L, '=', Expr1)) '}' { E'Inhs $2 }
| '(' Expr1 ')' { $2 }
@@ -158,6 +173,7 @@ Name_U :: { UName }
-- Literals
+Int :: { Int } : INT {% parseInt $1 }
String :: { ByteString } : STRING {% parseString $1 }
-- Aliases
@@ -230,6 +246,11 @@ parseKind "TERM" = pure K'Term
parseKind "TREE" = pure K'Tree
parseKind name = parseError (Just (Token'NameU name), ["CONSTRAINT", "DATA", "INHS", "TERM", "TREE"])
+parseInt :: ByteString -> M Int
+parseInt = BS.toString >>> readEither >>> \case
+ Left err -> throwError err
+ Right n -> pure n
+
-- TODO: This seems fairly inefficient...
parseString :: ByteString -> M ByteString
parseString = fmap BS.fromString <<< loop <<< BS.toString <<< BS.init <<< BS.tail where
diff --git a/bootstrap/Language/Sylvan/Parser/Lexer.x b/bootstrap/Language/Sylvan/Parser/Lexer.x
index 9e138e7..88c7c48 100644
--- a/bootstrap/Language/Sylvan/Parser/Lexer.x
@@ -21,6 +21,7 @@ tokens :-
"-" { const Token'Minus }
"*" { const Token'Star }
"->" { const Token'Arrow }
+ "data" { const Token'Data }
"fn" { const Token'Fn }
"forall" { const Token'Forall }
"foreign" { const Token'Foreign }
@@ -62,9 +63,10 @@ data Token
| Token'Minus
| Token'Star
| Token'Arrow
+ | Token'Data
+ | Token'Fn
| Token'Forall
| Token'Foreign
- | Token'Fn
| Token'Global
| Token'Hiding
| Token'Import
@@ -101,9 +103,10 @@ instance Show Token where
show Token'Minus = "\"-\""
show Token'Star = "\"*\""
show Token'Arrow = "\"->\""
+ show Token'Data = "\"data\""
+ show Token'Fn = "\"fn\""
show Token'Forall = "\"forall\""
show Token'Foreign = "\"foreign\""
- show Token'Fn = "\"fn\""
show Token'Global = "\"global\""
show Token'Hiding = "\"hiding\""
show Token'Import = "\"import\""
diff --git a/bootstrap/default.nix b/bootstrap/default.nix
index ae24293..79ec45a 100644
--- a/bootstrap/default.nix
@@ -1,8 +1,8 @@
-{ mkDerivation, alex, array, base, bytestring, containers
-, directory, filepath, happy, lib, logict, microlens, microlens-ghc
-, microlens-th, mtl, optparse-applicative, prettyprinter
-, prettyprinter-ansi-terminal, regex-tdfa, transformers
-, utf8-string
+{ mkDerivation, alex, array, base, bytestring, bytestring-trie
+, containers, directory, filepath, happy, lib, logict, microlens
+, microlens-ghc, microlens-th, mtl, optparse-applicative
+, prettyprinter, prettyprinter-ansi-terminal, regex-tdfa
+, transformers, utf8-string
}:
mkDerivation {
pname = "sylvan-bootstrap";
@@ -11,8 +11,8 @@ mkDerivation {
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = [
- array base bytestring containers directory filepath logict
- microlens microlens-ghc microlens-th mtl prettyprinter
+ array base bytestring bytestring-trie containers directory filepath
+ logict microlens microlens-ghc microlens-th mtl prettyprinter
prettyprinter-ansi-terminal regex-tdfa transformers utf8-string
];
libraryToolDepends = [ alex happy ];
diff --git a/bootstrap/sylvan-bootstrap.cabal b/bootstrap/sylvan-bootstrap.cabal
index 836b7a5..f880411 100644
--- a/bootstrap/sylvan-bootstrap.cabal
@@ -10,6 +10,7 @@ library
array ^>=0.5.4.0
, base >=4 && <5
, bytestring ^>=0.10.12.1
+ , bytestring-trie ^>=0.2.5.2
, containers ^>=0.6.4.1
, directory ^>=1.3.6.1
, filepath ^>=1.4.2.1
@@ -76,6 +77,7 @@ library
, Language.Sylvan.CST
, Language.Sylvan.CST.Pretty
, Language.Sylvan.Env
+ , Language.Sylvan.Eval
, Language.Sylvan.Modules
, Language.Sylvan.Parser
, Language.Sylvan.Parser.Lexer
diff --git a/src/std/data/linked_list/linked_list.syl b/src/std/data/linked_list/linked_list.syl
new file mode 100644
index 0000000..56c5f59
--- /dev/null
+++ b/src/std/data/linked_list/linked_list.syl
@@ -0,0 +1,8 @@
+module std::data::linked_list;
+
+import std::prelude;
+
+data LinkedList<a> {
+ nil,
+ cons(a, LinkedList<a>)
+}
diff --git a/src/sylvan/driver/main.syl b/src/sylvan/driver/main.syl
index 9eb4cf6..82275cd 100644
--- a/src/sylvan/driver/main.syl
+++ b/src/sylvan/driver/main.syl
@@ -1,6 +1,7 @@
module sylvan::driver;
import std::prelude hiding (foo) renaming (bar to foo) using (baz, asdf);
+import std::data::linked_list;
import std::data::set;
fn main(ioIn: IOToken): IOToken = print(ioIn, "Hello, world!");
@@ -10,3 +11,5 @@ global foo: Foo = {
bar = one(),
baz = "two",
};
+
+global n: Int = 3;
--
2.33.0