Skip to content

Commit

Permalink
Use top-to-bottom macro expansion, a la Clojure + prepare for Hackage
Browse files Browse the repository at this point in the history
publishing

Haskell (usually) doesn't care about the order in which things are defined, but keeping this guarantee in the presence of macros has turned out to be very difficult (if realistically feasible at all). Because macros can be defined by other macros, the AST would need to be re-expanded and re-expanded, and some edge cases were very nontrivial. So, we're following in Clojure's footsteps, which has solved the problem by enforcing top-to-bottom expansion (note that non-macro-involved functions can be defined wherever and are not subject to this restriction).
  • Loading branch information
jgrosso committed Aug 15, 2018
1 parent 2139e9b commit d6dfc47
Show file tree
Hide file tree
Showing 21 changed files with 320 additions and 444 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ cabal.project.local
axelTemp
resources/autogenerated/*
resources/new-project-template/**/*.hs
AUTOGENERATED*

flycheck_*.hs

ctags
TAGS
TAGS
106 changes: 79 additions & 27 deletions axel.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
--
-- see: https://github.com/sol/hpack
--
-- hash: 8d0ab6a7586d20892da1b6d2e8108404859096bc5719a7f3a8e30ebb8d4c4cf1
-- hash: 2c4cdd0178ad6519fe8100252b72565fbc261a394456c96838bcb397d9a9463d

name: axel
version: 0.1.0.0
category: Lisp, Transpiler
homepage: https://github.com/jgrosso/axel#readme
bug-reports: https://github.com/jgrosso/axel/issues
version: 0.0.2
synopsis: The Axel programming language.
description: Haskell's semantics, plus Lisp's macros. Meet Axel – a purely functional, extensible, and powerful programming language.
category: Language, Lisp, Macros, Transpiler
homepage: https://github.com/axellang/axel#readme
bug-reports: https://github.com/axellang/axel/issues
author: Joshua Grosso
maintainer: [email protected]
copyright: 2017 Joshua Grosso
Expand All @@ -17,9 +19,72 @@ license-file: LICENSE
build-type: Simple
cabal-version: >= 1.10
extra-source-files:
examples/axelTemp/Axel.hs
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/autogen/Paths_do.dump-hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/autogen/cabal_macros.h
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/autogen/Paths_do.hs
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/autogen/cabal_macros.h
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/autogen/Paths_do.hs
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/do-exe
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/do-exe-tmp/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/autogen/Paths_do.dump-hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/do-exe-tmp/app/Main.dump-hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/do-exe-tmp/Main.hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/do-exe-tmp/Main.o
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/do-exe-tmp/Paths_do.hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/do-exe/do-exe-tmp/Paths_do.o
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/Lib.dyn_hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/Lib.dyn_o
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/Lib.hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/Lib.o
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/libHSdo-0.1.0.0-84i3CClUbe35xQ9SiCfZTm-ghc8.4.3.dylib
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/libHSdo-0.1.0.0-84i3CClUbe35xQ9SiCfZTm.a
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/Paths_do.dyn_hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/Paths_do.dyn_o
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/Paths_do.hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/Paths_do.o
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/build/src/Lib.dump-hi
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/package.conf.inplace/package.cache
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/package.conf.inplace/package.cache.lock
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/setup-config
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/stack-build-caches/exe-do-exe
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/stack-build-caches/lib
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/stack-build-caches/test-do-test
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/stack-cabal-mod
examples/do/.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/stack-config-cache
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/bin/do-exe
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/doc/do-0.1.0.0/LICENSE
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/flag-cache/do-0.1.0.0
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/flag-cache/do-0.1.0.0-84i3CClUbe35xQ9SiCfZTm
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/lib/x86_64-osx-ghc-8.4.3/do-0.1.0.0-84i3CClUbe35xQ9SiCfZTm/Lib.dyn_hi
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/lib/x86_64-osx-ghc-8.4.3/do-0.1.0.0-84i3CClUbe35xQ9SiCfZTm/Lib.hi
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/lib/x86_64-osx-ghc-8.4.3/do-0.1.0.0-84i3CClUbe35xQ9SiCfZTm/libHSdo-0.1.0.0-84i3CClUbe35xQ9SiCfZTm.a
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/lib/x86_64-osx-ghc-8.4.3/do-0.1.0.0-84i3CClUbe35xQ9SiCfZTm/Paths_do.dyn_hi
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/lib/x86_64-osx-ghc-8.4.3/do-0.1.0.0-84i3CClUbe35xQ9SiCfZTm/Paths_do.hi
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/lib/x86_64-osx-ghc-8.4.3/libHSdo-0.1.0.0-84i3CClUbe35xQ9SiCfZTm-ghc8.4.3.dylib
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/pkgdb/package.cache
examples/do/.stack-work/install/x86_64-osx/lts-12.0/8.4.3/pkgdb/package.cache.lock
examples/do/.stack-work/intero/interokbXBrc-TEMP.hs
examples/do/.stack-work/intero/interoMkMX0r-TEMP.hs
examples/do/app/Main.axel
examples/do/app/Main.hs
examples/do/cabal.project.local
examples/do/dist-newstyle/cache/compiler
examples/do/dist-newstyle/cache/config
examples/do/dist-newstyle/cache/elaborated-plan
examples/do/dist-newstyle/cache/improved-plan
examples/do/dist-newstyle/cache/plan.json
examples/do/dist-newstyle/cache/solver-plan
examples/do/dist-newstyle/cache/source-hashes
examples/do/do.cabal
examples/do/package.yaml
examples/do/Setup.axel
examples/do/Setup.hs
examples/do/stack.yaml
examples/example.axel
README.org
scripts/build.sh
scripts/clean.sh
scripts/ghcid.sh
scripts/lint.sh
data-files:
resources/autogenerated/macros/AST.hs
Expand All @@ -36,7 +101,7 @@ data-files:

