Skip to content

Commit 22dbabe

Browse files
authored
Merge pull request #35 from mlabs-haskell/bladyjoker/frontend
Frontend: Integration with the Compiler
2 parents b7c7f60 + b1c3747 commit 22dbabe

File tree

15 files changed

+1324
-64
lines changed

15 files changed

+1324
-64
lines changed

flake.nix

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@
9494
# Frontend Build
9595
frontendBuild = buildAbstraction {
9696
import-location = ./lambda-buffers-frontend/build.nix;
97-
additional = { lambda-buffers-compiler = ./lambda-buffers-compiler; };
97+
additional = {
98+
lambda-buffers-compiler = ./lambda-buffers-compiler;
99+
lambda-buffers-compiler-cli = compilerFlake.packages."lambda-buffers-compiler:exe:lbc";
100+
};
98101
};
99102
frontendFlake = flakeAbstraction frontendBuild;
100103

lambda-buffers-compiler/lambda-buffers-compiler.cabal

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,7 @@ library
128128

129129
hs-source-dirs: src
130130

131-
-- NOTE(cstml): should we name this something shorter? lb-cli?
132-
executable lambda-buffers-compiler-cli
131+
executable lbc
133132
import: common-language
134133
import: common-imports
135134
main-is: Main.hs
@@ -154,7 +153,6 @@ test-suite tests
154153
, containers >=0.6
155154
, lambda-buffers-compiler
156155
, lambda-buffers-compiler-pb >=0.1
157-
, mtl >=2.2
158156
, proto-lens >=0.7
159157
, QuickCheck >=2.14
160158
, tasty >=1.4

lambda-buffers-compiler/test/Test/LambdaBuffers/Compiler/Gen.hs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
module Test.LambdaBuffers.Compiler.Gen (genCompilerInput) where
22

33
import Control.Lens ((&), (.~), (^.))
4-
import Control.Monad.Reader (replicateM)
4+
import Data.Foldable (Foldable (toList))
55
import Data.List qualified as List
6+
import Data.List.NonEmpty (NonEmpty ((:|)))
67
import Data.ProtoLens (Message (defMessage))
78
import Data.Text (Text)
89
import Data.Text qualified as Text
910
import Data.Traversable (for)
10-
import Proto.Compiler (ClassName, CompilerInput, ConstrName, Kind'KindRef (Kind'KIND_REF_TYPE), Module, ModuleName, ModuleNamePart, Sum, Sum'Constructor, Ty, TyAbs, TyArg, TyBody, TyDef, TyName, VarName)
11-
import Proto.Compiler_Fields (argKind, argName, constrName, constructors, fields, kindRef, moduleName, modules, name, ntuple, parts, tyAbs, tyArgs, tyBody, tyName, tyVar, typeDefs, varName)
11+
import Proto.Compiler (ClassName, CompilerInput, ConstrName, Kind'KindRef (Kind'KIND_REF_TYPE), Module, ModuleName, ModuleNamePart, Sum, Sum'Constructor, Ty, TyAbs, TyArg, TyBody, TyDef, TyName, TyRef, VarName)
12+
import Proto.Compiler_Fields (argKind, argName, constrName, constructors, fields, kindRef, moduleName, modules, name, ntuple, parts, tyAbs, tyArgs, tyBody, tyName, tyRef, tyVar, typeDefs, varName)
1213
import Proto.Compiler_Fields qualified as P
1314
import Test.QuickCheck qualified as QC (Gen, chooseEnum, chooseInt, elements, oneof, vectorOf)
1415

1516
vecOf :: forall {a}. QC.Gen a -> Int -> QC.Gen [a]
16-
vecOf g n = replicateM n g
17+
vecOf = flip QC.vectorOf
1718

1819
limit :: Int
19-
limit = 10
20+
limit = 4
2021

2122
-- | Names
2223
genAlphaNum :: QC.Gen Char
@@ -73,27 +74,44 @@ genSum args = do
7374
return $ defMessage & constructors .~ ctors
7475

7576
-- TODO(bladyjoker): Add TyRef, TyApp etc.
76-
genTy :: [TyArg] -> QC.Gen Ty
77-
genTy args = do
78-
ar <- QC.elements args
77+
genTy :: [TyRef] -> [TyArg] -> QC.Gen Ty
78+
genTy (r : refs) (a : args) = QC.oneof [genTyVar (a :| args), genTyRef (r :| refs)]
79+
genTy [] (a : args) = QC.oneof [genTyVar (a :| args)]
80+
genTy (r : refs) [] = QC.oneof [genTyRef (r :| refs)]
81+
genTy _ _ = error "TODO(bladyjoker): Not yet implemented"
82+
83+
genTyRef :: NonEmpty TyRef -> QC.Gen Ty
84+
genTyRef refs = do
85+
r <- QC.elements (toList refs)
86+
return $ defMessage & tyRef .~ r
87+
88+
genTyVar :: NonEmpty TyArg -> QC.Gen Ty
89+
genTyVar args = do
90+
ar <- QC.elements (toList args)
7991
return $ defMessage & tyVar . varName .~ (ar ^. argName)
8092

