VB.Net, C#: fix cmd line arg handling with --raw
[jackhill/mal.git] / vb / step5_tco.vb
CommitLineData
ee7cd585
JM
1Imports System
2Imports System.IO
3Imports System.Collections.Generic
4Imports Mal
5Imports MalVal = Mal.types.MalVal
6Imports MalInt = Mal.types.MalInt
7Imports MalSymbol = Mal.types.MalSymbol
8Imports MalList = Mal.types.MalList
9Imports MalVector = Mal.types.MalVector
10Imports MalHashMap = Mal.types.MalHashMap
11Imports MalFunc = Mal.types.MalFunc
12Imports MalEnv = Mal.env.Env
13
14Namespace Mal
aaba2493 15 Class step5_tco
ee7cd585
JM
16 ' read
17 Shared Function READ(str As String) As MalVal
18 Return reader.read_str(str)
19 End Function
20
21 ' eval
22 Shared Function eval_ast(ast As MalVal, env As MalEnv) As MalVal
23 If TypeOf ast Is MalSymbol Then
24 Dim sym As MalSymbol = DirectCast(ast, MalSymbol)
25 return env.do_get(sym.getName())
26 Else If TypeOf ast Is MalList Then
27 Dim old_lst As MalList = DirectCast(ast, MalList)
28 Dim new_lst As MalList
29 If ast.list_Q() Then
30 new_lst = New MalList
31 Else
32 new_lst = DirectCast(New MalVector, MalList)
33 End If
34 Dim mv As MalVal
35 For Each mv in old_lst.getValue()
36 new_lst.conj_BANG(EVAL(mv, env))
37 Next
38 return new_lst
39 Else If TypeOf ast Is MalHashMap Then
40 Dim new_dict As New Dictionary(Of String, MalVal)
41 Dim entry As KeyValuePair(Of String, MalVal)
42 For Each entry in DirectCast(ast,MalHashMap).getValue()
43 new_dict.Add(entry.Key, EVAL(DirectCast(entry.Value,MalVal), env))
44 Next
45 return New MalHashMap(new_dict)
46 Else
47 return ast
48 End If
49 return ast
50 End Function
51
52 ' TODO: move to types.vb when it is ported
53 Class FClosure
54 Public ast As MalVal
55 Public params As MalList
56 Public env As MalEnv
57 Function fn(args as MalList) As MalVal
58 return EVAL(ast, new MalEnv(env, params, args))
59 End Function
60 End Class
61
62 Shared Function EVAL(orig_ast As MalVal, env As MalEnv) As MalVal
63 Do
64
65 'Console.WriteLine("EVAL: {0}", printer._pr_str(orig_ast, true))
66 If not orig_ast.list_Q() Then
67 return eval_ast(orig_ast, env)
68 End If
69
70 ' apply list
71 Dim ast As MalList = DirectCast(orig_ast, MalList)
72 If ast.size() = 0 Then
73 return ast
74 End If
75 Dim a0 As MalVal = ast(0)
76 Dim a0sym As String
77 If TypeOf a0 is MalSymbol Then
78 a0sym = DirectCast(a0,MalSymbol).getName()
79 Else
80 a0sym = "__<*fn*>__"
81 End If
82
83 Select a0sym
84 Case "def!"
85 Dim a1 As MalVal = ast(1)
86 Dim a2 As MalVal = ast(2)
87 Dim res As MalVal = EVAL(a2, env)
88 env.do_set(DirectCast(a1,MalSymbol).getName(), res)
89 return res
90 Case "let*"
91 Dim a1 As MalVal = ast(1)
92 Dim a2 As MalVal = ast(2)
93 Dim key As MalSymbol
94 Dim val as MalVal
95 Dim let_env As new MalEnv(env)
96 For i As Integer = 0 To (DirectCast(a1,MalList)).size()-1 Step 2
97 key = DirectCast(DirectCast(a1,MalList)(i),MalSymbol)
98 val = DirectCast(a1,MalList)(i+1)
99 let_env.do_set(key.getName(), EVAL(val, let_env))
100 Next
101 orig_ast = a2
102 env = let_env
103 Case "do"
104 eval_ast(ast.slice(1, ast.size()-1), env)
105 orig_ast = ast(ast.size()-1)
106 Case "if"
107 Dim a1 As MalVal = ast(1)
108 Dim cond As MalVal = EVAL(a1, env)
109 If cond Is Mal.types.Nil or cond Is Mal.types.MalFalse Then
110 ' eval false slot form
111 If ast.size() > 3 Then
112 orig_ast = ast(3)
113 Else
114 return Mal.types.Nil
115 End If
116 Else
117 ' eval true slot form
118 orig_ast = ast(2)
119
120 End If
121 Case "fn*"
122 Dim fc As New FClosure()
123 fc.ast = ast(2)
124 fc.params = DirectCast(ast(1),MalLIst)
125 fc.env = env
126 Dim f As Func(Of MalList, MalVal) = AddressOf fc.fn
127 Dim mf As new MalFunc(ast(2), env,
128 DirectCast(ast(1),MalList), f)
129 return DirectCast(mf,MalVal)
130 Case Else
131 Dim el As MalList = DirectCast(eval_ast(ast, env), MalList)
132 Dim f As MalFunc = DirectCast(el(0), MalFunc)
133 Dim fnast As MalVal = f.getAst()
134 If not fnast Is Nothing
135 orig_ast = fnast
136 env = f.genEnv(el.rest())
137 Else
138 Return f.apply(el.rest())
139 End If
140 End Select
141
142 Loop While True
143 End Function
144
145 ' print
146 Shared Function PRINT(exp As MalVal) As String
147 return printer._pr_str(exp, TRUE)
148 End Function
149
150 ' repl
151 Shared repl_env As MalEnv
152
153 Shared Function REP(str As String) As String
154 Return PRINT(EVAL(READ(str), repl_env))
155 End Function
156
157 Shared Function Main As Integer
158 Dim args As String() = Environment.GetCommandLineArgs()
159
160 repl_env = New MalEnv(Nothing)
161
162 ' core.vb: defined using VB.NET
163 For Each entry As KeyValuePair(Of String,MalVal) In core.ns()
164 repl_env.do_set(entry.Key, entry.Value)
165 Next
166
167 ' core.mal: defined using the language itself
168 REP("(def! not (fn* (a) (if a false true)))")
169
170 If args.Length > 1 AndAlso args(1) = "--raw" Then
171 Mal.readline.SetMode(Mal.readline.Modes.Raw)
172 End If
173
174 ' repl loop
175 Dim line As String
176 Do
177 Try
178 line = Mal.readline.Readline("user> ")
179 If line is Nothing Then
180 Exit Do
181 End If
182 If line = "" Then
183 Continue Do
184 End If
185 Catch e As IOException
186 Console.WriteLine("IOException: " & e.Message)
187 End Try
188 Try
189 Console.WriteLine(REP(line))
190 Catch e as Exception
191 Console.WriteLine("Error: " & e.Message)
192 Console.WriteLine(e.StackTrace)
193 Continue Do
194 End Try
195 Loop While True
196 End function
aaba2493 197 End Class
ee7cd585 198End Namespace