Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add renamer phase and a simala backend for natural4 #609

Merged
merged 46 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d57e621
Add file structure
fendor Jul 16, 2024
c0d2a41
WIP: simala backend
fendor Jul 18, 2024
7dc7fcb
Fix renamer of MultiTerms. Allow Strings and improve object path rena…
fendor Aug 6, 2024
51b247f
Fix transpiler for attributes with conditionals
fendor Aug 6, 2024
c33aa9c
Renamer cleanup of imports and traces
fendor Aug 6, 2024
dc57d8d
Add support for quotes for string literals
fendor Aug 6, 2024
8180280
Simplify and improve variable / attribute assignment
fendor Aug 6, 2024
cbf4095
Unify attribute assignment codepath in the Renamer
fendor Aug 7, 2024
80609eb
Remove debugger helpers for the renamer
fendor Aug 7, 2024
91767c7
Move debugging code around
fendor Aug 7, 2024
71c2348
Prefer concrete monad stack
fendor Aug 7, 2024
bfe46f8
Add initial testsuite for Simala transpilation
fendor Aug 7, 2024
00b9622
Comments and small modifications in renamer.
kosmikus Aug 7, 2024
4f0a296
Add TypeDecl renaming phase
fendor Aug 8, 2024
2141b74
Add Trie implementation to implement lexical scope checking
fendor Aug 9, 2024
cf5e14d
Implement better lexical scoping
fendor Aug 9, 2024
6042cdc
Update Simala Spec tests
fendor Aug 9, 2024
5452c9a
Implement full renaming pipeline for list of rules
fendor Aug 9, 2024
ef26ec5
Introduce Transpiler monad
fendor Aug 9, 2024
609189f
Comments / discussion / refactoring.
kosmikus Aug 12, 2024
6102fbd
Implement lexical scoping rules for Renamer
fendor Aug 12, 2024
0404c28
Clean up renamer and simala functions
fendor Aug 12, 2024
3341af0
Fix function arity checks
fendor Aug 12, 2024
6c2dc39
Fix test indentation
fendor Aug 13, 2024
4922677
Add Simala transpiler backend
fendor Aug 13, 2024
b7dd0bb
Add more documentation to simala
fendor Aug 13, 2024
3c9f879
Emit Simala Decls
fendor Aug 13, 2024
51d489e
Cleanup incidental changes
fendor Aug 13, 2024
69c88fd
Add typed errors to renamer phase
fendor Aug 13, 2024
f638221
Add typed errors to simala transpilation phase
fendor Aug 13, 2024
d066b33
Merge branch 'fix/pull-interpreted-into-module' into HEAD
fendor Aug 14, 2024
d5025c0
WIP, add simala to main cli
fendor Aug 14, 2024
d6b0b54
Add Simala transpiler backend to main-cli
fendor Aug 14, 2024
5e2786a
Introduce co-log style logging for Renamer phase
fendor Aug 19, 2024
82a5694
Fix hie.yaml file
fendor Aug 19, 2024
703ae62
Fix doctests
fendor Aug 20, 2024
2a49fba
Remove unused modules
fendor Aug 20, 2024
c9df3b0
Merge remote-tracking branch 'origin/main' into fendor/backend/simala
fendor Aug 20, 2024
5d0b368
Split up the Renamer module into submodules
fendor Aug 22, 2024
f1efe65
Handle builtins separately from variables
fendor Aug 22, 2024
0c59ebd
Support more naturalL4 and honour name shadowing
fendor Aug 22, 2024
e2bbb1f
Fixup comment
fendor Aug 23, 2024
572e9f8
Add more docs and improve Scope API
fendor Aug 23, 2024
0a3e90a
Remove unused module
fendor Aug 23, 2024
664fb86
Bump simala commit
fendor Aug 23, 2024
2242010
Remove unused language extensions
fendor Aug 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/haskell/cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ source-repository-package
location: https://github.com/anka-213/haskell-wordnet
tag: a6d675bcbe1585fc652f95f60e0dec826a660646

source-repository-package
type: git
location: https://github.com/smucclaw/simala
tag: 85afeb86678a65d48bfac2bbb90306693d51582e