8193
genConstructor :: [TyArg] -> ConstrName -> QC.Gen Sum'Constructor
8294
genConstructor args cn = do
83-
tys <- QC.chooseInt (1, limit) >>= vecOf (genTy args)
95+
tys <- QC.chooseInt (1, limit) >>= vecOf (genTy mempty args)
8496
return $
8597
defMessage
8698
& constrName .~ cn
8799
& P.product . ntuple . fields .~ tys
88100

89-
-- TODO(bladyjoker): Add Opaque.
90101
genTyBody :: [TyArg] -> QC.Gen TyBody
91-
genTyBody args = do
102+
genTyBody args = QC.oneof [genTyBodyOpaque, genTyBodySum args]
103+
104+
genTyBodySum :: [TyArg] -> QC.Gen TyBody
105+
genTyBodySum args = do
92106
b <- genSum args
93107
return $ defMessage & P.sum .~ b
94108

109+
genTyBodyOpaque :: QC.Gen TyBody
110+
genTyBodyOpaque = return $ defMessage & P.opaque .~ defMessage
111+
95112
genTyAbs :: QC.Gen TyAbs
96113
genTyAbs = do
114+
-- TODO(bladyjoker): Allow empty args
97115
vns <- QC.chooseInt (1, limit) >>= vecOf genVarName
98116
args <- for (List.nub vns) genTyArg
99117
body <- genTyBody args
Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
module LambdaBuffers.Frontend.Cli.Compile (CompileOpts (..), compile) where
22

33
import Control.Lens (makeLenses, (^.))
4-
import Data.Map qualified as Map
4+
import Data.ByteString qualified as BS
5+
import Data.Maybe (fromMaybe)
6+
import Data.ProtoLens.Encoding qualified as Pb
7+
import Data.ProtoLens.TextFormat qualified as PbText
8+
import Data.Text.Lazy qualified as Text
9+
import Data.Text.Lazy.IO qualified as Text
510
import LambdaBuffers.Frontend (runFrontend)
611
import LambdaBuffers.Frontend.PPrint ()
7-
import Prettyprinter (Pretty (pretty))
8-
import Proto.Compiler ()
12+
import LambdaBuffers.Frontend.ToProto (toCompilerInput)
13+
import Proto.Compiler (CompilerInput)
14+
import System.FilePath ((<.>), (</>))
15+
import System.FilePath.Lens (extension)
16+
import System.IO.Temp (withSystemTempDirectory)
17+
import System.Process (callProcess)
918

1019
data CompileOpts = CompileOpts
1120
{ _importPaths :: [FilePath]
1221
, _moduleFilepath :: FilePath
22+
, _compilerCliFilepath :: FilePath
23+
, _debug :: Bool
24+
, _workingDir :: Maybe FilePath
1325
}
1426
deriving stock (Eq, Show)
1527

@@ -21,6 +33,27 @@ compile opts = do
2133
errOrMod <- runFrontend (opts ^. importPaths) (opts ^. moduleFilepath)
2234
case errOrMod of
2335
Left err -> print err
24-
Right mods -> do
36+
Right res -> do
37+
-- TODO(bladyjoker): Use proper logging (Katip)
2538
putStrLn "OK"
26-
putStrLn $ "Compiler closure contains the following modules: " <> (show . pretty . Map.elems $ mods)
39+
compInp <- either (\e -> error $ "Failed translating to Compiler proto: " <> show e) return (toCompilerInput res)
40+
let ext = if opts ^. debug then "textproto" else "pb"
41+
withSystemTempDirectory
42+
"lambda-buffers-frontend"
43+
( \tempDir -> do
44+
let workDir = fromMaybe tempDir (opts ^. workingDir)
45+
compInpFp = workDir </> "compiler-input" <.> ext
46+
compOutFp = workDir </> "compiler-output" <.> ext
47+
writeCompilerInput compInpFp compInp
48+
let args = ["compile", "--input-file", compInpFp, "--output-file", compOutFp]
49+
putStrLn $ "Calling: " <> show (opts ^. compilerCliFilepath) <> " on " <> show args
50+
callProcess (opts ^. compilerCliFilepath) args
51+
)
52+
53+
writeCompilerInput :: FilePath -> CompilerInput -> IO ()
54+
writeCompilerInput fp compInp = do
55+
let ext = fp ^. extension
56+
case ext of
57+
".pb" -> BS.writeFile fp (Pb.encodeMessage compInp)
58+
".textproto" -> Text.writeFile fp (Text.pack . show $ PbText.pprintMessage compInp)
59+
_ -> error $ "Unknown CompilerInput format " <> ext

