0 | module Libraries.Utils.Scheme
3 | data ForeignObj : Type where [external]
5 | %foreign "scheme:blodwen-eval-scheme"
6 | prim__evalScheme : String -> ForeignObj
8 | %foreign "scheme:blodwen-eval-okay"
9 | prim__evalOkay : ForeignObj -> Int
11 | %foreign "scheme:blodwen-get-eval-result"
12 | prim__evalResult : ForeignObj -> ForeignObj
14 | %foreign "scheme:blodwen-debug-scheme"
15 | prim__debugScheme : ForeignObj -> PrimIO ()
17 | %foreign "scheme:blodwen-is-number"
18 | prim_isNumber : ForeignObj -> Int
20 | %foreign "scheme:blodwen-is-integer"
21 | prim_isInteger : ForeignObj -> Int
23 | %foreign "scheme:blodwen-is-float"
24 | prim_isFloat : ForeignObj -> Int
26 | %foreign "scheme:blodwen-is-char"
27 | prim_isChar : ForeignObj -> Int
29 | %foreign "scheme:blodwen-is-string"
30 | prim_isString : ForeignObj -> Int
32 | %foreign "scheme:blodwen-is-procedure"
33 | prim_isProcedure : ForeignObj -> Int
35 | %foreign "scheme:blodwen-is-symbol"
36 | prim_isSymbol : ForeignObj -> Int
38 | %foreign "scheme:blodwen-is-nil"
39 | prim_isNil : ForeignObj -> Int
41 | %foreign "scheme:blodwen-is-pair"
42 | prim_isPair : ForeignObj -> Int
44 | %foreign "scheme:blodwen-is-vector"
45 | prim_isVector : ForeignObj -> Int
47 | %foreign "scheme:blodwen-is-box"
48 | prim_isBox : ForeignObj -> Int
51 | isNumber : ForeignObj -> Bool
52 | isNumber x = prim_isNumber x == 1
55 | isInteger : ForeignObj -> Bool
56 | isInteger x = prim_isInteger x == 1
59 | isFloat : ForeignObj -> Bool
60 | isFloat x = prim_isFloat x == 1
63 | isChar : ForeignObj -> Bool
64 | isChar x = prim_isChar x == 1
67 | isString : ForeignObj -> Bool
68 | isString x = prim_isString x == 1
71 | isProcedure : ForeignObj -> Bool
72 | isProcedure x = prim_isProcedure x == 1
75 | isSymbol : ForeignObj -> Bool
76 | isSymbol x = prim_isSymbol x == 1
79 | isNil : ForeignObj -> Bool
80 | isNil x = prim_isNil x == 1
83 | isPair : ForeignObj -> Bool
84 | isPair x = prim_isPair x == 1
87 | isVector : ForeignObj -> Bool
88 | isVector x = prim_isVector x == 1
91 | isBox : ForeignObj -> Bool
92 | isBox x = prim_isBox x == 1
96 | %foreign "scheme:blodwen-id"
98 | unsafeGetInteger : ForeignObj -> Integer
100 | %foreign "scheme:blodwen-id"
102 | unsafeGetString : ForeignObj -> String
104 | %foreign "scheme:blodwen-id"
106 | unsafeGetFloat : ForeignObj -> Double
108 | %foreign "scheme:blodwen-id"
110 | unsafeGetChar : ForeignObj -> Char
112 | %foreign "scheme:car"
114 | unsafeFst : ForeignObj -> ForeignObj
116 | %foreign "scheme:cdr"
118 | unsafeSnd : ForeignObj -> ForeignObj
120 | %foreign "scheme:blodwen-apply"
122 | unsafeApply : ForeignObj -> ForeignObj -> ForeignObj
124 | %foreign "scheme:blodwen-force"
126 | unsafeForce : ForeignObj -> ForeignObj
128 | %foreign "scheme:blodwen-vector-ref"
130 | unsafeVectorRef : ForeignObj -> Integer -> ForeignObj
132 | %foreign "scheme:blodwen-unbox"
134 | unsafeUnbox : ForeignObj -> ForeignObj
136 | %foreign "scheme:blodwen-vector-length"
138 | unsafeVectorLength : ForeignObj -> Integer
140 | %foreign "scheme:blodwen-vector-list"
142 | unsafeVectorToList : ForeignObj -> List ForeignObj
144 | %foreign "scheme:blodwen-make-symbol"
146 | makeSymbol : String -> ForeignObj
148 | %foreign "scheme:blodwen-read-symbol"
150 | unsafeReadSymbol : ForeignObj -> String
153 | evalSchemeStr : String -> IO (Maybe ForeignObj)
155 | = let obj = prim__evalScheme exp in
156 | if prim__evalOkay obj == 1
157 | then pure $
Just (prim__evalResult obj)
161 | debugScheme : ForeignObj -> IO ()
162 | debugScheme obj = primIO $
prim__debugScheme obj
165 | data Direction = Write | Readback
168 | data SchemeObj : Direction -> Type where
170 | Cons : SchemeObj t -> SchemeObj t -> SchemeObj t
171 | IntegerVal : Integer -> SchemeObj t
172 | FloatVal : Double -> SchemeObj t
173 | StringVal : String -> SchemeObj t
174 | CharVal : Char -> SchemeObj t
175 | Symbol : String -> SchemeObj t
176 | Box : SchemeObj t -> SchemeObj t
177 | Vector : Integer -> List (SchemeObj t) -> SchemeObj t
181 | Procedure : ForeignObj -> SchemeObj Readback
183 | Define : String -> SchemeObj Write -> SchemeObj Write
184 | Var : String -> SchemeObj Write
185 | Lambda : List String -> SchemeObj Write -> SchemeObj Write
186 | Let : String -> SchemeObj Write -> SchemeObj Write -> SchemeObj Write
187 | If : SchemeObj Write -> SchemeObj Write -> SchemeObj Write ->
189 | Case : SchemeObj Write ->
190 | List (SchemeObj Write, SchemeObj Write) ->
191 | Maybe (SchemeObj Write) ->
193 | Cond : List (SchemeObj Write, SchemeObj Write) ->
194 | Maybe (SchemeObj Write) ->
196 | Apply : SchemeObj Write -> List (SchemeObj Write) -> SchemeObj Write
199 | evalSchemeObj : SchemeObj Write -> IO (Maybe ForeignObj)
201 | = do let str = toString obj
204 | showSep : String -> List String -> String
205 | showSep sep [] = ""
206 | showSep sep [x] = x
207 | showSep sep (x :: xs) = x ++ sep ++ showSep sep xs
209 | toString : SchemeObj Write -> String
210 | toString Null = "'()"
211 | toString (Cons x y) = "(cons " ++ toString x ++ " " ++ toString y ++ ")"
212 | toString (IntegerVal x) = show x
213 | toString (FloatVal x) = show x
214 | toString (StringVal x) = show x
215 | toString (CharVal x)
216 | = if (the Int (cast x) >= 32 && the Int (cast x) < 127)
217 | then "#\\" ++ cast x
218 | else "(integer->char " ++ show (the Int (cast x)) ++ ")"
219 | toString (Symbol x) = "'" ++ x
220 | toString (Vector i xs) = "(vector " ++ show i ++ " " ++ showSep " " (map toString xs) ++ ")"
221 | toString (Box x) = "(box " ++ toString x ++ ")"
222 | toString (Define x body) = "(define (" ++ x ++ ") " ++ toString body ++ ")"
223 | toString (Var x) = x
224 | toString (Lambda xs x)
225 | = "(lambda (" ++ showSep " " xs ++ ") " ++ toString x ++ ")"
226 | toString (Let var val x)
227 | = "(let ((" ++ var ++ " " ++ toString val ++ ")) " ++ toString x ++ ")"
228 | toString (If x t e)
229 | = "(if " ++ toString x ++ " " ++ toString t ++ " " ++ toString e ++ ")"
230 | toString (Case x alts def)
231 | = "(case " ++ toString x ++ " " ++
232 | showSep " " (map showAlt alts) ++
235 | showAlt : (SchemeObj Write, SchemeObj Write) -> String
237 | = "((" ++ toString opt ++ ") " ++ toString go ++ ")"
239 | showDef : Maybe (SchemeObj Write) -> String
240 | showDef Nothing = ""
241 | showDef (Just e) = " (else " ++ toString e ++ ")"
242 | toString (Cond alts def)
244 | showSep " " (map showAlt alts) ++
247 | showAlt : (SchemeObj Write, SchemeObj Write) -> String
249 | = "(" ++ toString opt ++ " " ++ toString go ++ ")"
251 | showDef : Maybe (SchemeObj Write) -> String
252 | showDef Nothing = ""
253 | showDef (Just e) = " (else " ++ toString e ++ ")"
254 | toString (Apply x xs)
255 | = "(" ++ toString x ++ " " ++ showSep " " (map toString xs) ++ ")"
258 | decodeObj : ForeignObj -> SchemeObj Readback
260 | = if isInteger obj then IntegerVal (unsafeGetInteger obj)
261 | else if isVector obj then Vector (unsafeGetInteger (unsafeVectorRef obj 0))
262 | (readVector (unsafeVectorLength obj) 1 obj)
263 | else if isPair obj then Cons (decodeObj (unsafeFst obj))
264 | (decodeObj (unsafeSnd obj))
265 | else if isFloat obj then FloatVal (unsafeGetFloat obj)
266 | else if isString obj then StringVal (unsafeGetString obj)
267 | else if isChar obj then CharVal (unsafeGetChar obj)
268 | else if isSymbol obj then Symbol (unsafeReadSymbol obj)
269 | else if isProcedure obj then Procedure obj
270 | else if isBox obj then Box (decodeObj (unsafeUnbox obj))
273 | readVector : Integer -> Integer -> ForeignObj -> List (SchemeObj Readback)
274 | readVector len i obj
277 | else decodeObj (unsafeVectorRef obj i) ::
278 | readVector len (i + 1) obj
281 | interface Scheme a where
282 | toScheme : a -> SchemeObj Write
283 | fromScheme : SchemeObj Readback -> Maybe a
286 | evalScheme : Scheme a => a -> IO (Maybe ForeignObj)
287 | evalScheme = evalSchemeObj . toScheme
290 | decode : Scheme a => ForeignObj -> Maybe a
291 | decode = fromScheme . decodeObj
294 | Scheme Integer where
295 | toScheme x = IntegerVal x
297 | fromScheme (IntegerVal x) = Just x
298 | fromScheme _ = Nothing
302 | toScheme x = IntegerVal (cast x)
304 | fromScheme (IntegerVal x) = Just (cast x)
305 | fromScheme _ = Nothing
309 | toScheme x = IntegerVal (cast x)
311 | fromScheme (IntegerVal x) = Just (cast x)
312 | fromScheme _ = Nothing
316 | toScheme x = IntegerVal (cast x)
318 | fromScheme (IntegerVal x) = Just (cast x)
319 | fromScheme _ = Nothing
323 | toScheme x = IntegerVal (cast x)
325 | fromScheme (IntegerVal x) = Just (cast x)
326 | fromScheme _ = Nothing
330 | toScheme x = IntegerVal (cast x)
332 | fromScheme (IntegerVal x) = Just (cast x)
333 | fromScheme _ = Nothing
337 | toScheme x = IntegerVal (cast x)
339 | fromScheme (IntegerVal x) = Just (cast x)
340 | fromScheme _ = Nothing
343 | Scheme Bits16 where
344 | toScheme x = IntegerVal (cast x)
346 | fromScheme (IntegerVal x) = Just (cast x)
347 | fromScheme _ = Nothing
350 | Scheme Bits32 where
351 | toScheme x = IntegerVal (cast x)
353 | fromScheme (IntegerVal x) = Just (cast x)
354 | fromScheme _ = Nothing
357 | Scheme Bits64 where
358 | toScheme x = IntegerVal (cast x)
360 | fromScheme (IntegerVal x) = Just (cast x)
361 | fromScheme _ = Nothing
364 | Scheme String where
365 | toScheme x = StringVal x
367 | fromScheme (StringVal x) = Just x
368 | fromScheme _ = Nothing
371 | Scheme Double where
372 | toScheme x = FloatVal x
374 | fromScheme (FloatVal x) = Just x
375 | fromScheme _ = Nothing
379 | toScheme x = CharVal x
381 | fromScheme (CharVal x) = Just x
382 | fromScheme _ = Nothing
386 | toScheme False = IntegerVal 0
387 | toScheme True = IntegerVal 1
389 | fromScheme (IntegerVal 0) = Just False
390 | fromScheme (IntegerVal 1) = Just True
391 | fromScheme _ = Nothing
394 | Scheme a => Scheme (List a) where
396 | toScheme (x :: xs) = Cons (toScheme x) (toScheme xs)
398 | fromScheme Null = Just []
399 | fromScheme (Cons x xs) = Just $
!(fromScheme x) :: !(fromScheme xs)
400 | fromScheme _ = Nothing
403 | (Scheme a, Scheme b) => Scheme (a, b) where
404 | toScheme (x, y) = Cons (toScheme x) (toScheme y)
405 | fromScheme (Cons x y) = Just (!(fromScheme x), !(fromScheme y))
406 | fromScheme _ = Nothing
409 | Scheme a => Scheme (Maybe a) where
410 | toScheme Nothing = Null
411 | toScheme (Just x) = Box (toScheme x)
413 | fromScheme Null = Just Nothing
414 | fromScheme (Box x) = Just $
Just !(fromScheme x)
415 | fromScheme _ = Nothing