1 (* Copyright (C
) 2004-2006, 2008 Henry Cejtin
, Matthew Fluet
, Suresh
2 * Jagannathan
, and Stephen Weeks
.
4 * MLton is released under a BSD
-style license
.
5 * See the file MLton
-LICENSE for details
.
24 | EQUAL
=> (lt
,x
::eq
,gt
)
25 | GREATER
=> (lt
,eq
,x
::gt
))
51 datatype t
= T
of string list
53 fun compare (T ss1
, T ss2
) =
56 String.compare (CharVector
.map
Char.toLower s1
,
57 CharVector
.map
Char.toLower s2
))
60 fun last (T ss
) = List.last ss
62 String.concatWith
"_" ss
64 String.concatWith
"." ss
68 val ss
= Substring
.droplSpace ss
71 (fn c
=> Char.isAlphaNum c
72 orelse c
= #
"." orelse c
= #
"_")
74 val rest
= Substring
.droplSpace rest
76 if Substring
.isEmpty names
79 val names
= Substring
.fields (fn c
=> #
"." = c
) names
80 val names
= List.map Substring
.string names
100 Array t
=> concat
["Array(", toC t
, ")"]
101 | Base name
=> Name
.toC name
102 |
Con (name
, t
) => concat
[Name
.toC name
, "(", toC t
, ")"]
103 | Ref t
=> concat
["Ref(", toC t
, ")"]
105 |
Vector t
=> concat
["Vector(", toC t
, ")"]
108 Array t
=> concat
["(", toML t
, ") array"]
109 | Base name
=> Name
.toML name
110 |
Con (name
, t
) => concat
["(", toML t
, ") ", Name
.toML name
]
111 | Ref t
=> concat
["(", toML t
, ") ref"]
113 |
Vector t
=> concat
["(", toML t
, ") vector"]
120 |
SOME (Name
.T
["array"], rest
) => loop (rest
, Array t
)
121 |
SOME (Name
.T
["ref"], rest
) => loop (rest
, Ref t
)
122 |
SOME (Name
.T
["vector"], rest
) => loop (rest
, Vector t
)
123 |
SOME (name
, rest
) => loop (rest
, Con (name
, t
))
126 NONE
=> raise Fail (concat
["Type.parse: \"", Substring
.string s
, "\""])
127 |
SOME (Name
.T
["unit"], rest
) => loop (rest
, Unit
)
128 |
SOME (name
, rest
) => loop (rest
, Base name
)
135 val (arg
, rest
) = parse s
137 if Substring
.isPrefix
"*" rest
139 val rest
= #
2 (Substring
.splitAt (rest
, 1))
141 loop (rest
, arg
::args
)
143 else if Substring
.isPrefix
"->" rest
145 val rest
= #
2 (Substring
.splitAt (rest
, 2))
146 val (ret
, rest
) = parse rest
148 ({args
= List.rev (arg
::args
),
152 else raise Fail (concat
["Type.parseFn: \"", Substring
.string s
, "\""])
162 Const
of {name
: Name
.t
,
164 | Import
of {attrs
: string,
166 ty
: {args
: Type
.t list
,
168 | Symbol
of {name
: Name
.t
,
173 Const
{name
,...} => name
174 | Import
{name
,...} => name
175 | Symbol
{name
,...} => name
177 fun compare (entry1
, entry2
) =
178 Name
.compare (name entry1
, name entry2
)
184 ["PRIVATE extern const ",
189 | Import
{attrs
, name
, ty
= {args
, ret
}} =>
192 if String.size attrs
> 0 then " " else "",
197 String.concatWith
"," (List.map Type
.toC args
),
199 | Symbol
{name
, ty
} =>
217 | Import
{attrs
, name
, ty
= {args
, ret
}} =>
224 String.concatWith
" * " (List.map Type
.toML args
),
228 | Symbol
{name
, ty
} =>
236 "\" private : (unit -> (",
242 fun parseConst (s
, name
) =
244 val s
= #
2 (Substring
.splitAt (s
, 6))
245 val s
= Substring
.droplSpace s
246 val s
= if Substring
.isPrefix
":" s
247 then #
2 (Substring
.splitAt (s
, 1))
248 else raise Fail (concat
["Entry.parseConst: \"", Substring
.string s
, "\""])
249 val (ret
, rest
) = Type
.parse s
250 val () = if Substring
.isEmpty rest
252 else raise Fail (concat
["Entry.parseConst: \"", Substring
.string s
, "\""])
258 fun parseImport (s
, name
) =
260 val s
= #
2 (Substring
.splitAt (s
, 7))
261 val s
= Substring
.droplSpace s
263 case CharVectorSlice
.findi (fn (_
, c
) => c
= #
":") s
of
264 NONE
=> raise Fail (concat
["Entry.parseImport: \"", Substring
.string s
, "\""])
265 |
SOME (i
, _
) => Substring
.splitAt (s
, i
)
266 val attrs
= Substring
.droprSpace attrs
267 val s
= if Substring
.isPrefix
":" s
268 then #
2 (Substring
.splitAt (s
, 1))
269 else raise Fail (concat
["Entry.parseImport: \"", Substring
.string s
, "\""])
270 val ({args
, ret
}, rest
) = Type
.parseFn s
271 val () = if Substring
.isEmpty rest
273 else raise Fail (concat
["Entry.parseImport: \"", Substring
.string s
, "\""])
275 Import
{attrs
= Substring
.string attrs
,
277 ty
= {args
= args
, ret
= ret
}}
280 fun parseSymbol (s
, name
) =
282 val s
= #
2 (Substring
.splitAt (s
, 7))
283 val s
= Substring
.droplSpace s
284 val s
= if Substring
.isPrefix
":" s
285 then #
2 (Substring
.splitAt (s
, 1))
286 else raise Fail (concat
["Entry.parseSymbol: \"", Substring
.string s
, "\""])
287 val (ret
, rest
) = Type
.parse s
288 val () = if Substring
.isEmpty rest
290 else raise Fail (concat
["Entry.parseSymbol: \"", Substring
.string s
, "\""])
298 NONE
=> raise Fail
"Entry.parse"
299 |
SOME (name
, rest
) =>
300 if Substring
.isPrefix
"=" rest
302 val rest
= #
2 (Substring
.splitAt (rest
, 1))
303 val rest
= Substring
.droplSpace rest
305 if Substring
.isPrefix
"_const" rest
306 then parseConst (rest
, name
)
307 else if Substring
.isPrefix
"_import" rest
308 then parseImport (rest
, name
)
309 else if Substring
.isPrefix
"_symbol" rest
310 then parseSymbol (rest
, name
)
311 else raise Fail (concat
["Entry.parse: \"", Substring
.string s
, "\""])
313 else raise Fail (concat
["Entry.parse: \"", Substring
.string s
, "\""])
318 val f
= TextIO.openIn
"basis-ffi.def"
320 case TextIO.inputLine f
of
321 NONE
=> List.rev entries
323 if String.isPrefix
"#" s
326 val entry
= Entry
.parse (Substring
.full s
)
328 loop (entry
:: entries
)
330 val entries
= loop
[]
331 val () = TextIO.closeIn f
332 val entries
= List.sort Entry
.compare entries
337 fun outputC entries
=
339 val f
= TextIO.openOut
"basis-ffi.h"
340 fun print s
= TextIO.output (f
, s
)
341 fun println s
= if s
<> "" then (print s
; print
"\n") else ()
343 val () = println
"/* This file is automatically generated. Do not edit. */\n\n"
344 val () = println
"#ifndef _MLTON_BASIS_FFI_H_\n"
345 val () = println
"#define _MLTON_BASIS_FFI_H_\n"
346 val () = List.app (fn entry
=> println (Entry
.toC entry
)) entries
347 val () = println
"#endif /* _MLTON_BASIS_FFI_H_ */"
348 val () = TextIO.closeOut f
353 fun outputML entries
=
355 val f
= TextIO.openOut
"basis-ffi.sml"
356 fun print s
= TextIO.output (f
, s
)
357 fun println s
= if s
<> "" then (print s
; print
"\n") else ()
360 (List.map (fn n
=> "Char" ^ n
) ["8", "16", "32"]) @
361 (List.map (fn n
=> "Int" ^ n
) ["8", "16", "32", "64"]) @
362 (List.map (fn n
=> "Real" ^ n
) ["32", "64"]) @
363 (List.map (fn n
=> "Word" ^ n
) ["8", "16", "32", "64"])
365 val () = println
"(* This file is automatically generated. Do not edit. *)\n"
366 val () = println
"local open Primitive in "
367 val () = println
"structure PrimitiveFFI ="
368 val () = println
"struct"
373 val Name
.T names
= Entry
.name entry
374 val str
= List.rev (List.tl (List.rev names
))
375 fun loop (cur
, str
) =
380 (println ("structure " ^ s ^
" = ")
382 ; if List.exists (fn s
' => s
= s
') primStrs
383 then println ("type t = " ^ s ^
".t")
387 List.app (fn _
=> println
"end") cur
392 ; loop (cur
, s
::str
))
395 ; println (Entry
.toML entry
)
400 val () = List.app (fn _
=> println
"end") cur
401 val () = println
"end"
402 val () = println
"end"
403 val () = TextIO.closeOut f
408 val () = outputC entries
409 val () = outputML entries