lambda-buffers-frontend/app/Main.hs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
module Main (main) where
22

3-
import Control.Applicative (Alternative (many), (<**>))
4-
3+
import Control.Applicative (Alternative (many), optional, (<**>))
54
import LambdaBuffers.Frontend.Cli.Compile (CompileOpts (CompileOpts), compile)
65
import LambdaBuffers.Frontend.Cli.Format (FormatOpts (FormatOpts), format)
76
import Options.Applicative (
@@ -49,6 +48,29 @@ compileOptsP =
4948
<> metavar "FILEPATH"
5049
<> help "LambdaBuffers file (.lbf) to compile"
5150
)
51+
<*> strOption
52+
( long "compiler"
53+
<> short 'c'
54+
<> metavar "FILEPATH"
55+
<> help "LambdaBuffers compiler location (lambda-buffers-compiler-cli)"
56+
)
57+
<*> flag
58+
False
59+
True
60+
( long "debug"
61+
<> short 'd'
62+
<> help "Run in debug mode"
63+
<> showDefault
64+
)
65+
<*> optional
66+
( strOption
67+
( long "work-dir"
68+
<> short 'w'
69+
<> metavar "FILEPATH"
70+
<> help "Working directory used to communicate with the Compiler"
71+
<> showDefault
72+
)
73+
)
5274

5375
formatOptsP :: Parser FormatOpts
5476
formatOptsP =

lambda-buffers-frontend/build.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
, index-state
66
, compilerHsPb
77
, lambda-buffers-compiler
8+
, lambda-buffers-compiler-cli
89
, commonTools
910
, shellHook
1011
}:
@@ -41,7 +42,7 @@ let
4142

4243
exactDeps = true;
4344

44-
nativeBuildInputs = builtins.attrValues commonTools;
45+
nativeBuildInputs = [ lambda-buffers-compiler-cli ] ++ builtins.attrValues commonTools;
4546

4647
tools = {
4748
cabal = { };

lambda-buffers-frontend/lambda-buffers-frontend.cabal

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,34 +88,42 @@ common common-language
8888
library
8989
import: common-language
9090
build-depends:
91-
, base >=4.16
92-
, containers >=0.6
93-
, directory >=1.3
94-
, filepath >=1.4
95-
, lambda-buffers-compiler >=0.1
96-
, mtl >=2.2
97-
, parsec >=3.1
98-
, prettyprinter >=1.7
99-
, text >=1.2
100-
, transformers >=0.5
91+
, base >=4.16
92+
, containers >=0.6
93+
, directory >=1.3
94+
, filepath >=1.4
95+
, lambda-buffers-compiler >=0.1
96+
, lambda-buffers-compiler-pb >=0.1
97+
, lens >=5.2
98+
, mtl >=2.2
99+
, parsec >=3.1
100+
, prettyprinter >=1.7
101+
, proto-lens >=0.7
102+
, text >=1.2
103+
, transformers >=0.5
101104

102105
hs-source-dirs: src
103106
exposed-modules:
104107
LambdaBuffers.Frontend
105108
LambdaBuffers.Frontend.Parsec
106109
LambdaBuffers.Frontend.PPrint
107110
LambdaBuffers.Frontend.Syntax
111+
LambdaBuffers.Frontend.ToProto
108112

109-
executable lambda-buffers-frontend-cli
113+
executable lbf
110114
import: common-language
111115
build-depends:
112116
, base >=4.16
113-
, containers >=0.6
117+
, bytestring >=0.11
118+
, filepath >=1.4
114119
, lambda-buffers-compiler-pb >=0.1
115120
, lambda-buffers-frontend
116121
, lens >=5.2
117122
, optparse-applicative >=0.17
118123
, prettyprinter >=1.7
124+
, process >=1.6
125+
, proto-lens >=0.7
126+
, temporary
119127
, text >=1.2
120128

121129
hs-source-dirs: app

lambda-buffers-frontend/resources/good/Test.lbf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ sum Either a b = Left a | Right b
1717

1818
sum List a = Nil | List a (List a)
1919

20-
opaque Int a
20+
opaque Int
21+
2122
opaque Bytes
2223

2324
sum Foo a = MkFoo

0 commit comments

Comments
 (0)