-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.fs
More file actions
151 lines (121 loc) · 4.17 KB
/
Program.fs
File metadata and controls
151 lines (121 loc) · 4.17 KB
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
open System
open PowerArgs
open Feint
open Feint.Compiler
open Feint.Interpreter
type Operation =
| RunCode
| RunFile
| PrintCodeTokens
| PrintFileTokens
// | PrintCodeAst
// | PrintFileAst
| RunRepl
type Result =
| Success
| ParseErr of string
| InterpretErr of string
| ReplErr of string
// XXX: This is used as a hacky way to "return" a result from Main()
// since it's required to return void/unit.
exception Exit of Result
[<ArgExceptionBehavior(ArgExceptionPolicy.StandardExceptionHandling)>]
type Argv() =
// Args ------------------------------------------------------------
[<HelpHook>]
[<ArgDescription("Show this help")>]
[<ArgShortcut("-h")>]
[<ArgShortcut("--help")>]
member val help = false with get, set
[<ArgDescription("Run code snippet")>]
[<ArgShortcut("-c")>]
[<ArgShortcut("--code")>]
member val code: string = null with get, set
[<ArgDescription("Run file")>]
[<ArgExistingFile>]
[<ArgPosition(0)>]
member val fileName: string = null with get, set
[<ArgDescription("Print tokens")>]
[<ArgShortcut("-t")>]
[<ArgShortcut("--tokens")>]
member val tokens = false with get, set
[<ArgDescription("Print AST instead of interpreting when running code or file")>]
[<ArgShortcut("-a")>]
[<ArgShortcut("--ast")>]
member val ast = false with get, set
// Operations ------------------------------------------------------
member this.selectOperation() =
if not (isNull this.code) then
if this.tokens then
PrintCodeTokens
// elif this.ast then PrintCodeAst
else
RunCode
elif not (isNull this.fileName) then
if this.tokens then
PrintFileTokens
// elif this.ast then PrintFileAst
else
RunFile
else
RunRepl
member this.runCode() =
Interpreter.interpretText this.code "<code>" |> this.handleRunResult
member this.runFile() =
Interpreter.interpretFile this.fileName |> this.handleRunResult
member _.handleRunResult result =
match result with
| Interpreter.Success -> Success
| Interpreter.ParseErr err -> ParseErr err
| Interpreter.InterpretErr err -> InterpretErr err
member _.printTokens results =
let handle result =
Lexer.formatResult result |> Console.WriteLine
List.iter handle results
Success
member this.printCodeTokens() =
Lexer.tokensFromText "<code>" this.code |> this.printTokens
member this.printFileTokens() =
Lexer.tokensFromFile this.fileName |> this.printTokens
// member this.printCodeAst() =
// Driver.printAstFromText this.code "<code>"
// Success
// member this.printFileAst() =
// Driver.printAstFromFile this.fileName
// Success
member _.runRepl() =
match Repl.startRepl () with
| Repl.Exit -> Success
| Repl.ReadLineErr exc -> ReplErr $"{exc}"
// Main ------------------------------------------------------------
member this.Main() : unit =
let result =
match this.selectOperation () with
| RunCode -> this.runCode ()
| RunFile -> this.runFile ()
| PrintCodeTokens -> this.printCodeTokens ()
| PrintFileTokens -> this.printFileTokens ()
// | PrintCodeAst -> this.printCodeAst ()
// | PrintFileAst -> this.printFileAst ()
| RunRepl -> this.runRepl ()
raise (Exit result)
[<EntryPoint>]
let main argv =
try
let result = Args.InvokeMain<Argv>(argv)
match result.Cancelled with
| true -> 0 // --help
| false ->
match result.HandledException with
| null -> 254 // unreachable?
| _ -> 255 // bad args
with Exit result ->
let msg, exitCode =
match result with
| Success -> "", 0
| ParseErr msg -> msg, 1
| InterpretErr msg -> msg, 2
| ReplErr msg -> msg, 3
if msg.Length > 0 then
Console.Error.WriteLine msg
exitCode