source-repository head
type: git
location: https://github.com/jgrosso/axel
location: https://github.com/axellang/axel

library
exposed-modules:
Expand All @@ -53,6 +118,7 @@ library
Axel.Parse
Axel.Parse.AST
Axel.Quote
Axel.Utils.Debug
Axel.Utils.Directory
Axel.Utils.Display
Axel.Utils.Function
Expand All @@ -63,16 +129,13 @@ library
Paths_axel
hs-source-dirs:
src
ghc-options: -Wall -Werror -Wmissing-import-lists -Wincomplete-record-updates -Wincomplete-uni-patterns
ghc-options: -Wall -Wmissing-import-lists -Wincomplete-record-updates -Wincomplete-uni-patterns
build-depends:
aeson >=1.3.1 && <1.4
, base >=4.11.1 && <4.12
, bytestring >=0.10.8 && <0.11
base >=4.11.1 && <4.12
, directory >=1.3 && <1.4
, filepath >=1.4.1 && <1.5
, ghc ==8.4.3
, haskell-src-exts >=1.20.2 && <1.21
, lens >=4.16.1 && <4.17
, lens >=4.16.1 && <4.18
, lens-aeson >=1.0.2 && <1.1
, monad-control >=1.0.2 && <1.1
, mtl >=2.2.1 && <2.3
, parsec >=3.1.11 && <3.2
Expand All @@ -82,6 +145,8 @@ library
, strict >=0.3.2 && <0.4
, text >=1.2.2 && <1.3
, typed-process >=0.2.2 && <0.3
, vector >=0.12.0 && <0.13
, yaml >=0.8.31 && <0.10
default-language: Haskell2010

executable axel-exe
Expand All @@ -90,22 +155,9 @@ executable axel-exe
Paths_axel
hs-source-dirs:
app
ghc-options: -Wall -Werror -Wmissing-import-lists -Wincomplete-record-updates -Wincomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N
ghc-options: -Wall -Wmissing-import-lists -Wincomplete-record-updates -Wincomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N
build-depends:
axel
, base >=4.11.1 && <4.12
, directory >=1.3 && <1.4
default-language: Haskell2010

test-suite axel-test
type: exitcode-stdio-1.0
main-is: Axel/Spec.hs
other-modules:
Paths_axel
hs-source-dirs:
test
ghc-options: -Wall -Werror -Wmissing-import-lists -Wincomplete-record-updates -Wincomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N
build-depends:
base >=4.11.1 && <4.12
, hspec
default-language: Haskell2010
3 changes: 3 additions & 0 deletions examples/do/Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Distribution.Simple(defaultMain)
main :: (IO ())
main = defaultMain
12 changes: 7 additions & 5 deletions examples/do/app/Main.axel
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
(module Main)

(defmacro fnCase
((cases) (<$> (fn (varId)
[`(fn (~varId)
(case ~varId ~@cases))])
AST.gensym)))
(importq Axel.Parse.AST AST all)

(defmacro quasiquote
(([(AST.SExpression xs)])
Expand All @@ -20,6 +16,12 @@
(pure [(AST.SExpression ['AST.SExpression (AST.SExpression ['concat (AST.SExpression (: 'list (map quasiquoteElem xs)))])])])))
(([atom]) (pure [(AST.SExpression ['quote atom])])))

(defmacro fnCase
((cases) (<$> (fn (varId)
[`(fn (~varId)
(case ~varId ~@cases))])
AST.gensym)))

