Skip to content

Commit 928a5e9

Browse files
committed
Initial commit
0 parents  commit 928a5e9

File tree

6 files changed

+410
-0
lines changed

6 files changed

+410
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
_build
2+
dist
3+
dist-newstyle
4+
*~

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Minimal skeleton for developing a new Agda backend
2+
3+
- The backend is defined in `src/Main.hs`.
4+
- The `test/` directory contains an example compilation of `Test.agda` to `Test.txt`.

agda2min.cabal

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
cabal-version: 2.2
2+
name: agda2min
3+
version: 1.1
4+
author: ???
5+
category: Language, Compiler
6+
build-type: Simple
7+
synopsis: Compiling Agda code to ??.
8+
9+
extra-doc-files: README.md
10+
11+
source-repository head
12+
type: git
13+
location: https://github.com/omelkonian/agda-minimal-backend.git
14+
15+
executable agda2min
16+
hs-source-dirs: src
17+
main-is: Main.hs
18+
other-modules: Paths_agda2min
19+
autogen-modules: Paths_agda2min
20+
build-depends: base >= 4.10 && < 4.18,
21+
Agda >= 2.6.4 && < 2.6.5,
22+
deepseq >= 1.4.4 && < 1.6

src/Main.hs

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
{-# LANGUAGE LambdaCase, RecordWildCards #-}
2+
module Main where
3+
4+
import Data.Maybe ( fromMaybe )
5+
import Control.Monad ( unless )
6+
import Control.Monad.IO.Class ( MonadIO(liftIO) )
7+
import Control.DeepSeq ( NFData(..) )
8+
9+
import System.Console.GetOpt ( OptDescr(Option), ArgDescr(ReqArg) )
10+
11+
import Data.Version ( showVersion )
12+
import Paths_agda2min ( version )
13+
14+
import Agda.Syntax.Common.Pretty ( prettyShow )
15+
import Agda.Syntax.Internal ( qnameName, qnameModule )
16+
import Agda.Syntax.TopLevelModuleName ( TopLevelModuleName, moduleNameToFileName )
17+
18+
import Agda.Compiler.Common ( curIF, compileDir )
19+
import Agda.Compiler.Backend ( Backend(..), Backend'(..), Recompile(..), IsMain )
20+
21+
import Agda.TypeChecking.Monad.Base ( Definition(..) )
22+
import Agda.TypeChecking.Monad
23+
( TCM, withCurrentModule, iInsideScope, setScope
24+
, CompilerPragma(..), getUniqueCompilerPragma )
25+
26+
import Agda.Main ( runAgda )
27+
28+
main = runAgda [Backend backend]
29+
30+
data Options = Options { optOutDir :: Maybe FilePath }
31+
32+
instance NFData Options where
33+
rnf _ = ()
34+
35+
outdirOpt :: Monad m => FilePath -> Options -> m Options
36+
outdirOpt dir opts = return opts{ optOutDir = Just dir }
37+
38+
defaultOptions :: Options
39+
defaultOptions = Options{ optOutDir = Nothing }
40+
41+
type ModuleEnv = ()
42+
type ModuleRes = ()
43+
type CompiledDef = String
44+
45+
backend :: Backend' Options Options ModuleEnv ModuleRes CompiledDef
46+
backend = Backend'
47+
{ backendName = "agda2??"
48+
, backendVersion = Just (showVersion version)
49+
, options = defaultOptions
50+
, commandLineFlags =
51+
[ Option ['o'] ["out-dir"] (ReqArg outdirOpt "DIR")
52+
"Write output files to DIR. (default: project root)"
53+
]
54+
, isEnabled = \ _ -> True
55+
, preCompile = return
56+
, postCompile = \ _ _ _ -> return ()
57+
, preModule = moduleSetup
58+
, postModule = writeModule
59+
, compileDef = compile
60+
, scopeCheckingSuffices = False
61+
, mayEraseType = \ _ -> return True
62+
}
63+
64+
moduleSetup :: Options -> IsMain -> TopLevelModuleName -> Maybe FilePath
65+
-> TCM (Recompile ModuleEnv ModuleRes)
66+
moduleSetup _ _ m _ = do
67+
setScope . iInsideScope =<< curIF
68+
return $ Recompile ()
69+
70+
compile :: Options -> ModuleEnv -> IsMain -> Definition -> TCM CompiledDef
71+
compile opts tlm _ Defn{..}
72+
= withCurrentModule (qnameModule defName)
73+
$ getUniqueCompilerPragma "AGDA2??" defName >>= \case
74+
Nothing -> return []
75+
Just (CompilerPragma _ _) ->
76+
return $ prettyShow (qnameName defName) <> " = " <> prettyShow theDef
77+
78+
writeModule :: Options -> ModuleEnv -> IsMain -> TopLevelModuleName -> [CompiledDef]
79+
-> TCM ModuleRes
80+
writeModule opts _ _ m cdefs = do
81+
outDir <- compileDir
82+
liftIO $ putStrLn (moduleNameToFileName m "txt")
83+
let outFile = fromMaybe outDir (optOutDir opts) <> "/" <> moduleNameToFileName m "txt"
84+
unless (all null cdefs) $ liftIO
85+
$ writeFile outFile
86+
$ "*** module " <> prettyShow m <> " ***\n" <> unlines cdefs

test/Test.agda

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
module _ where
2+
3+
open import Agda.Builtin.Nat using (Nat; _+_; _*_)
4+
open import Agda.Builtin.List using (List; []; _∷_)
5+
6+
variable a b : Set
7+
8+
-- ** Datatypes & functions
9+
10+
data Exp (v : Set) : Set where
11+
Plus : Exp v Exp v Exp v
12+
Int : Nat Exp v
13+
Var : v Exp v
14+
{-# COMPILE AGDA2?? Exp #-}
15+
16+
eval : (a Nat) Exp a Nat
17+
eval env (Plus a b) = eval env a + eval env b
18+
eval env (Int n) = n
19+
eval env (Var x) = env x
20+
{-# COMPILE AGDA2?? eval #-}
21+
22+
-- ** Natural numbers
23+
24+
sum : List Nat Nat
25+
sum [] = 0
26+
sum (x ∷ xs) = x + sum xs
27+
{-# COMPILE AGDA2?? sum #-}
28+
29+
-- ** Polymorphic functions
30+
31+
_++_ : List a List a List a
32+
[] ++ ys = ys
33+
(x ∷ xs) ++ ys = x ∷ (xs ++ ys)
34+
{-# COMPILE AGDA2?? _++_ #-}
35+
36+
map : (a b) List a List b
37+
map f [] = []
38+
map f (x ∷ xs) = f x ∷ map f xs
39+
{-# COMPILE AGDA2?? map #-}
40+
41+
-- ** Lambdas
42+
43+
plus3 : List Nat List Nat
44+
plus3 = map (λ n n + 3)
45+
{-# COMPILE AGDA2?? plus3 #-}
46+
47+
doubleLambda : Nat Nat Nat
48+
doubleLambda = λ a b a + 2 * b
49+
{-# COMPILE AGDA2?? doubleLambda #-}

0 commit comments

Comments
 (0)