Compare commits

...

3 Commits

Author SHA1 Message Date
6dda8c4268 2026-05-15 19:55:51 -06:00
5dcf44222f 2026-05-15 16:45:48 -06:00
d38e98d90f 2026-05-15 15:40:40 -06:00
10 changed files with 170 additions and 42 deletions

View File

@@ -7,7 +7,7 @@
{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE PartialTypeSignatures #-}
{-# OPTIONS_GHC -Wno-orphans -Wno-unused-matches -Wno-missing-signatures #-} {-# OPTIONS_GHC -Wno-orphans -Wno-unused-matches -Wno-missing-signatures #-}
{- HLINT ignore "Avoid lambda using `infix`" -} {- HLINT ignore "Avoid lambda using `infix`" -}
module Gyehoek.ANF module Gyehoek.ANF.Syntax
(toANF, lower) (toANF, lower)
where where
@@ -21,8 +21,8 @@ import Data.Generics.Labels
import Data.Vector.Strict (Vector) import Data.Vector.Strict (Vector)
import Data.Function (fix) import Data.Function (fix)
import Effectful.Writer.Static.Local import Effectful.Writer.Static.Local
import Gyehoek.Syntax qualified as Lam import Gyehoek.Scheme.Syntax qualified as Lam
import Gyehoek.Syntax (Name, Prim(..), Lit(..)) import Gyehoek.Scheme.Syntax (Name, Prim(..), Lit(..))
import Gyehoek.GenSym import Gyehoek.GenSym
import Control.Monad.Cont import Control.Monad.Cont
import Data.Foldable import Data.Foldable
@@ -185,7 +185,12 @@ expr2 =
(PrimCons (PrimCons
(Lam.ExpLit (LitInt 2)) (Lam.ExpLit (LitInt 2))
(Lam.ExpLit (LitInt 3))))) (Lam.ExpLit (LitInt 3)))))
, Lam.ExpPrim (PrimWrite (Lam.ExpLit (LitInt 4))) , Lam.ExpPrim
(PrimWrite
(Lam.ExpPrim
(PrimMul
(Lam.ExpLit (LitInt 5))
(Lam.ExpLit (LitInt 4)))))
] ]
@@ -364,9 +369,14 @@ lowerPrim r p e k =
telescope (lowerVal <$> p) \case telescope (lowerVal <$> p) \case
(preview binaryPrim -> Just (bop,a,b)) -> do (preview binaryPrim -> Just (bop,a,b)) -> do
r1 <- gensym r1 <- gensym
r2 <- gensym
Emit [ QBE.BinaryOp (r1 QBE.:= QBE.Long) bop a b Emit [ QBE.BinaryOp (r1 QBE.:= QBE.Long) bop a b
, QBE.BinaryOp (lowerName r QBE.:= QBE.Long) QBE.And , QBE.BinaryOp (r2 QBE.:= QBE.Long) QBE.And
(QBE.ValTemporary r1) (QBE.ValConst (QBE.CInt 0b10)) (QBE.ValTemporary r1)
(QBE.ValConst (QBE.CInt 0xffff_ffff_ffff_fffd))
, QBE.BinaryOp (lowerName r QBE.:= QBE.Long) QBE.Or
(QBE.ValTemporary r2)
(QBE.ValConst (QBE.CInt 0b10))
] ]
<$> lower' e k <$> lower' e k
PrimCons x y -> lowerCons r x y e k PrimCons x y -> lowerCons r x y e k

51
app/Gyehoek/Options.hs Normal file
View File