(= do' (-> ([] AST.Expression) AST.Expression)
(() (fnCase
((: var (: '<- (: val rest)))
Expand Down
5 changes: 5 additions & 0 deletions examples/do/app/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Axel.Parse.AST as AST
do' :: ((->) ([] AST.Expression) AST.Expression)
do' = (\aXEL_AUTOGENERATED_IDENTIFIER_0 -> (case aXEL_AUTOGENERATED_IDENTIFIER_0 of {((:) var ((:) (AST.Symbol "<-") ((:) val rest))) -> (AST.SExpression (concat [[(AST.Symbol ">>=")],[val],[(AST.SExpression (concat [[(AST.Symbol "fn")],[(AST.SExpression (concat [[var]]))],[(do' rest)]]))]]));((:) val rest) -> (case rest of {[] -> val;_ -> (AST.SExpression (concat [[(AST.Symbol ">>")],[val],[(do' rest)]]))})}))
main :: (IO ())
main = ((>>=) getLine (\line -> ((>>) (putStrLn line) (pure ()))))
5 changes: 3 additions & 2 deletions examples/do/do.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
--
-- see: https://github.com/sol/hpack
--
-- hash: 0037b02c438ca0e266b36bbc6819c4f7b82001900b25cff6b073210c41d253bd
-- hash: 6b2dec4e676f630059031c7d0886c3e3660d816e93a55f828cc7d946af54cbb2

name: do
version: 0.1.0.0
Expand Down Expand Up @@ -31,5 +31,6 @@ executable do-exe
app
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
base >=4.7 && <5
axel ==0.0.1
, base >=4.7 && <5
default-language: Haskell2010
34 changes: 12 additions & 22 deletions examples/do/package.yaml
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
name: do
version: 0.1.0.0
github: "githubuser/do"
license: BSD3
author: "Author name here"
maintainer: "[email protected]"
copyright: "2018 Author name here"

copyright: 2018 Author name here
maintainer: [email protected]
dependencies:
- base >= 4.7 && < 5
name: do
version: '0.1.0.0'
extra-source-files:
- README.md
- ChangeLog.md
# Metadata used when publishing your package
# synopsis: Short description of your package
# category: Web

# To avoid duplicated efforts in documentation and dealing with the
# complications of embedding Haddock markup inside cabal files, it is
# common to point users to the README.md file.
description: Please see the README on GitHub at <https://github.com/githubuser/do#readme>

dependencies:
- base >= 4.7 && < 5

author: Author name here
github: githubuser/do
license: BSD3
executables:
do-exe:
main: Main.hs
source-dirs: app
source-dirs: app
main: Main.hs
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies: []
description: Please see the README on GitHub at <https://github.com/githubuser/do#readme>
29 changes: 10 additions & 19 deletions package.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
name: axel
version: '0.1.0.0'
category: Lisp, Transpiler
version: '0.0.2'
category: Language, Lisp, Macros, Transpiler
author: Joshua Grosso
maintainer: [email protected]
copyright: 2017 Joshua Grosso
license: BSD3
github: jgrosso/axel
github: axellang/axel
synopsis: The Axel programming language.
description: Haskell's semantics, plus Lisp's macros. Meet Axel – a purely functional, extensible, and powerful programming language.
extra-source-files:
- README.org
- examples/**/*
- scripts/**/*
ghc-options:
- -Wall
- -Werror
- -Wmissing-import-lists
- -Wincomplete-record-updates
- -Wincomplete-uni-patterns
Expand All @@ -24,13 +26,10 @@ library:
exposed-modules:
- Axel.Project
dependencies:
- aeson >=1.3.1 && <1.4
- bytestring >=0.10.8 && <0.11
- directory >=1.3 && <1.4
- filepath >=1.4.1 && <1.5
- ghc ==8.4.3
- haskell-src-exts >=1.20.2 && <1.21
- lens >=4.16.1 && <4.17
- lens >=4.16.1 && <4.18
- lens-aeson >=1.0.2 && <1.1
- monad-control >=1.0.2 && <1.1
- mtl >=2.2.1 && <2.3
- parsec >=3.1.11 && <3.2
Expand All @@ -40,6 +39,8 @@ library:
- strict >=0.3.2 && <0.4
- text >=1.2.2 && <1.3
- typed-process >=0.2.2 && <0.3
- vector >=0.12.0 && <0.13
- yaml >=0.8.31 && <0.10
executables:
axel-exe:
main: Main.hs
Expand All @@ -51,13 +52,3 @@ executables:
dependencies:
- axel
- directory >=1.3 && <1.4
tests:
axel-test:
main: Axel/Spec.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- hspec
1 change: 1 addition & 0 deletions scripts/ghcid.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ghcid -c "stack ghci axel"
16 changes: 9 additions & 7 deletions src/Axel/AST.hs
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,15 @@ instance ToHaskell Import where
toHaskell (ImportType typeName imports) =
typeName <> surround Parentheses (delimit Commas imports)

newtype ImportList =
ImportList [Import]
data ImportSpecification
= ImportAll
| ImportOnly [Import]
deriving (Eq)

instance ToHaskell ImportList where
toHaskell :: ImportList -> String
toHaskell (ImportList importList) =
instance ToHaskell ImportSpecification where
toHaskell :: ImportSpecification -> String
toHaskell ImportAll = ""
toHaskell (ImportOnly importList) =
surround Parentheses $ delimit Commas $ map toHaskell importList

data Lambda = Lambda
Expand All @@ -123,12 +125,12 @@ data MacroDefinition = MacroDefinition
data QualifiedImport = QualifiedImport
{ _moduleName :: Identifier
, _alias :: Identifier
, _imports :: ImportList
, _imports :: ImportSpecification
} deriving (Eq)

data RestrictedImport = RestrictedImport
{ _moduleName :: Identifier
, _imports :: ImportList
, _imports :: ImportSpecification
} deriving (Eq)

data TypeclassInstance = TypeclassInstance
Expand Down
Loading

0 comments on commit d6dfc47

Please sign in to comment.