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