Type inference for functions works YAAAY
[cc1516.git] / spl.icl
1 module spl
2
3 import StdFile
4 import StdBool
5 import StdMisc
6 import StdFunc
7 import StdTuple
8 import StdList
9 import StdString
10 import Data.Either
11 import Data.Maybe
12 import Data.Func
13 import System.CommandLine
14 import GenPrint
15 import Data.Map
16 from Text import class Text(concat,join), instance Text String
17
18 import parse
19 import lex
20 import sem
21 import AST
22 from yard import :: Error, instance toString Error
23
24 :: Opts = {
25 version :: Bool,
26 program :: String,
27 lex :: Bool,
28 parse :: Bool,
29 sem :: Bool,
30 fp :: Maybe String,
31 help :: Bool}
32
33 derive gPrint TokenValue
34
35 Start :: *World -> *World
36 Start w
37 # (args, w) = parseArgs w
38 # (stdin, w) = stdio w
39 | args.version
40 # stdin = stdin
41 <<< "spl 0.1 (17 march 2016)\n"
42 <<< "Copyright Pim Jager and Mart Lubbers\n"
43 = snd $ fclose stdin w
44 | args.help
45 # stdin = stdin
46 <<< "Usage: " <<< args.program <<< " [OPTION] [FILE]\n"
47 <<< "<spl> ::= <spl> <parser> <lexer>\n"
48 <<< "Lex parse and either FILE or stdin\n"
49 <<< "\n"
50 <<< "Options:\n"
51 <<< " --help Show this help\n"
52 <<< " --version Show the version\n"
53 <<< " --[no-]lex Lexer output(default: disabled)\n"
54 <<< " --[no-]parse Parser output(default: disabled)\n"
55 <<< " --[no-]sem Semantic analysis output(default: enabled)\n"
56 = snd $ fclose stdin w
57 # (contents, stdin, w) = readFileOrStdin stdin args.fp w
58 = case contents of
59 (Left cs) = snd $ fclose (stdin <<< cs) w
60 (Right cs) = case lexer cs of
61 (Left e) = snd $ fclose (stdin <<< toString e) w
62 (Right lexOut)
63 # stdin = if (not args.lex) stdin (
64 stdin <<< "//LEXER\n" <<< printTokens lexOut <<< "//LEXER\n")
65 = case parser lexOut of
66 (Left e) = snd $ fclose (stdin <<< toString e) w
67 (Right parseOut)
68 # stdin = if (not args.parse) stdin (
69 stdin <<< "//PARSER\n" <<< toString parseOut <<< "//PARSER\n")
70 = case sem parseOut of
71 (Left e) = snd $ fclose (stdin <<< join "\n" (map toString e)) w
72 (Right ast)
73 # stdin = if (not args.sem) stdin (stdin
74 <<< "//SEM G\n" <<< toString ast <<< "//SEMA\n")
75 = snd $ fclose (stdin <<< "\n") w
76 where
77 printConstraints :: Constraints -> String
78 printConstraints [] = ""
79 printConstraints [(t1, t2):ts] = concat [
80 "(", toString t1, ",", toString t2, ")"] +++ printConstraints ts
81
82 printTokens :: [Token] -> String
83 printTokens ts = concat $ flatten $ map pt ts
84 where
85 pt ({line,col},token) = [toString line, ":",
86 toString col, ": ", printToString token, "\n"]
87
88 parseArgs :: *World -> (Opts, *World)
89 parseArgs w
90 # ([p:args], w) = getCommandLine w
91 = (pa args {
92 program=p,
93 version=False,
94 lex=False,
95 parse=False,
96 sem=True,
97 fp=Nothing,
98 help=False}, w)
99 where
100 pa :: [String] Opts -> Opts
101 pa [] o = o
102 pa ["--help":r] o = pa r {o & help=True}
103 pa ["--version":r] o = pa r {o & version=True}
104 pa ["--lex":r] o = pa r {o & lex=True}
105 pa ["--no-lex":r] o = pa r {o & lex=False}
106 pa ["--parse":r] o = pa r {o & parse=True}
107 pa ["--no-parse":r] o = pa r {o & parse=False}
108 pa ["--sem":r] o = pa r {o & sem=True}
109 pa ["--no-sem":r] o = pa r {o & sem=False}
110 pa [x:r] o = pa r {o & fp=Just x}
111
112 readFileOrStdin :: *File (Maybe String) *World -> *(Either String [Char], *File, *World)
113 readFileOrStdin stdin Nothing w
114 # (cs, stdin) = readEntireFile stdin
115 = (Right cs, stdin, w)
116 readFileOrStdin stdin (Just fp) w
117 # (b, fin, w) = fopen fp FReadText w
118 | not b = (Left "Unable to open file", stdin, w)
119 # (cs, fin) = readEntireFile fin
120 # (b, w) = fclose fin w
121 | not b = (Left "Unable to close file", stdin, w)
122 = (Right cs, stdin, w)
123
124 readEntireFile :: *File -> *([Char], *File)
125 readEntireFile f
126 # (b, c, f) = freadc f
127 | not b = ([], f)
128 # (cs, f) = readEntireFile f
129 = ([c:cs], f)