~remexre/public-inbox

Adds datatypes. v1 APPLIED

Nathan Ringo: 1
 Adds datatypes.

 10 files changed, 69 insertions(+), 18 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~remexre/public-inbox/patches/25864/mbox | git am -3
Learn more about email & git

[PATCH] Adds datatypes. Export this patch

---
 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