allow-newer:
compact:*,
udpipe-hs:base,
Expand Down
24 changes: 23 additions & 1 deletion lib/haskell/natural4/app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ import LS.XPile.Petri (toPetri)
import LS.XPile.Prolog (rulesToProlog, rulesToSCasp)
import LS.XPile.Purescript (translate2PS)
import LS.XPile.SVG qualified as AAS
import LS.XPile.Simala.Transpile qualified as Simala
import LS.XPile.Typescript (asTypescript)
import LS.XPile.Uppaal qualified as Uppaal
import LS.XPile.VueJSON
Expand Down Expand Up @@ -123,6 +124,8 @@ import System.IO.Unsafe (unsafeInterleaveIO)
import Text.Pretty.Simple (pPrint, pShowNoColor)
import Text.Regex.PCRE.Heavy qualified as PCRE
import Text.XML.HXT.Core qualified as HXT
import qualified LS.Renamer as Renamer
import LS.Renamer.Rules (RnRule)

--
-- Command-line options parsing
Expand Down Expand Up @@ -275,7 +278,7 @@ main = do
rc <- SFL4.getConfig opts
-- putStrLn "main: doing dumpRules"
rules <- SFL4.dumpRules opts
let l4i = l4interpret rules
l4i <- l4interpret rules
iso8601 <- now8601

-- NLG stuff
Expand Down Expand Up @@ -550,6 +553,10 @@ transpilersMap =
, "an anyall SVG of the decision trees"
, [aasvgTranspiler]
)
, ( SFL4.simalaMode
, "Transpile hornlike rules to the purely functional Simala language"
, [simalaTranspiler]
)
]

toNative :: [SFL4.Rule] -> SFL4.Interpreted -> String
Expand Down Expand Up @@ -652,6 +659,13 @@ withNLGData k ds =
Nothing -> pure (Skipped "skipping transpiler due to lacking NLG environment")
Just env -> k env ds

withRnRules :: ([RnRule] -> (TranspilationResult a)) -> DriverState -> (TranspilationResult a)
withRnRules k ds = case ds.interpreted.renamedRules of
Renamer.RenamerFail errMsg _scope -> Skipped $ "Failed to rename rules: " <> errorToString errMsg
Renamer.RenamerSuccess rnRules _scope -> k rnRules
where
errorToString = Text.unpack . Renamer.renderRenamerError

simpleTranspiler ::
FilePath
-> String
Expand Down Expand Up @@ -1109,6 +1123,14 @@ aasvgTranspiler =
Nothing ->
pure () -- no on-screen output

simalaTranspiler :: Transpiler
simalaTranspiler =
simpleTranspiler "simala" "simala" (withRnRules runSimalaTranspiler)
where
runSimalaTranspiler rnRules = case Simala.runSimalaTranspiler rnRules of
Left err -> mkResultWithErrors ("", lines $ Text.unpack $ Simala.renderTranspilerError err)
Right decls -> mkResultWithoutErrors (Text.unpack $ Simala.render decls)

rulesTranspiler :: Transpiler
rulesTranspiler =
screenTranspiler "rules" (withoutErrors (onlyRules id))
Expand Down
20 changes: 20 additions & 0 deletions lib/haskell/natural4/natural4.cabal

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions lib/haskell/natural4/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ description: natural4 parses a Legal Spreadsheet's CSV and transpiles to multipl
dependencies:
- base >= 4.7 && < 5
- containers
- co-log-core
- unordered-containers
- hashable
- flow
Expand Down Expand Up @@ -95,6 +96,8 @@ dependencies:
# - holmes
# Note: when adding `extra-deps` in `stack.yaml`, have to add them under the relevant package in `package.yaml` too
# See https://docs.haskellstack.org/en/stable/stack_yaml_vs_cabal_package_file/#why-specify-dependencies-twice
# Dependencies specific to the WIP simala backend
- simala

language: GHC2021