@@ -0,0 +1,51 @@
{-# LANGUAGE NoFieldSelectors #-}
module Gyehoek.Options
( Options(..)
, parser
)
where
import System.IO (Handle)
import Data.HashSet (HashSet)
import Options.Applicative
import System.FilePath
import qualified Data.HashSet as HS
import Control.Lens hiding (argument)
import GHC.Generics (Generic)
data Options = MkOptions
{ -- dumpANF :: Maybe FilePath
-- , dumpQBE :: Maybe FilePath
output :: Maybe FilePath
, sourceFiles :: HashSet FilePath
}
deriving (Show, Generic)
-- osPath :: ReadM _
-- osPath = eitherReader $
-- (_Left %~ show) . encodeUtf @(Either _)
-- parseDumpQBE =
-- optional $ strOption
-- ( long "dump-qbe"
-- <> metavar "FILE"
-- )
-- parseDumpANF =
-- optional $ strOption
-- ( long "dump-anf"
-- <> metavar "FILE"
-- )
parseOutput =
optional $ strOption
( long "output"
<> short 'o'
<> metavar "FILE"
)
parser :: Parser Options
parser = MkOptions
<$> parseOutput
<*> (HS.fromList <$> some (argument str (metavar "FILES")))

View File

@@ -2,7 +2,7 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeOperators #-}
{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE PartialTypeSignatures #-}
module Gyehoek.Syntax where module Gyehoek.Scheme.Syntax where
import Data.Text (Text) import Data.Text (Text)
import Data.List (List) import Data.List (List)
@@ -40,10 +40,17 @@ data Lit
| LitBool Bool | LitBool Bool
deriving (Show, Generic) deriving (Show, Generic)
data Define
= DefineConstant Name Exp
| DefineProcedure Name (List Name) (List Exp)
deriving (Show, Generic)
data Exp data Exp
= ExpLet (NonEmpty (Name, Exp)) Exp = ExpLet (NonEmpty (Name, Exp)) Exp
| ExpPrim (Prim Exp) | ExpPrim (Prim Exp)
| ExpBegin (List Exp) | ExpBegin (List Exp)
| ExpDefine Define
| ExpIf Exp Exp Exp
| ExpLit Lit | ExpLit Lit
| ExpApply Exp (List Exp) | ExpApply Exp (List Exp)
| ExpLambda (List Name) Exp | ExpLambda (List Name) Exp
@@ -78,17 +85,30 @@ instance SexpIso Lit where
$ With (. sexpIso) $ With (. sexpIso)
$ End $ End
instance SexpIso Define where
sexpIso = match
$ With (. defconst)
$ With (. defun)
$ End
where
defconst = list $ el (sym "define") >>> el symbol >>> el sexpIso
defun = list $ el (sym "define") >>> el args >>> rest sexpIso
args = list $ el symbol >>> rest symbol
instance SexpIso Exp where instance SexpIso Exp where
sexpIso = match sexpIso = match
$ With (. Gyehoek.Sexp.let_ symbol sexpIso sexpIso) $ With (. Gyehoek.Sexp.let_ symbol sexpIso sexpIso)
$ With (. sexpIso) $ With (. sexpIso)
$ With (\bgn -> bgn . list (el (sym "begin") >>> rest sexpIso)) $ With (\bgn -> bgn . list (el (sym "begin") >>> rest sexpIso))
$ With (. sexpIso) $ With (. sexpIso)
$ With (. if_)
$ With (. sexpIso)
$ With (\app -> app . list (el sexpIso >>> rest sexpIso)) $ With (\app -> app . list (el sexpIso >>> rest sexpIso))
$ With (. lam) $ With (. lam)
$ With (. symbol) $ With (. symbol)
$ End $ End
where where
if_ = list $ el (sym "if") >>> el sexpIso >>> el sexpIso >>> el sexpIso
lam = list lam = list
( el (sym "lambda") ( el (sym "lambda")
>>> el (sexpIso @(List Name)) >>> el (sexpIso @(List Name))

View File

@@ -1 +0,0 @@
module Gyehoek.Scratch where

View File

@@ -1,6 +1,7 @@
{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeOperators #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedLabels #-}
module Gyehoek.Sexp module Gyehoek.Sexp
( let_ ( let_
, sexp , sexp
@@ -8,12 +9,14 @@ module Gyehoek.Sexp
, nonEmptyGrammar , nonEmptyGrammar
, encode , encode
, decode , decode
, parseSexps
) )
where where
import Data.Text (Text) import Data.Text (Text)
import Language.SexpGrammar as Sexp hiding (List, encode, decode, iso) import Language.SexpGrammar as Sexp hiding (List, encode, decode, iso)
import Language.SexpGrammar qualified as Sexp import Language.SexpGrammar qualified as Sexp
import Language.Sexp qualified as S
import Language.SexpGrammar.Generic import Language.SexpGrammar.Generic
import Data.InvertibleGrammar.Base qualified as IGB import Data.InvertibleGrammar.Base qualified as IGB
import Data.InvertibleGrammar qualified as IG import Data.InvertibleGrammar qualified as IG
@@ -24,6 +27,12 @@ import Data.Text.Encoding
import Data.Either (either) import Data.Either (either)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Control.Lens import Control.Lens
import Data.Generics.Labels
import System.Process
import GHC.IO.Unsafe (unsafePerformIO)
import qualified Data.Text.IO as TIO
import Control.Monad (join)
import qualified Language.Sexp.Located as SexpLoc
sexp :: SexpIso a => Iso' a Text sexp :: SexpIso a => Iso' a Text
@@ -37,6 +46,10 @@ encode = (_Right %~ decodeUtf8 . view strict) . Sexp.encode
decode :: SexpIso a => Text -> Either String a decode :: SexpIso a => Text -> Either String a
decode = Sexp.decode . view lazy . encodeUtf8 decode = Sexp.decode . view lazy . encodeUtf8
parseSexps :: SexpIso a => FilePath -> Text -> Either String (List a)
parseSexps f = marshal . SexpLoc.parseSexps f . view lazy . encodeUtf8
where marshal = join . traverseOf (_Right . each) (fromSexp sexpIso)
nonEmptyGrammar :: Grammar p (NonEmpty x :- t) (List x :- x :- t) nonEmptyGrammar :: Grammar p (NonEmpty x :- t) (List x :- x :- t)
nonEmptyGrammar = IGB.Iso nonEmptyGrammar = IGB.Iso
(\((x:|xs) :- t) -> xs :- x :- t) (\((x:|xs) :- t) -> xs :- x :- t)

View File

@@ -1,17 +1,54 @@
{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE OverloadedLists #-}
module Main module Main
(main) (main)
where where
import qualified Gyehoek.ANF as ANF import qualified Gyehoek.ANF.Syntax as ANF
import Gyehoek.QBE (render) import Gyehoek.QBE (render)
import Gyehoek.Options
import qualified Data.Text.IO as TIO import qualified Data.Text.IO as TIO
import Prelude hiding ((.),id) import Data.Text (Text)
import Prelude hiding (readFile, (.),id)
import Control.Category import Control.Category
import Options.Applicative
import Control.Lens
import Data.Generics.Labels
import System.OsPath (OsPath)
import System.FilePath ((-<.>))
import Effectful.FileSystem
import Effectful
import Effectful.FileSystem.IO
import Gyehoek.GenSym (runGenSym)
import qualified Gyehoek.Sexp as Sexp
import Data.Text.Lens
import Data.List (List)
import qualified Gyehoek.Scheme.Syntax as Scm
import Effectful.Exception
main :: IO () main :: IO ()
main = TIO.putStrLn . render $ ANF.expr main = do
opts <- info (helper <*> parser) (fullDesc)
runEff . runFileSystem . driver $ opts
hPutStr :: IOE :> es => Handle -> Text -> Eff es ()
hPutStr h = liftIO . TIO.hPutStr h
readFile :: IOE :> es => FilePath -> Eff es Text
readFile = liftIO . TIO.readFile
readScm :: FileSystem :> es => FilePath -> Eff es (List Scm.Exp)
readScm f = (Sexp.parseSexps f <$> readFile f) >>= either error pure
driver :: FileSystem :> es => Options -> Eff es ()
driver = runGenSym . traverseOf_ (#sourceFiles . folded) \f ->
withFile f ReadMode \h_scm ->
(Sexp.encode <$> ANF.toANF _) >>= \case
Left e -> hPutStr stderr (view packed e)
Right s ->
withFile (f -<.> "anf") WriteMode \h_anf -> do
hPutStr h_anf ";;; -*- mode:scheme -*-\n\n"
hPutStr h_anf s

View File

@@ -13,48 +13,58 @@ build-type: Simple
-- extra-doc-files: CHANGELOG.md -- extra-doc-files: CHANGELOG.md
-- extra-source-files: -- extra-source-files:
common ghcstuffs-dev
ghc-options:
-Wno-unused-matches -Wno-missing-signatures -Wno-typed-holes
common ghcstuffs common ghcstuffs
ghc-options: ghc-options:
-Wall -fdefer-type-errors -fno-show-valid-hole-fits -Wall -fdefer-type-errors -fno-show-valid-hole-fits
-fdefer-out-of-scope-variables -Wno-typed-holes -fdefer-out-of-scope-variables -fplugin=Effectful.Plugin
-fplugin=Effectful.Plugin
other-extensions: default-extensions:
BlockArguments BlockArguments
DeriveGeneric
OverloadedStrings
PartialTypeSignatures PartialTypeSignatures
PatternSynonyms
executable gyehoek executable gyehoek
import: ghcstuffs import: ghcstuffs, ghcstuffs-dev
main-is: Main.hs main-is: Main.hs
-- cabal-fmt: expand app -Main -- cabal-fmt: expand app -Main
other-modules: other-modules:
Gyehoek.ANF Gyehoek.ANF.Syntax
Gyehoek.Sexp
Gyehoek.GenSym Gyehoek.GenSym
Gyehoek.Options
Gyehoek.QBE Gyehoek.QBE
Gyehoek.QBE.Parse Gyehoek.QBE.Parse
Gyehoek.Scratch Gyehoek.Scheme.Syntax
Gyehoek.Syntax Gyehoek.Sexp
-- other-extensions:
build-depends: build-depends:
, base ^>=4.21.2.0 , base ^>=4.21.2.0
, containers
, effectful , effectful
, effectful-core , effectful-core
, effectful-plugin , effectful-plugin
, filepath
, generic-lens
, invertible-grammar
, lens , lens
, megaparsec , megaparsec
, mtl , mtl
, optparse-applicative
, prettyprinter , prettyprinter
, process
, qbe , qbe
, recursion-schemes , recursion-schemes
, sexp-grammar
, template-haskell , template-haskell
, text , text
, unordered-containers
, vector , vector
, generic-lens
, sexp-grammar
, invertible-grammar
hs-source-dirs: app hs-source-dirs: app
default-language: GHC2024 default-language: GHC2024

Binary file not shown.

View File

@@ -1,12 +0,0 @@
type :scm = {l 2}
export
function w $main () {
@start
%x0 =l call $GC_malloc (l 16)
%.3 =l add %x0, 8
storel 10, %x0
storel 14, %.3
%x1 =l call $scm_write (l %x0)
%x2 =l call $scm_write (l 18)
ret %x2
}

View File

@@ -3,9 +3,9 @@
SCM scm_write (SCM x) { SCM scm_write (SCM x) {
if (SCM_IMP (x)) { if (SCM_IMP (x)) {
printf ("#<immediate %ld>\n", SCM_UNPACK (x)); printf ("#<immediate %ld>\n", SCM_UNPACK (x) >> 2);
} else { } else {
printf ("#<heap object %ld>\n", SCM_UNPACK(x)); printf ("#<heap object %lx>\n", SCM_UNPACK(x));
} }
return SCM_PACK(NULL); return SCM_PACK(NULL);
} }