Skip to content

Commit 100d787

Browse files
committed
Initial add
1 parent 291a6d4 commit 100d787

File tree

20 files changed

+1549
-0
lines changed

20 files changed

+1549
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ cabal-dev
44
*.hi
55
*.chi
66
*.chs.h
7+
*.lksh*
78
.virthualenv

PureScript.cabal

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Purescript
2+
version: 0.0.1
3+
cabal-version: >=1.2
4+
build-type: Simple
5+
license: MIT
6+
license-file: LICENSE
7+
copyright: (c) Phil Freeman 2013
8+
maintainer: Phil Freeman <paf31@cantab.net>
9+
stability: experimental
10+
synopsis: PureScript Programming Language Compiler
11+
description: A small compile-to-JS language with extensible records and type-safe blocks
12+
author: Phil Freeman <paf31@cantab.net>
13+
data-dir: ""
14+
15+
library
16+
build-depends: base -any, cmdtheline -any, containers -any,
17+
mtl -any, parsec -any, utf8-string -any
18+
exposed-modules: PureScript
19+
exposed: True
20+
buildable: True
21+
hs-source-dirs: src
22+
other-modules: Test Main PureScript.CodeGen PureScript.Kinds
23+
PureScript.Parser PureScript.TypeChecker PureScript.Types
24+
PureScript.Values PureScript.Parser.Common
25+
PureScript.Parser.Declarations PureScript.Parser.Types
26+
PureScript.Parser.Values PureScript.TypeChecker.Kinds
27+
PureScript.TypeChecker.Monad PureScript.TypeChecker.Types
28+
29+
executable psc
30+
build-depends: base -any, cmdtheline -any, containers -any,
31+
mtl -any, parsec -any, utf8-string -any
32+
main-is: Main.hs
33+
buildable: True
34+
hs-source-dirs: src
35+
other-modules: Test
36+

Setup.lhs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/runhaskell
2+
> module Main where
3+
> import Distribution.Simple
4+
> main :: IO ()
5+
> main = defaultMain
6+

src/Main.hs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
-----------------------------------------------------------------------------
2+
--
3+
-- Module : Main
4+
-- Copyright : (c) Phil Freeman 2013
5+
-- License : MIT
6+
--
7+
-- Maintainer : Phil Freeman <paf31@cantab.net>
8+
-- Stability : experimental
9+
-- Portability :
10+
--
11+
-- |
12+
--
13+
-----------------------------------------------------------------------------
14+
15+
module Main where
16+
17+
import PureScript
18+
import Text.Parsec
19+
import Data.Maybe (mapMaybe)
20+
import Data.List (intercalate)
21+
import System.Console.CmdTheLine
22+
import Control.Applicative
23+
import System.Exit (exitSuccess, exitFailure)
24+
import qualified System.IO.UTF8 as U
25+
26+
compile :: [FilePath] -> Maybe FilePath -> IO ()
27+
compile inputFiles outputFile = do
28+
input <- fmap concat $ mapM U.readFile inputFiles
29+
let ast = parse parseDeclarations "" input
30+
case ast of
31+
Left err -> do
32+
U.print err
33+
exitFailure
34+
Right decls -> do
35+
case check (typeCheckAll decls) of
36+
Left typeError -> do
37+
U.putStrLn typeError
38+
exitFailure
39+
Right _ -> do
40+
let js = intercalate "\n" $ mapMaybe declToJs decls
41+
case outputFile of
42+
Just path -> U.writeFile path js
43+
Nothing -> U.putStrLn js
44+
exitSuccess
45+
46+
inputFiles :: Term [FilePath]
47+
inputFiles = nonEmpty $ posAny [] $ posInfo
48+
{ posDoc = "The input .ps files" }
49+
50+
outputFile :: Term (Maybe FilePath)
51+
outputFile = value $ opt Nothing $ (optInfo [ "o", "output" ])
52+
{ optDoc = "The output .js file" }
53+
54+
term :: Term (IO ())
55+
term = compile <$> inputFiles <*> outputFile
56+
57+
termInfo :: TermInfo
58+
termInfo = defTI
59+
{ termName = "psc"
60+
, version = "1.0"
61+
, termDoc = "Compiles PureScript to Javascript"
62+
}
63+
64+
main = run (term, termInfo)

src/PureScript.hs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
-----------------------------------------------------------------------------
2+
--
3+
-- Module : PureScript
4+
-- Copyright : (c) Phil Freeman 2013
5+
-- License : MIT
6+
--
7+
-- Maintainer : Phil Freeman <paf31@cantab.net>
8+
-- Stability : experimental
9+
-- Portability :
10+
--
11+
-- |
12+
--
13+
-----------------------------------------------------------------------------
14+
15+
module PureScript (
16+
module PureScript.Values,
17+
module PureScript.Types,
18+
module PureScript.Kinds,
19+
module PureScript.Declarations,
20+
module PureScript.Parser,
21+
module PureScript.CodeGen,
22+
module PureScript.TypeChecker
23+
) where
24+
25+
import PureScript.Values
26+
import PureScript.Types
27+
import PureScript.Kinds
28+
import PureScript.Declarations
29+
import PureScript.Parser
30+
import PureScript.CodeGen
31+
import PureScript.TypeChecker