Expand Down
33 changes: 20 additions & 13 deletions lib/haskell/natural4/src/LS/Interpreter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ import LS.RelationalPredicates
getBSR,
partitionExistentials,
)
import LS.Renamer.Rules (RnRule)
import qualified LS.Renamer as Renamer
import qualified LS.Renamer.Scope as Scope
import LS.Rule
( Rule
( DefTypically,
Expand Down Expand Up @@ -216,7 +219,6 @@ import LS.XPile.Logging
import Text.Pretty.Simple (pShowNoColor)
import Text.Regex.PCRE.Heavy qualified as PCRE


-- | This is generated by the Interpreter and handed around to different transpilers.
--
-- In the future we may add to this list of attributes the following frequently called functions:
Expand All @@ -242,6 +244,8 @@ data Interpreted = L4I {
-- eliminated. [TODO].
, origrules :: [Rule]

, renamedRules :: Renamer.RenamerResult [RnRule]

-- | valuepredicates contain the bulk of the top-level decision logic, and can be easily expressed as instance or class methosd.
, valuePreds :: [ValuePredicate]

Expand All @@ -257,6 +261,7 @@ defaultL4I = L4I
{ classtable = CT Map.empty
, scopetable = Map.empty
, origrules = mempty
, renamedRules = Renamer.RenamerSuccess mempty Scope.emptyScope
, valuePreds = mempty
, ruleGraph = Gr.empty
, ruleGraphErr = mempty
Expand All @@ -280,22 +285,24 @@ type RuleGraph = Gr Rule RuleGraphEdgeLabel
-- handed to each transpiler for use, as an `l4i` argument.
--

l4interpret :: [Rule] -> Interpreted
l4interpret rs =
l4interpret :: [Rule] -> IO Interpreted
l4interpret rs = do
let ct :: ClsTab
ct = classHierarchy rs
st :: ScopeTabs
st = symbolTable rs
(vp, _vpErr) = xpLog $ attrsAsMethods rs
(rDGout, rDGerr) = xpLog $ ruleDecisionGraph rs
in
L4I { classtable = ct
, scopetable = st
, origrules = rs
, valuePreds = fromRight [] vp
, ruleGraph = rDGout
, ruleGraphErr = rDGerr
}
rnRules <- Renamer.runRenamerFor mempty rs

pure L4I { classtable = ct
, scopetable = st
, origrules = rs
, renamedRules = rnRules
, valuePreds = fromRight [] vp
, ruleGraph = rDGout
, ruleGraphErr = rDGerr
}

-- | Provide the fully expanded, exposed, decision roots of all rules in the ruleset,
-- grouped ("nubbed") into rule groups (since multiple rules may have the same decision body).
Expand Down Expand Up @@ -1151,7 +1158,7 @@ globalFacts l4i = do
pure $ Node pt []
}

-- * Extract everything that looks like a method.
-- | Extract everything that looks like a method.
--
-- A common form is:
-- @
Expand All @@ -1166,7 +1173,7 @@ globalFacts l4i = do
-- [([ClassA, RecordAttr, AttributeName], foo, Just bar
-- @
--
-- | we extract the methods to a fully qualified and annotatable form defined as `ValuePredicate` -- see Types.hs
-- we extract the methods to a fully qualified and annotatable form defined as `ValuePredicate` -- see Types.hs
--
-- Go through every rule and break it down into this structure.

Expand Down
5 changes: 5 additions & 0 deletions lib/haskell/natural4/src/LS/Lib.hs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ module LS.Lib
vueMode,
pursMode,
uppaalMode,
simalaMode,
defaultModes,
knownModes
)
Expand Down Expand Up @@ -419,6 +420,7 @@ defaultModes =
, mathlangmwMode
, genmathlangMode
, introMode
, simalaMode
]

-- | All known modes, including ones that are off by default.
Expand Down Expand Up @@ -547,6 +549,9 @@ genmathlangMode = MkModeName "genmathlang"
introMode :: ModeName
introMode = MkModeName "intro"

simalaMode :: ModeName
simalaMode = MkModeName "simala"

getConfig :: Options -> IO RunConfig
getConfig o = do
mpd <- lookupEnv "MP_DEBUG"
Expand Down
43 changes: 43 additions & 0 deletions lib/haskell/natural4/src/LS/Log.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module LS.Log (
-- * Logger Type and utility functions
Tracer (..),
traceWith,
cmap,
module CoFunctor,

-- * Experimental logger backends
prettyTracer,
)
where

import Data.Functor.Contravariant as CoFunctor
import Prettyprinter
import Prettyprinter.Render.Text (renderStrict)
import System.IO (stderr)
import qualified Data.Text.IO as Text

newtype Tracer m a = Tracer {runTracer :: a -> m ()}

instance Contravariant (Tracer m) where
contramap f (Tracer m) = Tracer (m . f)

instance (Applicative m) => Semigroup (Tracer m a) where
tracer1 <> tracer2 = Tracer $ \a -> runTracer tracer1 a *> runTracer tracer2 a

instance (Applicative m) => Monoid (Tracer m a) where
mempty = Tracer $ \_ -> pure ()

traceWith :: Tracer m a -> a -> m ()
traceWith tracer msg = runTracer tracer msg

-- | Shorter name for 'contramap' specialised to
cmap :: forall a' a m. (a' -> a) -> Tracer m a -> Tracer m a'
cmap = contramap

prettyTracer :: (Pretty a) => Tracer IO a
prettyTracer =
Tracer $
Text.hPutStrLn stderr
. renderStrict
. layoutPretty defaultLayoutOptions
. pretty
Loading