summaryrefslogtreecommitdiff
path: root/driver.fun
blob: 19adcaaadc62509479b7f7a814530a792b1b9317 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
functor Driver(E: EMIT): DRIVER = struct
  structure I = E.I
  structure P = E.I.P

  datatype execMode = Normal | DebugE | DebugT

  type config = {
    file: string option,
    includeDirs: string list,
    mode: execMode
  }

  val updateC = fn z =>
  let
    fun from file includeDirs mode = { file, includeDirs, mode }
    fun to f { file, includeDirs, mode } = f file includeDirs mode
  in
    FRU.makeUpdate3 (from, from, to)
  end z

  val initConfig: config = { file = NONE, includeDirs = [], mode = Normal }

  val die = fn z => die 1 z

  fun finish ({ file = NONE, ... }: config) = die `"No file specified" %
    | finish conf = updateC conf u#includeDirs rev %

  fun parseFlag conf "-dE" tail =
    parseCmdArgs (updateC conf s#mode DebugE %) tail
    | parseFlag conf "-dT" tail =
        parseCmdArgs (updateC conf s#mode DebugT %) tail
    | parseFlag _ arg _ = die `arg `": unknown flag" %

  and parseCmdArgs conf [] = finish conf
    | parseCmdArgs _ ("-I" :: []) =
        die `"-I: expected directory path after flag" %
    | parseCmdArgs conf ("-I" :: path :: tail) =
        parseCmdArgs (updateC conf u#includeDirs
            (fn dirs => path :: dirs) %) tail
    | parseCmdArgs (C as { file, ... }) (arg :: tail) =
      if String.sub (arg, 0) = #"-" then
        parseFlag C arg tail
      else
        case file of
          NONE =>
            let
              val size = size arg
            in
              if String.extract (arg, size - 2, NONE) <> ".c" then
                die `arg `": expected file with .c suffix" %
              else
                let
                  val file = String.substring (arg, 0, size - 2)
                in
                  parseCmdArgs (updateC C s#file (SOME file) %) tail
                end
            end
        | SOME _ => die `arg `": file already specified" %

  fun exec () =
  let
    val config = parseCmdArgs initConfig (CommandLine.arguments ())
    val file = valOf $ #file config
  in
    case (#mode config) of
      Normal =>
        let
          val parseCtx = P.createCtx file (#includeDirs config) true

          fun collect ctx =
          let
            val (continue, ctx) = P.parseDef ctx
          in
            if continue then
              collect ctx
            else
              P.finalize ctx
          end

          val parseCtx = collect parseCtx
          val progInfo = P.explode parseCtx
          val ilCtx = I.createCtx progInfo (SOME $ file ^ ".i")
        in
          E.emit (file ^ ".s") ilCtx (SOME $ file ^ ".e")
        end
    | DebugT => P.P.T.debugPrint file
    | DebugE => P.P.debugPrint file (#includeDirs config)
  end
end