[MLton-commit] r4984
Wesley Terpstra
wesley at mlton.org
Mon Dec 18 18:56:34 PST 2006
my collection of SML libs, only half finished mostly
----------------------------------------------------------------------
A mltonlib/trunk/ca/terpstra/pickle/
A mltonlib/trunk/ca/terpstra/pickle/Makefile
A mltonlib/trunk/ca/terpstra/pickle/README
A mltonlib/trunk/ca/terpstra/pickle/ast.sml
A mltonlib/trunk/ca/terpstra/pickle/export.sml
A mltonlib/trunk/ca/terpstra/pickle/gen.sml
A mltonlib/trunk/ca/terpstra/pickle/import.sml
A mltonlib/trunk/ca/terpstra/pickle/lib/
A mltonlib/trunk/ca/terpstra/pickle/lib/binary.sml
A mltonlib/trunk/ca/terpstra/pickle/lib/pickle.mlb
A mltonlib/trunk/ca/terpstra/pickle/lib/pickle.sig
A mltonlib/trunk/ca/terpstra/pickle/lib/pickle.sml
A mltonlib/trunk/ca/terpstra/pickle/lib/text.sml
A mltonlib/trunk/ca/terpstra/pickle/main.sml
A mltonlib/trunk/ca/terpstra/pickle/method.sml
A mltonlib/trunk/ca/terpstra/pickle/pickle.mlb
A mltonlib/trunk/ca/terpstra/pickle/tag.sml
A mltonlib/trunk/ca/terpstra/pickle/tests/
A mltonlib/trunk/ca/terpstra/pickle/tests/Makefile
A mltonlib/trunk/ca/terpstra/pickle/tests/double.test
A mltonlib/trunk/ca/terpstra/pickle/tests/rebind.test
A mltonlib/trunk/ca/terpstra/pickle/tests/recursive.test
A mltonlib/trunk/ca/terpstra/pickle/tests/scope.test
A mltonlib/trunk/ca/terpstra/pickle/tests/tree.test
A mltonlib/trunk/ca/terpstra/pickle/tml.grm
A mltonlib/trunk/ca/terpstra/pickle/tml.lex
A mltonlib/trunk/ca/terpstra/pickle/tree.sml
A mltonlib/trunk/ca/terpstra/pickle/type.sml
----------------------------------------------------------------------
Added: mltonlib/trunk/ca/terpstra/pickle/Makefile
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/Makefile 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/Makefile 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,22 @@
+TARGETS = pickle
+
+all: $(TARGETS)
+
+clean:
+ rm -f *.grm.* *.lex.* *.dep $(TARGETS)
+
+%.dep: %.mlb
+ echo -en "$(basename $@) $@:\t" > $@.tmp
+ mlton -stop f $< | sed 's/^/ /;s/$$/ \\/' >> $@.tmp
+ mv $@.tmp $@
+
+%: %.mlb
+ mlton -output $@ $<
+
+%.grm.sml %.grm.sig %.grm.desc: %.grm
+ mlyacc $<
+
+%.lex.sml: %.lex
+ mllex $<
+
+-include $(patsubst %.mlb,%.dep,$(wildcard *.mlb))
Added: mltonlib/trunk/ca/terpstra/pickle/README
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/README 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/README 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,10 @@
+Since MLton has no automatic serialization capability, this attempts to
+build one as a library. The idea was that a protocol could be specified as
+a SML type and the compiled into a serializer for C and SML.
+
+The serializers are built as functors. This way they can be instantiated on
+a binary or text serializer for basic types.
+
+Compile the compiler with:
+ make
+The test directory includes example SML types suitable for compilation
Added: mltonlib/trunk/ca/terpstra/pickle/ast.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/ast.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/ast.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,34 @@
+type tyvar = string
+type tag = string
+
+(* Types which can be written down without a declaration: *)
+datatype inline_typ = RECORD of (string * inline_typ) vector
+ | RECURSIVE of string * (inline_typ * tag) vector * tag
+ | TUPLE of inline_typ vector
+ | TYVAR of tyvar * tag * tag
+
+(* At the top-level, the most general declaration looks like:
+ *
+ * datatype d1 = C of d1 | D of d2 | E of t1
+ * and d2 = F of d1 | G of d2 | F of t2
+ * withtypes t1 = string * d2
+ * and t2 = t1 (* the OLD binding of t1, not the one above *)
+ *
+ * The datatypes are evaluated within the scope of the withtypes and
+ * the other datatypes.
+ *
+ * The withtypes are evaluated within the scope of the datatypes (but
+ * not of the other withtypes).
+ *
+ * An entire such clause is a 'toplevel_typ' below
+ *)
+
+type data_typ = tag * tag * (string * inline_typ option) vector
+
+type 'a bind_typ = { name : string,
+ reader : string,
+ writer : string,
+ tyvars : (tyvar * tag) vector,
+ typ : 'a }
+
+type toplevel_typ = data_typ bind_typ vector * inline_typ bind_typ vector
Added: mltonlib/trunk/ca/terpstra/pickle/export.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/export.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/export.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,22 @@
+fun export ((data, bind), (l, scope)) =
+ let
+ fun decl { name, reader=_, writer=_, tyvars, typ=_ } l =
+ l && " type " ++ tuple (#1, tyvars) && name && "\n"
+ fun binder ({ name, reader=_, writer=_, tyvars=_, typ=_ }, m) =
+ Map.insert m (name, { reader = "", writer = "" })
+
+ val l = l ++ foldl (decl, bind)
+ val scope = Vector.foldl binder scope bind
+ val (l, scope) = dtype ((data, Vector.fromList []), (l, scope))
+
+ fun typack rw (t, _) l = l && t && " Base." && rw
+ fun tyfun rw v l =
+ if Vector.length v = 0 then l else
+ l ++ sfoldl (typack rw, " * ", v) && " -> " ++ tuple (#1, v)
+ fun methods {name, reader=_, writer=_, tyvars, typ=_} l =
+ l && " val " && name
+ && ": { r: " ++ tyfun "r" tyvars && name && " Base.r, w: "
+ ++ tyfun "w" tyvars && name && " Base.w }\n"
+ in
+ (l ++ foldl (methods, data) ++ foldl (methods, bind), scope)
+ end
Added: mltonlib/trunk/ca/terpstra/pickle/gen.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/gen.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/gen.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,30 @@
+ structure Order = struct type k = string val order = String.compare end
+structure Set = Set(Order)
+structure Map = Map(Order)
+
+infix 5 && ++
+fun l && x = x :: l
+fun l ++ f = f l
+
+fun foldl (f, v) l = Vector.foldl (fn (x, l) => f x l) l v
+fun foldli (f, v) l = Vector.foldli (fn (i, x, l) => f (i, x) l) l v
+fun sfoldl (f, s, v) l =
+ let
+ fun sep (0, s) = ""
+ | sep (_, s) = s
+ fun gen (i, x, l) = l && sep (i, s) ++ f x
+ in
+ Vector.foldli gen l v
+ end
+
+fun tuple (f, v) l =
+ if Vector.length v = 0 then l else
+ l && "(" ++ sfoldl (fn x => fn l => l && f x, ", ", v) && ") "
+
+local
+ fun bindToKey { name, reader, writer, tyvars=_, typ=_ } =
+ (name, { reader = reader, writer = writer })
+in
+ fun defd (bind:'a bind_typ vector) =
+ Map.fromVector (Vector.map bindToKey bind)
+end
Added: mltonlib/trunk/ca/terpstra/pickle/import.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/import.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/import.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,58 @@
+fun import ((data, bind) : toplevel_typ, (l, scope)) =
+ let
+ val withscope = Map.union (scope, defd data)
+ val datascope = Map.union (withscope, defd bind)
+ val imports = ref Set.empty
+
+ fun refd (typ, map) =
+ case typ of
+ (RECORD v) => Vector.foldl refd map (Vector.map #2 v)
+ | (TUPLE v) => Vector.foldl refd map v
+ | (TYVAR _) => map
+ | (RECURSIVE (n, v, _)) =>
+ Vector.foldl refd
+ (Map.insert map (n, Vector.length v))
+ (Vector.map #1 v)
+
+ fun prune scope map =
+ let
+ fun filter ((k, v), m) =
+ case Map.fetch scope k of
+ NONE => Map.insert m (k, v)
+ | SOME _ => m
+ in
+ Map.foldl filter Map.empty map
+ end
+
+ val withtyp = Vector.map #typ bind
+ val datatyp = Vector.map #typ data
+ val withref = prune withscope (Vector.foldl refd Map.empty withtyp)
+ fun constr ((_, NONE), m) = m
+ | constr ((_, SOME typ), m) = refd (typ, m)
+ fun datav ((_, _, v), m) = Vector.foldl constr m v
+ val dataref = prune datascope (Vector.foldl datav Map.empty datatyp)
+
+ val import = Map.union (dataref, withref)
+
+ fun fakescope ((k, _), m) = Map.insert m (k, {reader = "", writer = ""})
+ val outscope = Map.foldl fakescope datascope import
+
+ fun tyvar 1 l = l && "'a1"
+ | tyvar i l = l && "'a" && Int.toString i && ", " ++ tyvar (i - 1)
+ fun tyvars n l =
+ if n = 0 then l else
+ l && "(" ++ tyvar n && ") "
+ fun tyarg rw 1 l = l && "'a1 Base." && rw
+ | tyarg rw i l = l && "'a" && Int.toString i && " Base." && rw && " * "
+ ++ tyarg rw (i - 1)
+ fun tyfun rw n l =
+ if n = 0 then l else
+ l ++ tyarg rw n && " -> " ++ tyvars n
+
+ fun declare ((k, v), l) =
+ l && " type " ++ tyvars v && k && "\n"
+ && " val " && k && ": { r: " ++ tyfun "r" v && k
+ && " Base.r, w: " ++ tyfun "w" v && k && " Base.w }\n"
+ in
+ (Map.foldl declare l import, outscope)
+ end
Added: mltonlib/trunk/ca/terpstra/pickle/lib/binary.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/lib/binary.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/lib/binary.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,66 @@
+structure Binary : PICKLER =
+ struct
+ exception Corrupt
+
+ structure Base =
+ struct
+ type wt = Word8.word list
+ type rt = Word8.word list
+ type 'a r = rt -> rt * 'a
+ type 'a w = wt * 'a -> wt
+
+ val opts = { r = fn _ => fn (a :: r) => (r, Word8.toInt a) | _ => raise Corrupt,
+ w = fn _ => fn (l, i) => Word8.fromInt i :: l }
+ end
+
+ type t = Word8Vector.vector
+ val eof = []
+ val convert = { w = Word8Vector.fromList o rev,
+ r = fn v => List.tabulate
+ (Word8Vector.length v, fn i => Word8Vector.sub (v, i)) }
+
+ type unit = unit
+ type bool = bool
+ type char = char
+ type word = word
+ type int = int
+ type string = string
+ type 'a vector = 'a vector
+
+ val unit = { r = fn l => (l, ()), w = fn (l, _) => l }
+ val bool = { r = fn ((a:Word8.word) :: r) => (r, 0w0 <> a) | _ => raise Corrupt,
+ w = fn (l, b) => (if b then (0w1:Word8.word) else 0w0) :: l }
+ val char = { r = fn (a :: r) => (r, Char.chr (Word8.toInt a)) | _ => raise Corrupt,
+ w = fn (l, c) => Word8.fromInt (Char.ord c) :: l }
+
+ val (w2s, s2w) = (Word8.fromInt o Word.toInt, Word.fromInt o Word8.toInt)
+ val (<<, >>, orb) = (Word.<<, Word.>>, Word.orb)
+ infix 5 << >>
+ infix 4 orb
+ val word = { r = fn (w0 :: w1 :: w2 :: w3 :: r) =>
+ (r, s2w w0 << 0w24 orb s2w w1 << 0w16 orb s2w w2 << 0w8 orb s2w w3)
+ | _ => raise Corrupt,
+ w = fn (l, w) =>
+ w2s w :: w2s (w >> 0w8) :: w2s (w >> 0w16) :: w2s (w >> 0w24) :: l }
+ val int = { r = fn l => let val (r, w) = #r word l in (r, Word.toInt w) end,
+ w = fn (l, i) => #w word (l, Word.fromInt i) }
+
+ fun rstring l =
+ let
+ val (l, i) = #r int l
+ val (s, l) = (List.take (l, i), List.drop (l, i))
+ val s = List.map (Char.chr o Word8.toInt) s
+ val s = implode s
+ in
+ (l, s)
+ end
+ fun wstring (l, s) =
+ List.map (Word8.fromInt o Char.ord) (rev (explode s))
+ @ #w int (l, String.size s)
+
+ fun rvector f l = (l, Vector.fromList [])
+ fun wvector f (l, v) = l (*!!! buggy *)
+
+ val string = { r = rstring, w = wstring }
+ val vector = { r = rvector, w = wvector }
+ end
Added: mltonlib/trunk/ca/terpstra/pickle/lib/pickle.mlb
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/lib/pickle.mlb 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/lib/pickle.mlb 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,8 @@
+local
+ $(SML_LIB)/basis/basis.mlb
+in
+ pickle.sig
+ pickle.sml
+ binary.sml
+ text.sml
+end
Added: mltonlib/trunk/ca/terpstra/pickle/lib/pickle.sig
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/lib/pickle.sig 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/lib/pickle.sig 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,56 @@
+signature PICKLER_BASE =
+ sig
+ type rt
+ type wt
+ type 'a r = rt -> rt * 'a
+ type 'a w = wt * 'a -> wt
+ val opts: { r: int -> int r, w: int -> int w }
+ end
+
+signature PICKLER_SIMPLE =
+ sig
+ structure Base : PICKLER_BASE
+ type t
+
+ val eof: Base.wt
+ val convert: { r: t -> Base.rt, w: Base.wt -> t }
+ end
+
+signature PICKLER =
+ sig
+ include PICKLER_SIMPLE
+
+ type unit = unit
+ type bool = bool
+ type char = char
+ type word = word
+ type int = int
+ type string = string
+ type 'a vector = 'a vector
+
+ (* real, substring, exn, 'a array, 'a list, 'a ref, 'a array, order, 'a option *)
+ val unit: { r: unit Base.r, w: unit Base.w }
+ val bool: { r: bool Base.r, w: bool Base.w }
+ val char: { r: char Base.r, w: char Base.w }
+ val word: { r: word Base.r, w: word Base.w }
+ val int: { r: int Base.r, w: int Base.w }
+ val string: { r: string Base.r, w: string Base.w }
+ val vector: { r: 'a Base.r -> 'a vector Base.r,
+ w: 'a Base.w -> 'a vector Base.w }
+ end
+
+signature PICKLE =
+ sig
+ structure Base : PICKLER_BASE
+
+ type t
+ type 'a pickle = { r: 'a Base.r, w: 'a Base.w }
+
+ val compose1: { r: 'a Base.r -> 'b Base.r, w: 'a Base.w -> 'b Base.w }
+ -> 'a pickle -> 'b pickle
+ val compose2: { r: 'a1 Base.r * 'a2 Base.r -> 'b Base.r,
+ w: 'a1 Base.w * 'a2 Base.w -> 'b Base.w }
+ -> 'a1 pickle * 'a2 pickle -> 'b pickle
+
+ val pickle: 'a pickle -> { r: t -> 'a, w: 'a -> t }
+ end
Added: mltonlib/trunk/ca/terpstra/pickle/lib/pickle.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/lib/pickle.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/lib/pickle.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,14 @@
+functor Pickle(P : PICKLER_SIMPLE) :> PICKLE =
+ struct
+ structure Base = P.Base
+ type 'a pickle = { r: 'a Base.r, w: 'a Base.w }
+ type t = P.t
+
+ fun compose1 {r=rf, w=wf} {r=r1, w=w1} = {r=rf r1, w=wf w1}
+ fun compose2 {r=rf, w=wf} ({r=r1, w=w1}, {r=r2, w=w2}) = {r=rf(r1,r2), w=wf(w1,w2)}
+
+ fun pickle ({r, w}: 'a pickle) =
+ { r = fn t => (#2 o r o (#r P.convert)) t,
+ w = fn x => (#w P.convert) (w (P.eof, x)) }
+ end
+
\ No newline at end of file
Added: mltonlib/trunk/ca/terpstra/pickle/lib/text.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/lib/text.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/lib/text.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,66 @@
+structure Binary : PICKLER =
+ struct
+ exception Corrupt
+
+ structure Base =
+ struct
+ type wt = Word8.word list
+ type rt = Word8.word list
+ type 'a r = rt -> rt * 'a
+ type 'a w = wt * 'a -> wt
+
+ val opts = { r = fn _ => fn (a :: r) => (r, Word8.toInt a) | _ => raise Corrupt,
+ w = fn _ => fn (l, i) => Word8.fromInt i :: l }
+ end
+
+ type t = Word8Vector.vector
+ val eof = []
+ val convert = { w = Word8Vector.fromList o rev,
+ r = fn v => List.tabulate
+ (Word8Vector.length v, fn i => Word8Vector.sub (v, i)) }
+
+ type unit = unit
+ type bool = bool
+ type char = char
+ type word = word
+ type int = int
+ type string = string
+ type 'a vector = 'a vector
+
+ val unit = { r = fn l => (l, ()), w = fn (l, _) => l }
+ val bool = { r = fn ((a:Word8.word) :: r) => (r, 0w0 <> a) | _ => raise Corrupt,
+ w = fn (l, b) => (if b then (0w1:Word8.word) else 0w0) :: l }
+ val char = { r = fn (a :: r) => (r, Char.chr (Word8.toInt a)) | _ => raise Corrupt,
+ w = fn (l, c) => Word8.fromInt (Char.ord c) :: l }
+
+ val (w2s, s2w) = (Word8.fromInt o Word.toInt, Word.fromInt o Word8.toInt)
+ val (<<, >>, orb) = (Word.<<, Word.>>, Word.orb)
+ infix 5 << >>
+ infix 4 orb
+ val word = { r = fn (w0 :: w1 :: w2 :: w3 :: r) =>
+ (r, s2w w0 << 0w24 orb s2w w1 << 0w16 orb s2w w2 << 0w8 orb s2w w3)
+ | _ => raise Corrupt,
+ w = fn (l, w) =>
+ w2s w :: w2s (w >> 0w8) :: w2s (w >> 0w16) :: w2s (w >> 0w24) :: l }
+ val int = { r = fn l => let val (r, w) = #r word l in (r, Word.toInt w) end,
+ w = fn (l, i) => #w word (l, Word.fromInt i) }
+
+ fun rstring l =
+ let
+ val (l, i) = #r int l
+ val (s, l) = (List.take (l, i), List.drop (l, i))
+ val s = List.map (Char.chr o Word8.toInt) s
+ val s = implode s
+ in
+ (l, s)
+ end
+ fun wstring (l, s) =
+ List.map (Word8.fromInt o Char.ord) (rev (explode s))
+ @ #w int (l, String.size s)
+
+ fun rvector f l = (l, Vector.fromList [])
+ fun wvector f (l, v) = l (*!!! buggy *)
+
+ val string = { r = rstring, w = wstring }
+ val vector = { r = rvector, w = wvector }
+ end
Added: mltonlib/trunk/ca/terpstra/pickle/main.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/main.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/main.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,66 @@
+fun prerr s =
+ TextIO.outputSubstr (TextIO.stdErr, Substring.full s)
+fun help () = (
+ prerr "Usage: pickle {functor-name} < {input-file} > {output-file}\n";
+ OS.Process.exit OS.Process.failure)
+
+structure LrVals = TMLLrValsFun(structure Token = LrParser.Token)
+structure Lex = TMLLexFun(structure Tokens = LrVals.Tokens)
+structure Parse = Join(structure ParserData = LrVals.ParserData
+ structure Lex = Lex
+ structure LrParser = LrParser)
+
+val name =
+ case CommandLine.arguments () of
+ (x :: []) => x
+ | (x :: r) => ""
+ | [] => ""
+val () = if name = "" then help () else ()
+
+fun signame s =
+ let
+ fun chr (i, c, t) =
+ if i <> 0 andalso Char.isUpper c andalso
+ not (Char.isUpper (String.sub (s, i - 1)))
+ then #"_" :: Char.toUpper c :: t
+ else Char.toUpper c :: t
+ in
+ implode (CharVector.foldri chr [] s)
+ end
+
+val argname = signame name ^ "_ARG"
+val signame = signame name
+
+fun error (s, (), ()) = print ("Error: " ^ s ^ "\n")
+fun reader _ =
+ case TextIO.inputLine TextIO.stdIn of
+ SOME x => x
+ | NONE => ""
+
+val stream = Parse.makeLexer reader
+val lookahead = 30
+val ast = #1 (Parse.parse (lookahead, stream, error, ()))
+val (start, ast) = tag ast
+
+fun dump l = List.app print (List.rev l)
+fun rungen f = #1 (List.foldl f ([], Map.empty) ast)
+
+val () = (
+ print ("signature " ^ argname ^ " =\n");
+ print (" sig\n");
+ print (" structure Base : SERIAL_BASE\n");
+ dump (rungen import);
+ print (" end\n\n");
+ print ("signature " ^ signame ^ " =\n");
+ print (" sig\n");
+ print (" structure Base : SERIAL_BASE\n");
+ print (" structure Arg : " ^ argname ^ "\n");
+ dump (rungen export);
+ print (" end\n\n");
+ print ("functor " ^ name ^ "(Arg : " ^ argname ^ ") : " ^ signame ^ " =\n");
+ print (" struct\n");
+ print (" structure Base = Arg.Base\n");
+ print (" structure Arg = Arg\n");
+ print (" exception Corrupt\n");
+ dump (rungen (method start));
+ print (" end\n"))
Added: mltonlib/trunk/ca/terpstra/pickle/method.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/method.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/method.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,126 @@
+local
+ fun record (n, typ) l = l && n && "=" ++ inline typ
+ and inline node l =
+ case node of
+ (RECORD v) =>
+ l && "{ " ++ sfoldl (record, ", ", v) && " }"
+ | (RECURSIVE (_, _, t)) => l && t
+ | (TUPLE v) =>
+ l && "(" ++ sfoldl (inline, ", ", v) && ")"
+ | (TYVAR (_, t, _)) => l && t
+in
+ val pattern = inline
+end
+
+fun method start (arg as ((data, bind), (l, scope))) =
+ let
+ val withscope = Map.union (scope, defd data)
+ val datascope = Map.union (withscope, defd bind)
+ exception Undefined
+
+ fun mapOpt (f, NONE) l = l
+ | mapOpt (f, SOME x) l = l ++ f x
+
+ fun data_opts { typ = (ropt, wopt, v), ... } l =
+ l && "val (" && ropt && ", " && wopt && ") = ((#r Base.opts) "
+ && Int.toString (Vector.length v) && ", (#w Base.opts) "
+ && Int.toString (Vector.length v) && ")\n"
+
+ fun write_inline scope =
+ let
+ fun fnhelper (typ, f) l =
+ l && " fun " && f && " (a, " ++ pattern typ && ") =\n"
+ && " let\n val a = a\n" ++ inline typ
+ && " in\n a\n end\n"
+ and invoke n l =
+ case Map.fetch scope n of
+ NONE => l && "(#w Arg." && n && ")"
+ | (SOME {reader=_, writer}) => l && writer
+ and inline node l =
+ case node of
+ (RECORD v) => l ++ foldl (inline o #2, v)
+ | (TUPLE v) => l ++ foldl (inline, v)
+ | (TYVAR (_, t, f)) =>
+ l && " val a = " && f && " (a, " && t && ")\n"
+ | (RECURSIVE (n, v, t)) =>
+ l ++ foldl (fnhelper, v) && " val a = "
+ ++ invoke n && " "
+ ++ tuple (#2, v) && "(a, " && t && ")\n"
+ in
+ inline
+ end
+
+ fun write_bind { name=_, reader=_, writer, tyvars, typ } l =
+ l && "and " && writer ++ tuple (#2, tyvars)
+ && " (a, " ++ pattern typ && ") =\n"
+ && " let\n val a = a\n" ++ write_inline withscope typ
+ && " in\n a\n end\n"
+
+ fun write_data { name=_, reader=_, writer, tyvars, typ = (_, wopt, v) } l =
+ let
+ fun constr (opt, (constr, typo)) l =
+ l && (if opt = 0 then " " else "| ")
+ && "(" && constr && " " ++ mapOpt (pattern, typo) && ") =>\n"
+ && " let\n val a = " && wopt && " (a, " && Int.toString opt && ")\n"
+ ++ mapOpt (write_inline datascope, typo) && " in\n a\n end\n"
+ in
+ l && "and " && writer && " " ++ tuple (#2, tyvars)
+ && "(a, x) = case x of\n"
+ ++ foldli (constr, v)
+ end
+
+ fun read_inline scope =
+ let
+ fun fnhelper (typ, f) l =
+ l && " fun " && f && " a =\n let\n"
+ && " val a = a\n" ++ inline typ && " in\n (a, "
+ ++ pattern typ && ")\n end\n"
+ and invoke n l =
+ case Map.fetch scope n of
+ NONE => l && "(#r Arg." && n && ")"
+ | (SOME {reader, writer=_}) => l && reader
+ and inline node l =
+ case node of
+ (RECORD v) => l ++ foldl (inline o #2, v)
+ | (TUPLE v) => l ++ foldl (inline, v)
+ | (TYVAR (_, t, f)) =>
+ l && " val (a, " && t && ") = " && f && " a\n"
+ | (RECURSIVE (n, v, t)) =>
+ l ++ foldl (fnhelper, v) && " val (a, " && t
+ && ") = " ++ invoke n && " " ++ tuple (#2, v) && "a\n"
+ in
+ inline
+ end
+
+ fun read_bind { name=_, reader, writer=_, tyvars, typ } l =
+ l && "and " && reader && " " ++ tuple (#2, tyvars) && "a =\n"
+ && " let\n val a = a\n" ++ read_inline withscope typ && " in\n"
+ && " (a, " ++ pattern typ && ")\n end\n"
+
+ fun read_data { name=_, reader, writer=_, tyvars, typ = (ropt, _, v) } l =
+ let
+ fun constr (opt, (constr, typo)) l =
+ l && (if opt = 0 then " " else "| ")
+ && "(a, " && Int.toString opt && ") =>\n"
+ && " let\n val a = a\n"
+ ++ mapOpt (read_inline datascope, typo)
+ && " in\n (a, " && constr && " "
+ ++ mapOpt (pattern, typo) && ")\n end\n"
+ in
+ l && "and " && reader && " " ++ tuple (#2, tyvars) && "a =\n"
+ && "case " && ropt && " a of\n"
+ ++ foldli (constr, v) && "| (a, _) => raise Corrupt\n"
+ end
+
+ fun binds {name, reader, writer, tyvars=_, typ=_} l =
+ l && "val " && name && " = "
+ && " { r = " && reader && ", w = " && writer && " }\n"
+ in
+ (#1 (dtype arg)
+ ++ foldl (data_opts, data)
+ && "fun " && start && " x = x\n"
+ ++ foldl (write_bind, bind) ++ foldl (write_data, data)
+ ++ foldl ( read_bind, bind) ++ foldl ( read_data, data)
+ ++ foldl (binds, bind) ++ foldl (binds, data),
+ datascope)
+ end
Added: mltonlib/trunk/ca/terpstra/pickle/pickle.mlb
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/pickle.mlb 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/pickle.mlb 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,17 @@
+local
+ $(SML_LIB)/basis/basis.mlb
+ $(SML_LIB)/mlyacc-lib/mlyacc-lib.mlb
+in
+ tree.sml
+ ast.sml
+ tml.grm.sig
+ tml.lex.sml
+ tml.grm.sml
+ gen.sml
+ tag.sml
+ type.sml
+ import.sml
+ export.sml
+ method.sml
+ main.sml
+end
Added: mltonlib/trunk/ca/terpstra/pickle/tag.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tag.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tag.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,57 @@
+fun tag ast =
+ let
+ fun topdefd ((data, bind), m) =
+ Map.union (Map.union (m, defd bind), defd data)
+ fun toSet m = Map.foldl (fn ((k, _), s) => Set.insert s k) Set.empty m
+ val ids = ref (toSet (List.foldl topdefd Map.empty ast))
+
+ val c = ref 0
+ fun pick pfx () =
+ let
+ val id = pfx ^ Int.toString (!c)
+ val () = c := (!c) + 1
+ in
+ if Set.member (!ids) id then pick pfx () else
+ id before ids := Set.insert (!ids) id
+ end
+ val pickId = pick "v_"
+ val pickFn = pick "f_"
+
+ fun tymap tyvars = Vector.map (fn (x, _) => (x, pickFn ())) tyvars
+ fun findFn tyvars n =
+ let
+ exception UnboundTyvar
+ val x = Vector.find (fn (m, _) => n = m) tyvars
+ in
+ case x of
+ NONE => raise UnboundTyvar
+ | SOME (_, f) => f
+ end
+
+ fun inline tyvars typ =
+ case typ of
+ (RECORD v) =>
+ RECORD (Vector.map (fn (n, t) => (n, inline tyvars t)) v)
+ | (TUPLE v) =>
+ TUPLE (Vector.map (inline tyvars) v)
+ | (TYVAR (tyvar, _, _)) =>
+ TYVAR (tyvar, pickId (), findFn tyvars tyvar)
+ | (RECURSIVE (name, tyv, _)) =>
+ RECURSIVE (name, Vector.map (maprec tyvars) tyv, pickId ())
+ and maprec tyvars (ty, _) = (inline tyvars ty, pickFn ())
+
+ fun bindtyp f { name, reader, writer, tyvars, typ } =
+ let val tyvars = tymap tyvars
+ in { name = name, reader = pickFn (), writer = pickFn (),
+ tyvars = tyvars, typ = f tyvars typ } end
+
+ fun datatyp tyvars (_, _, v) =
+ (pickFn (), pickFn (), Vector.map
+ (fn (name, inlineo) => (name, Option.map (inline tyvars) inlineo))
+ v)
+
+ fun process (data, bind) =
+ (Vector.map (bindtyp datatyp) data, Vector.map (bindtyp inline) bind)
+ in
+ (pickFn (), List.map process ast)
+ end
Added: mltonlib/trunk/ca/terpstra/pickle/tests/Makefile
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tests/Makefile 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tests/Makefile 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,13 @@
+TARGETS = $(patsubst %.test,%,$(wildcard *.test))
+
+all: $(TARGETS)
+clean:
+ rm -f *.sml $(TARGETS)
+
+%.sml: %.test
+ cp ../sb.sig $@.tmp
+ ../pickle Test < $< >> $@.tmp
+ mv $@.tmp $@
+
+%: %.sml
+ mlton $<
Added: mltonlib/trunk/ca/terpstra/pickle/tests/double.test
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tests/double.test 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tests/double.test 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,2 @@
+datatype ('a, 'b) union = LEFT of 'a | RIGHT of 'b
+type ('a, 'b) pair = 'a * 'b
Added: mltonlib/trunk/ca/terpstra/pickle/tests/rebind.test
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tests/rebind.test 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tests/rebind.test 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,10 @@
+(* use old binding *)
+type pair = string * int
+
+(* flip bindings *)
+type int = string
+and string = int
+
+datatype opt =
+ VECTOR of opt * string * int
+ | NADA of opt * pair
Added: mltonlib/trunk/ca/terpstra/pickle/tests/recursive.test
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tests/recursive.test 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tests/recursive.test 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1 @@
+type 'a x = 'a vector list set
Added: mltonlib/trunk/ca/terpstra/pickle/tests/scope.test
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tests/scope.test 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tests/scope.test 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,7 @@
+(* Note that {} and unit are different because unit can be rebound *)
+datatype d1 = C of { baz : d1 * int } list | D of {} | E of t1
+and d2 = F of d1 | G of d2 | Q of t2
+withtype t1 = string * d2
+and t2 = string * unit
+
+datatype 'a d3 = datatype list
Added: mltonlib/trunk/ca/terpstra/pickle/tests/tree.test
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tests/tree.test 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tests/tree.test 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,2 @@
+datatype color = RED | BLACK
+datatype 'a tree = LEAF | NODE of color * 'a tree * 'a * 'a tree
Added: mltonlib/trunk/ca/terpstra/pickle/tml.grm
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tml.grm 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tml.grm 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,143 @@
+%%
+
+(* bugs: no functor, structure, or abstype support *)
+
+%term LONGID of string
+ | TYVAR of string
+ | AND | ASTERISK | BAR | COLON | COMMA | DATATYPE | EOF | EQUALOP
+ | EQTYPE | LBRACE | LPAREN | OF | OP | RBRACE | RPAREN | TYPE | WITHTYPE
+
+%nonterm file of toplevel_typ list
+ | node of toplevel_typ
+ | typBind of toplevel_typ
+ | typBind' of inline_typ bind_typ list
+ | typBind'' of inline_typ bind_typ list
+ | tyvars of (tyvar * tag) vector
+ | tyvar_pc of (tyvar * tag) list
+ | datatypeRhs of toplevel_typ
+ | db of data_typ bind_typ
+ | dbs of data_typ bind_typ list
+ | withtypes of inline_typ bind_typ list
+ | constrs of (string * inline_typ option) list
+ | constr of string * inline_typ option
+ | opcon of string
+ | con of string
+ | longid of string
+ | longidnA of string
+ | id of string
+ | idnA of string
+ | tyvar of tyvar
+ | tycon of string
+ | longtycon of string
+ | ty of inline_typ
+ | ty' of inline_typ
+ | tlabels of (string * inline_typ) list
+ | tlabel of string * inline_typ
+ | ty0_pc of (inline_typ * tag) list
+ | tuple_ty of inline_typ list
+
+%pos unit
+%verbose
+%eop EOF
+%noshift EOF
+%name TML
+%keyword AND DATATYPE EQTYPE OF OP TYPE WITHTYPE
+
+%value LONGID ("bogus")
+%value TYVAR ("'a")
+
+%%
+
+file : ([])
+ | node file (node :: file)
+
+node : DATATYPE datatypeRhs (datatypeRhs)
+ | TYPE typBind (typBind)
+ | EQTYPE typBind (typBind)
+
+(* ==================== Type ============ *)
+
+typBind : typBind' ((Vector.fromList [], Vector.fromList typBind'))
+
+typBind' : tyvars tycon EQUALOP ty typBind''
+ ({ name = tycon, reader = "", writer = "", tyvars = tyvars,
+ typ = ty } :: typBind'')
+
+typBind'' : ([])
+ | AND typBind' (typBind')
+
+tyvars : (Vector.fromList [])
+ | tyvar (Vector.fromList [(tyvar, "")])
+ | LPAREN tyvar_pc RPAREN (Vector.fromList tyvar_pc)
+
+tyvar_pc : tyvar ([(tyvar, "")])
+ | tyvar COMMA tyvar_pc ((tyvar, "") :: tyvar_pc)
+
+(* ==================== DataType ============ *)
+
+datatypeRhs : tyvars tycon EQUALOP DATATYPE longtycon
+ (Vector.fromList [], Vector.fromList
+ [{ name = tycon, reader = "", writer = "", tyvars = tyvars,
+ typ = RECURSIVE (longtycon,
+ Vector.map (fn (x, y) => (TYVAR (x, "", ""), y))
+ tyvars, "")}])
+ | dbs withtypes
+ ((Vector.fromList dbs, Vector.fromList withtypes))
+
+dbs : db ([db])
+ | db AND dbs (db :: dbs)
+
+db : tyvars tycon EQUALOP constrs
+ ({ name = tycon, reader = "", writer = "", tyvars = tyvars,
+ typ = ("", "", Vector.fromList constrs) })
+
+constrs : constr ([constr])
+ | constr BAR constrs (constr :: constrs)
+
+constr : opcon (opcon, NONE)
+ | opcon OF ty (opcon, SOME ty)
+
+opcon : con (con)
+ | OP con (con)
+
+withtypes : ([])
+ | WITHTYPE typBind' (typBind')
+
+(* ==================== Terminals ============ *)
+
+longidnA : LONGID (LONGID)
+longid : longidnA (longidnA)
+ | ASTERISK ("*")
+
+id : longid (longid) (* forbid '.' in name !!! *)
+idnA : longidnA (longidnA) (* forbid '.' in name !!! *)
+
+con : id (id)
+tycon : idnA (idnA)
+longtycon : idnA (idnA)
+
+tyvar : TYVAR (TYVAR)
+
+(* ==================== Types ================ *)
+
+ty : tuple_ty (TUPLE (Vector.fromList tuple_ty))
+ | ty' (ty')
+
+ty' : tyvar (TYVAR (tyvar, "", ""))
+ | LBRACE tlabels RBRACE (RECORD (Vector.fromList tlabels))
+ | LBRACE RBRACE (RECORD (Vector.fromList []))
+ | LPAREN ty0_pc RPAREN longtycon (RECURSIVE (longtycon, Vector.fromList ty0_pc, ""))
+ | LPAREN ty RPAREN (ty)
+ | ty' longtycon (RECURSIVE (longtycon, Vector.fromList [(ty', "")], ""))
+ | longtycon (RECURSIVE (longtycon, Vector.fromList [], ""))
+
+tlabel : id COLON ty (id, ty)
+
+tlabels : tlabel COMMA tlabels (tlabel :: tlabels)
+ | tlabel ([tlabel])
+
+tuple_ty : ty' ASTERISK tuple_ty (ty' :: tuple_ty)
+ | ty' ASTERISK ty' ([ty'1, ty'2])
+
+ty0_pc : ty COMMA ty ([(ty1, ""), (ty2, "")])
+ | ty COMMA ty0_pc ((ty, "") :: ty0_pc)
Added: mltonlib/trunk/ca/terpstra/pickle/tml.lex
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tml.lex 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tml.lex 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,71 @@
+val nix = ((), ())
+fun eof () = Tokens.EOF nix
+
+type svalue = Tokens.svalue
+type ('a, 'b) token = ('a, 'b) Tokens.token
+type lexresult = (svalue, unit) token
+type arg = unit
+type pos = unit
+
+val commentLevel = ref 0
+
+%%
+
+%reject
+%s A;
+%header (functor TMLLexFun (structure Tokens : TML_TOKENS));
+
+alphanum=[A-Za-z'_0-9]*;
+alphanumId=[A-Za-z]{alphanum};
+sym=[-!%&$+/:<=>?@~`^|#*]|"\\";
+symId={sym}+;
+id={alphanumId}|{symId};
+longid={id}("."{id})*;
+ws=("\012"|[\t\ ])*;
+nrws=("\012"|[\t\ ])+;
+cr="\013";
+nl="\010";
+eol=({cr}{nl}|{nl}|{cr});
+num=[0-9]+;
+frac="."{num};
+exp=[eE](~?){num};
+real=(~?)(({num}{frac}?{exp})|({num}{frac}{exp}?));
+hexDigit=[0-9a-fA-F];
+hexnum={hexDigit}+;
+
+%%
+<INITIAL>{ws} => (continue ());
+<INITIAL>{eol} => (continue ());
+<INITIAL>"," => (Tokens.COMMA nix);
+<INITIAL>"{" => (Tokens.LBRACE nix);
+<INITIAL>"}" => (Tokens.RBRACE nix);
+<INITIAL>"(" => (Tokens.LPAREN nix);
+<INITIAL>")" => (Tokens.RPAREN nix);
+<INITIAL>"|" => (Tokens.BAR nix);
+<INITIAL>":" => (Tokens.COLON nix);
+<INITIAL>"=" => (Tokens.EQUALOP nix);
+<INITIAL>"and" => (Tokens.AND nix);
+<INITIAL>"datatype" => (Tokens.DATATYPE nix);
+<INITIAL>"eqtype" => (Tokens.EQTYPE nix);
+<INITIAL>"of" => (Tokens.OF nix);
+<INITIAL>"op" => (Tokens.OP nix);
+<INITIAL>"type" => (Tokens.TYPE nix);
+<INITIAL>"withtype" => (Tokens.WITHTYPE nix);
+<INITIAL>"'"{alphanum}? => (Tokens.TYVAR (yytext, (), ()));
+<INITIAL>{longid} =>
+ (case yytext of
+ "*" => Tokens.ASTERISK nix
+ | _ => Tokens.LONGID (yytext, (), ()));
+<INITIAL>"(*" => (YYBEGIN A
+ ; commentLevel := 1
+ ; continue ());
+<INITIAL>. => (print ("parsing: illegal token\n") ;
+ continue ());
+
+<A>"(*" => (commentLevel := !commentLevel + 1; continue ());
+<A>"*)" => (commentLevel := !commentLevel - 1
+ ; if 0 = !commentLevel then YYBEGIN INITIAL else ()
+ ; continue ());
+<A>. => (continue ());
+<A>{ws} => (continue ());
+<A>{eol} => (continue ());
Added: mltonlib/trunk/ca/terpstra/pickle/tree.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/tree.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/tree.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,173 @@
+signature MAP =
+ sig
+ type k
+ type 'a t
+
+ val empty: 'a t
+
+ val app: (k * 'a -> unit) -> 'a t -> unit
+ val filter: (k * 'a -> bool) -> 'a t -> 'a t
+ val map: (k * 'a -> k * 'b) -> 'a t -> 'b t
+
+ val foldl: ((k * 'a) * 'b -> 'b) -> 'b -> 'a t -> 'b
+ val foldr: ((k * 'a) * 'b -> 'b) -> 'b -> 'a t -> 'b
+
+ val fromList: (k * 'a) list -> 'a t
+ val fromVector: (k * 'a) vector -> 'a t
+
+ val fetch: 'a t -> k -> 'a option
+ val insert: 'a t -> k * 'a -> 'a t
+
+ (* put smaller set on the right *)
+ val union: 'a t * 'a t -> 'a t
+ val intersection: 'a t * 'a t -> 'a t
+ val difference: 'a t * 'a t -> 'a t
+ end
+
+signature SET =
+ sig
+ type k
+ type t
+
+ val empty: t
+
+ val app: (k -> unit) -> t -> unit
+ val filter: (k -> bool) -> t -> t
+ val map: (k -> k ) -> t -> t
+
+ val foldl: (k * 'a -> 'a) -> 'a -> t -> 'a
+ val foldr: (k * 'a -> 'a) -> 'a -> t -> 'a
+
+ val fromList: k list -> t
+ val fromVector: k vector -> t
+
+ val member: t -> k -> bool
+ val insert: t -> k -> t
+
+ (* put smaller set on the right *)
+ val union: t * t -> t
+ val intersection: t * t -> t
+ val difference: t * t -> t
+ end
+
+signature TREE_ORDER =
+ sig
+ type 'a member
+ val order: 'a member * 'a member -> order
+ end
+
+functor Tree(O : TREE_ORDER) =
+ struct
+ open O
+ datatype colour = Red | Black
+ datatype 'a tree = Node of colour * 'a tree * 'a member * 'a tree | Leaf
+
+ val empty = Leaf
+
+ fun app f Leaf = ()
+ | app f (Node (_, l, v, r)) =
+ (app f l; f v; app f r)
+
+ fun map f Leaf = Leaf
+ | map f (Node (c, l, v, r)) =
+ Node (c, map f l, f v, map f r)
+
+ fun foldl f b Leaf = b
+ | foldl f b (Node (c, l, v, r)) =
+ foldl f (f (v, foldl f b l)) r
+
+ fun foldr f b Leaf = b
+ | foldr f b (Node (c, l, v, r)) =
+ foldr f (f (v, foldr f b r)) l
+
+ fun member Leaf _ = false
+ | member (Node (_, l, v, r)) x =
+ case order (x, v) of
+ LESS => member l x
+ | GREATER => member r x
+ | EQUAL => true
+
+ fun balance x = case x of
+ (Black, Node (Red, Node (Red, a, x, b), y, c), z, d) =>
+ Node (Red, Node (Black, a, x, b), y, Node (Black, c, z, d))
+ | (Black, Node (Red, a, x, Node (Red, b, y, c)), z, d) =>
+ Node (Red, Node (Black, a, x, b), y, Node (Black, c, z, d))
+ | (Black, a, x, Node (Red, Node (Red, b, y, c), z, d)) =>
+ Node (Red, Node (Black, a, x, b), y, Node (Black, c, z, d))
+ | (Black, a, x, Node (Red, b, y, Node (Red, c, z, d))) =>
+ Node (Red, Node (Black, a, x, b), y, Node (Black, c, z, d))
+ | (a, b, c, d) =>
+ Node (a, b, c, d)
+
+ fun insert t x =
+ let
+ fun ins Leaf = Node (Red, Leaf, x, Leaf)
+ | ins (Node (c, a, y, b)) =
+ case order (x, y) of
+ LESS => balance (c, ins a, y, b)
+ | GREATER => balance (c, a, y, ins b)
+ | EQUAL => Node (c, a, x, b)
+ in
+ case ins t of
+ Node (_, a, y, b) => Node (Black, a, y, b)
+ | Leaf => Leaf
+ end
+
+ fun fromList l =
+ List.foldl (fn (v, t) => insert t v) empty l
+ fun fromVector v =
+ Vector.foldl (fn (v, t) => insert t v) empty v
+
+ fun filter f t =
+ foldl (fn (v, t) => if f v then insert t v else t) empty t
+
+ fun union (x, y) =
+ foldl (fn (v, t) => insert t v) x y
+ fun intersection (x, y) =
+ filter (member x) y
+ fun difference (x, y) =
+ filter (not o member y) x
+ end
+
+signature KEY_ORDER =
+ sig
+ type k
+ val order: k * k -> order
+ end
+
+functor Set(O : KEY_ORDER) :> SET where type k = O.k =
+ struct
+ structure TO =
+ struct
+ type 'a member = O.k
+ val order = O.order
+ end
+
+ structure Tree = Tree(TO)
+ open Tree
+
+ type k = O.k
+ type t = unit tree
+ end
+
+functor Map(O : KEY_ORDER) :> MAP where type k = O.k =
+ struct
+ structure TO =
+ struct
+ type 'a member = O.k * 'a
+ fun order ((x, _), (y, _)) = O.order (x, y)
+ end
+
+ structure Tree = Tree(TO)
+ open Tree
+
+ type k = O.k
+ type 'a t = 'a tree
+
+ fun fetch Leaf _ = NONE
+ | fetch (Node (_, l, (k, v), r)) x =
+ case O.order (x, k) of
+ LESS => fetch l x
+ | GREATER => fetch r x
+ | EQUAL => SOME v
+ end
Added: mltonlib/trunk/ca/terpstra/pickle/type.sml
===================================================================
--- mltonlib/trunk/ca/terpstra/pickle/type.sml 2006-12-19 02:56:05 UTC (rev 4983)
+++ mltonlib/trunk/ca/terpstra/pickle/type.sml 2006-12-19 02:56:32 UTC (rev 4984)
@@ -0,0 +1,41 @@
+fun dtype ((data, bind), (l, scope)) =
+ let
+ val withscope = Map.union (scope, defd data)
+ val datascope = Map.union (withscope, defd bind)
+
+ fun dump scope =
+ let
+ fun record (n, typ) l = l && n && ": " ++ inline typ
+ and tyvars v l =
+ if Vector.length v = 0 then l else
+ l && "(" ++ sfoldl (inline o #1, ", ", v) && ") "
+ and invoke n l =
+ case Map.fetch scope n of
+ NONE => l && "Arg." && n
+ | SOME _ => l && n
+ and inline node l =
+ case node of
+ (RECORD v) => l && "{ " ++ sfoldl (record, ", ", v) && " }"
+ | (RECURSIVE (n, v, _)) => l ++ tyvars v ++ invoke n
+ | (TUPLE v) => l ++ sfoldl (inline, " * ", v)
+ | (TYVAR (tyvar, _, _)) => l && tyvar
+ in
+ inline
+ end
+
+ fun withtyp (i, { name, reader=_, writer=_, tyvars, typ }) l =
+ l && (if i = 0 then "type " else "and ")
+ ++ tuple (#1, tyvars) && name && " = " ++ dump withscope typ && "\n"
+
+ fun const (n, NONE) l = l && n && "\n"
+ | const (n, SOME typ) l = l && n && " of " ++ dump datascope typ && "\n"
+ fun datatyp (i, { name, reader=_, writer=_, tyvars, typ = (_, _, v) }) l =
+ l && (if i = 0 then " datatype " else " and ")
+ ++ tuple (#1, tyvars) && name && " = " ++ sfoldl (const, "\t| ", v)
+ in
+ (l ++ foldli (datatyp, data)
+ && (if Vector.length data <> 0 andalso
+ Vector.length bind <> 0 then "with" else "")
+ ++ foldli (withtyp, bind),
+ datascope)
+ end
More information about the MLton-commit
mailing list