src/PureScript/CodeGen.hs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
-----------------------------------------------------------------------------
2+
--
3+
-- Module : PureScript.CodeGen
4+
-- Copyright : (c) Phil Freeman 2013
5+
-- License : MIT
6+
--
7+
-- Maintainer : Phil Freeman <paf31@cantab.net>
8+
-- Stability : experimental
9+
-- Portability :
10+
--
11+
-- |
12+
--
13+
-----------------------------------------------------------------------------
14+
15+
module PureScript.CodeGen (
16+
declToJs
17+
) where
18+
19+
import Data.List (nub, intersperse, intercalate)
20+
import PureScript.Values
21+
import PureScript.Declarations
22+
23+
declToJs :: Declaration -> Maybe String
24+
declToJs (ValueDeclaration name val) = Just $ "var " ++ name ++ " = " ++ valueToJs val ++ ";"
25+
declToJs (DataDeclaration dcs@(DataConstructors { dataConstructors = ctors })) =
26+
Just $ concatMap (\(ctor, _) -> "var " ++ ctor ++ " = function (value) { return { ctor: '" ++ ctor ++ "', value: value }; };") ctors
27+
declToJs _ = Nothing
28+
29+
valueToJs :: Value -> String
30+
valueToJs (NumericLiteral n) = show n
31+
valueToJs (StringLiteral s) = show s
32+
valueToJs (BooleanLiteral True) = "true"
33+
valueToJs (BooleanLiteral False) = "false"
34+
valueToJs (Unary op value) = unaryOperatorString op ++ "(" ++ valueToJs value ++ ")"
35+
valueToJs (Binary op left right) = "(" ++ valueToJs left ++ ") " ++ binaryOperatorString op ++ " (" ++ valueToJs right ++ ")"
36+
valueToJs (ArrayLiteral xs) = "[" ++ intercalate "," (map valueToJs xs) ++ "]"
37+
valueToJs (ObjectLiteral ps) = "{" ++ intercalate "," (map objectPropertyToJs ps) ++ "}"
38+
valueToJs (Accessor prop val) = "(" ++ valueToJs val ++ ")." ++ prop
39+
valueToJs (Abs args value) = "function (" ++ intercalate "," args ++ ") { return " ++ valueToJs value ++ "; }"
40+
valueToJs (Var ident) = ident
41+
valueToJs (App f xs) = "(" ++ valueToJs f ++ ") (" ++ intercalate "," (map valueToJs xs) ++ ")"
42+
valueToJs (Block sts) = "(function () {" ++ intercalate ";" (map statementToJs sts) ++ "})()"
43+
valueToJs (Constructor name) = name
44+
valueToJs (Case value binders) =
45+
"(function (_0) {"
46+
++ concatMap (\(b, val) -> fst $ binderToJs 0 0 b $ "return " ++ valueToJs val ++ ";") binders
47+
++ "throw \"Failed pattern match\";"
48+
++ "})(" ++ valueToJs value ++ ")"
49+
valueToJs (TypedValue value _) = valueToJs value
50+
51+
unaryOperatorString :: UnaryOperator -> String
52+
unaryOperatorString Negate = "-"
53+
unaryOperatorString Not = "!"
54+
unaryOperatorString BitwiseNot = "~"
55+
56+
binaryOperatorString :: BinaryOperator -> String
57+
binaryOperatorString Add = "+"
58+
binaryOperatorString Subtract = "-"
59+
binaryOperatorString Multiply = "*"
60+
binaryOperatorString Divide = "/"
61+
binaryOperatorString Modulus = "%"
62+
binaryOperatorString LessThan = "<"
63+
binaryOperatorString LessThanOrEqualTo = "<="
64+
binaryOperatorString GreaterThan = ">"
65+
binaryOperatorString GreaterThanOrEqualTo = ">="
66+
binaryOperatorString BitwiseAnd = "&"
67+
binaryOperatorString BitwiseOr = "|"
68+
binaryOperatorString BitwiseXor = "^"
69+
binaryOperatorString ShiftLeft = "<<"
70+
binaryOperatorString ShiftRight = ">>"
71+
binaryOperatorString ZeroFillShiftRight = ">>>"
72+
binaryOperatorString EqualTo = "==="
73+
binaryOperatorString NotEqualTo = "!=="
74+
binaryOperatorString And = "&&"
75+
binaryOperatorString Or = "||"
76+
binaryOperatorString Concat = "+"
77+
78+
binderToJs :: Int -> Int -> Binder -> String -> (String, Int)
79+
binderToJs varName fresh (VarBinder s) done = ("var " ++ s ++ " = _" ++ show varName ++ "; " ++ done, fresh)
80+
binderToJs varName fresh (ConstructorBinder ctor b) done =
81+
("if (_" ++ show varName ++ ".ctor === \"" ++ ctor ++ "\") {"
82+
++ "var _" ++ show fresh' ++ " = _" ++ show varName ++ ".value;"
83+
++ js
84+
++ "}", fresh'')
85+
where
86+
fresh' = succ fresh
87+
(js, fresh'') = binderToJs fresh' fresh' b done
88+
binderToJs varName fresh (ObjectBinder bs) done = go fresh bs done
89+
where
90+
go fresh [] done = (done, fresh)
91+
go fresh ((prop, binder):bs') done =
92+
( "var _" ++ show fresh' ++ " = _" ++ show varName ++ "." ++ prop ++ ";"
93+
++ js
94+
, fresh''')
95+
where
96+
fresh' = succ fresh
97+
(done', fresh'') = go fresh' bs' done
98+
(js, fresh''') = binderToJs fresh' fresh'' binder done'
99+
100+
objectPropertyToJs :: (String, Value) -> String
101+
objectPropertyToJs (key, value) = key ++ ":" ++ valueToJs value
102+
103+
statementToJs :: Statement -> String
104+
statementToJs (VariableIntroduction name value) = "var " ++ name ++ " = " ++ valueToJs value
105+
statementToJs (Assignment target value) = target ++ " = " ++ valueToJs value
106+
statementToJs (While cond sts) = "while ("
107+
++ valueToJs cond ++ ") {"
108+
++ intercalate ";" (map statementToJs sts) ++ "}"
109+
statementToJs (For (init, cond, done) sts) = "for (" ++
110+
statementToJs init
111+
++ "; " ++ valueToJs cond
112+
++ "; " ++ statementToJs done
113+
++ ") {" ++ intercalate ";" (map statementToJs sts) ++ "}"
114+
statementToJs (IfThenElse cond thens elses) = "if ("
115+
++ valueToJs cond ++ ") {"
116+
++ intercalate ";" (map statementToJs thens) ++ "}"
117+
++ flip (maybe "") elses (\sts ->
118+
" else {" ++ intercalate ";" (map statementToJs sts) ++ "}")
119+
statementToJs (Return value) = "return " ++ valueToJs value

src/PureScript/Declarations.hs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
-----------------------------------------------------------------------------
2+
--
3+
-- Module : PureScript.Declarations
4+
-- Copyright : (c) Phil Freeman 2013
5+
-- License : MIT
6+
--
7+
-- Maintainer : Phil Freeman <paf31@cantab.net>
8+
-- Stability : experimental
9+
-- Portability :
10+
--
11+
-- |
12+
--
13+
-----------------------------------------------------------------------------
14+
15+
module PureScript.Declarations (
16+
Declaration (..),
17+
DataConstructors (..)
18+
) where
19+
20+
import PureScript.Values
21+
import PureScript.Types
22+
23+
data Declaration
24+
= DataDeclaration DataConstructors
25+
| TypeDeclaration String Type
26+
| ValueDeclaration String Value deriving Show
27+
28+
data DataConstructors = DataConstructors
29+
{ typeConstructorName :: String
30+
, typeArguments :: [String]
31+
, dataConstructors :: [(String, Type)]
32+
} deriving Show

src/PureScript/Kinds.hs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
-----------------------------------------------------------------------------
2+
--
3+
-- Module : PureScript.Kinds
4+
-- Copyright : (c) Phil Freeman 2013
5+
-- License : MIT
6+
--
7+
-- Maintainer : Phil Freeman <paf31@cantab.net>
8+
-- Stability : experimental
9+
-- Portability :
10+
--
11+
-- |
12+
--
13+
-----------------------------------------------------------------------------
14+
15+
module PureScript.Kinds (
16+
Kind (..)
17+
) where
18+
19+
data Kind
20+
= KUnknown Int
21+
| Star
22+
| Row
23+
| FunKind Kind Kind deriving Eq
24+
25+
instance Show Kind where
26+
show (KUnknown _) = "?"
27+
show Star = "*"
28+
show Row = "R"
29+
show (FunKind k1 k2) = "(" ++ show k1 ++ ") -> (" ++ show k2 ++ ")"

src/PureScript/Parser.hs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
-----------------------------------------------------------------------------
2+
--
3+
-- Module : PureScript.Parser
4+
-- Copyright : (c) Phil Freeman 2013
5+
-- License : MIT
6+
--
7+
-- Maintainer : Phil Freeman <paf31@cantab.net>
8+
-- Stability : experimental
9+
-- Portability :
10+
--
11+
-- |
12+
--
13+
-----------------------------------------------------------------------------
14+
15+
module PureScript.Parser (
16+
module PureScript.Parser.Types,
17+
module PureScript.Parser.Values,
18+
module PureScript.Parser.Declarations
19+
) where
20+
21+
import PureScript.Parser.Types
22+
import PureScript.Parser.Values
23+
import PureScript.Parser.Declarations
24+

0 commit comments

Comments
 (0)