Skip to content

Commit

Permalink
Add simple parsing in of vars from .env for output configs
Browse files Browse the repository at this point in the history
  • Loading branch information
ym-han committed Nov 4, 2024
1 parent b2b93bd commit 99959e5
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 27 deletions.
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ UPDATE_REMOTE_DECISION_SERVICE_ON_SAVE_STATUS=<use "update" if you want it to up
DECISION_SERVICE_REQUEST_MAKER_CMD=<for CCLAW: use "l4-oia">
DEMO_OIA_DATA_MODEL_XML_PATH=<for CCLAW: use path to projectDataModel.xml>
COMPILED_SIMALA_OUTPUT_DIR="generated/simala"
NLG_EN_OUTPUT_DIR="generated/nlg_en"
NLG_EN_OUTPUT_FILENAME="nlg_en_output.json"
GF_PORTABLE_GRAMMAR_FORMAT_FILENAME="Lam4.pgf"
```

## How to compile Lam4 files

Use the `lam4-cli`.

EG, from the root `lam4` dir:
EG, from the root `lam4` dir:

> `cabal run lam4-cli -- examples/arithmetic.l4`
Expand Down Expand Up @@ -100,9 +103,9 @@ When things update...
* You can update your VSCode extension from the command line using the commands mentioned earlier. Yongming has a personal script for this that can be adapted (`yongminghan` is the publisher). If the changes don't show up, try restarting the extension host from VSCode:

```bash
code --uninstall-extension yongminghan.lam4;
rm lam4-0.0.1.vsix;
vsce package;
code --uninstall-extension yongminghan.lam4;
rm lam4-0.0.1.vsix;
vsce package;
code --install-extension lam4*.vsix
```

Expand All @@ -125,7 +128,7 @@ After building:

#### Typechecker, evaluator, backend related

The type checker is currently implemented in Typescript, but in the medium term I want to just move that to the Haskell backend.
The type checker is currently implemented in Typescript, but in the medium term I want to just move that to the Haskell backend.

I also want to have some kind of JSON RPC going with the Haskell backend, so that we'll be able to, e.g., parse the program, run the evaluator, and see nice feedback in a webview, all within the IDE.

Expand All @@ -136,4 +139,4 @@ I also want to have some kind of JSON RPC going with the Haskell backend, so tha

When time permits -- e.g., shortly after the first end-to-end system is done --- we should try cutting down on symbols like braces if that will confuse non-professional programmers. EG, we could instead go for something that uses indentation.

This is already possible with Langium; I just haven't done it because it requires a bit more effort and would complicate the codebase more than I would like at this stage.
This is already possible with Langium; I just haven't done it because it requires a bit more effort and would complicate the codebase more than I would like at this stage.
92 changes: 71 additions & 21 deletions lam4-cli/app/Main.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}

module Main where

Expand All @@ -14,33 +14,50 @@ import Data.ByteString as BS hiding (concat, concatMap,
map, null, putStr)
import qualified Data.Text as T

import Configuration.Dotenv (loadFile, defaultConfig, onMissingFile)

import Cradle
import qualified Lam4.Expr.ConcreteSyntax as CST (Decl)
import Lam4.Expr.ExtractProgramInfo
import Lam4.Expr.Parser (parseProgramByteStr)
import Lam4.Expr.ToConcreteEvalAST (cstProgramToConEvalProgram)
import Lam4.Expr.ToSimala ()
import qualified Lam4.Expr.ToSimala as ToSimala
import qualified Lam4.Render.Render as Render
import Lam4.Render.Render (NLGConfig(..))
import Lam4.Parser.Monad (evalParserFromScratch)
import Lam4.Render.Render (NLGConfig (..))
import qualified Lam4.Render.Render as Render
import Options.Applicative as Options
import System.Directory
import System.FilePath ((</>))
import System.Environment.Blank (getEnv)

------------------------------
-- The key config types
-------------------------------

data FrontendConfig =
MkFrontendConfig { frontendDir :: FilePath
, runner :: String
, args :: [String]
}

data OutputConfig =
MkOutputConfig { simalaOutputConfig :: SimalaOutputConfig
, nlgOutputConfig :: NLGConfig }

data SimalaOutputConfig =
MkSimalaOutputConfig {
outputDir :: FilePath
, programFilename :: FilePath
, programInfoFilename :: FilePath
}

----------------------------------
-- Constants / default values
----------------------------------

-- TODO: Most of the following should be put in, and read from, the .env file

lam4FrontendDir :: FilePath
lam4FrontendDir = "lam4-frontend"

Expand All @@ -49,22 +66,24 @@ frontendConfig = MkFrontendConfig { runner = "node"
, frontendDir = lam4FrontendDir
, args = [lam4FrontendDir </> "bin" </> "cli", "toMinimalAst"] }

-- TODO: Most of the following should be put in, and read from, the .env file
simalaOutputConfig :: SimalaOutputConfig
simalaOutputConfig = MkSimalaOutputConfig {
defaultSimalaOutputConfig :: SimalaOutputConfig
defaultSimalaOutputConfig = MkSimalaOutputConfig {
outputDir = "generated" </> "simala"
, programFilename = "output.simala"
, programInfoFilename = "program_info.json" }

-- TODO: read outputDir in from a .env file
nlgConfig :: NLGConfig
nlgConfig = MkNLGConfig {
defaultNlgConfig :: NLGConfig
defaultNlgConfig = MkNLGConfig {
outputDir = "generated" </> "nlg_en"
, resultFilename = "output.txt"
, abstractSyntaxFilename = "Lam4.pgf"
, outputFilename = "nlg_en_output.json"
, pgfFilename = "Lam4.pgf"
, concreteSyntaxName = "Lam4Eng"
}

--------------------
-- CLI Options
--------------------

-- TODO: Think about exposing a tracing option?
data Options =
MkOptions
Expand Down Expand Up @@ -95,6 +114,32 @@ optionsConfig =
<> header "Lam4 (an experimental variant of the L4 legal DSL)"
)

-- | Load output configs from environment variables if .env present; use default configs if not
loadConfigsFromEnv :: IO OutputConfig
loadConfigsFromEnv = do
-- Try to load .env file, warn if not found
_ <- onMissingFile
(loadFile defaultConfig)
(hPutStrLn stderr "Warning: .env file not found, using default configuration")

mSimalaOutDir <- getEnv "COMPILED_SIMALA_OUTPUT_DIR"
mNlgEnOutDir <- getEnv "NLG_EN_OUTPUT_DIR"
mGfPgfFilename <- getEnv "GF_PORTABLE_GRAMMAR_FORMAT_FILENAME"
mNlgOutFilename <- getEnv "NLG_EN_OUTPUT_FILENAME"

let simalaOutConfig = MkSimalaOutputConfig {
outputDir = fromMaybe defaultSimalaOutputConfig.outputDir mSimalaOutDir
, programFilename = defaultSimalaOutputConfig.programFilename -- TODO: move to .env in the future (and update the lsp client accordingly)
, programInfoFilename = defaultSimalaOutputConfig.programInfoFilename -- TODO: move to .env in the future (and update the lsp client accordingly)
}
nlgOutConfig = MkNLGConfig { outputDir = fromMaybe defaultNlgConfig.outputDir mNlgEnOutDir
, outputFilename = fromMaybe defaultNlgConfig.outputFilename mNlgOutFilename
, pgfFilename = fromMaybe defaultNlgConfig.pgfFilename mGfPgfFilename
, concreteSyntaxName = defaultNlgConfig.concreteSyntaxName -- TODO: Figure out a better way to handle this
}
pure $ MkOutputConfig { simalaOutputConfig = simalaOutConfig
, nlgOutputConfig = nlgOutConfig }

main :: IO ()
main = do
options <- Options.execParser optionsConfig
Expand All @@ -108,18 +153,23 @@ main = do
simalaProgram = ToSimala.compile conEvalProgram
programInfo = extractProgramInfo conEvalProgram

-- Load output configs
outConfig <- loadConfigsFromEnv
let simalaOutConfig = outConfig.simalaOutputConfig
nlgOutConfig = outConfig.nlgOutputConfig

-- Create output directory and write files first
createDirectoryIfMissing True simalaOutputConfig.outputDir
createDirectoryIfMissing True outConfig.simalaOutputConfig.outputDir
-- save simala program and program info to disk
writeFileUtf8 (simalaOutputConfig.outputDir </> simalaOutputConfig.programFilename) (ToSimala.render simalaProgram)
writeFileLBS (simalaOutputConfig.outputDir </> simalaOutputConfig.programInfoFilename) (encodePretty programInfo)
writeFileUtf8 (simalaOutConfig.outputDir </> simalaOutConfig.programFilename) (ToSimala.render simalaProgram)
writeFileLBS (simalaOutConfig.outputDir </> simalaOutConfig.programInfoFilename) (encodePretty programInfo)

-- NLG (put this behind an option later)
-- TODO: Make a ToNLG monad
nlgEnv <- Render.makeNLGEnv nlgConfig
let nlRendering = Render.renderCstProgramToNL nlgEnv cstProgram
createDirectoryIfMissing True nlgConfig.outputDir
writeFileUtf8 (nlgConfig.outputDir </> nlgConfig.resultFilename) nlRendering
nlgEnv <- Render.makeNLGEnv nlgOutConfig
let nlRendering = Render.renderCstProgramToNL nlgEnv cstProgram
createDirectoryIfMissing True nlgOutConfig.outputDir
writeFileUtf8 (nlgOutConfig.outputDir </> nlgOutConfig.outputFilename) nlRendering
-- TODO: Save a json version with the nlg output as a member

-- Perform evaluation (if needed)
Expand Down
1 change: 1 addition & 0 deletions lam4-cli/lam4-cli.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ executable lam4-cli
, filepath
, bytestring
, lens-regex-pcre
, dotenv

hs-source-dirs: app
default-language: GHC2021

0 comments on commit 99959e5

Please # to comment.