File: Reflect.k

package info (click to toggle)
kaya 0.4.2-4
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 4,448 kB
  • ctags: 1,694
  • sloc: cpp: 9,536; haskell: 7,461; sh: 3,013; yacc: 910; makefile: 816; perl: 90
file content (101 lines) | stat: -rw-r--r-- 3,974 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/** -*-C-*-ish
    Kaya standard library
    Copyright (C) 2004, 2005, 2006 Edwin Brady

    This file is distributed under the terms of the GNU Lesser General
    Public Licence. See COPYING for licence.
*/
"<summary>Inspect Kaya data values directly</summary>
<prose>This module allows you to convert primitive Kaya data types to a representation which may be inspected and edited directly within Kaya, and then convert this representation back again. This capability can then be used to save Kaya values persistently as the <moduleref>Pickle</moduleref> does, or to allow arbitrary Kaya values to be interactively constructed by the application user.</prose>"
module Reflect;

import Prelude;

"<summary>Data value, reflected as a kaya data structure.</summary>
<prose>A Data value, reflected as a kaya data structure.
Any cycles or shared values in the structure will also be shared in the
reflected structure. Note that the <code>fnid</code> in the <code>DClosure</code>
constructor may change if the program is recompiled, but is guaranteed to
be the same if the binary is unchanged.</prose>"
public data Data 
    = DInt(Int int)
    | DFloat(Float float)
    | DString(String string)
    | DArray([Data] array)
    | DUnion(Int tag, [Data] fields)
    | DClosure(Int fnid, [Data] args);

foreign "stdfuns.o" {
    pure Data doReflect(Ptr vm, a x) = funtable_reflect;
    pure val reifyUnion(Int tag, Int arity) = reifyUnion;
    pure val reifyClosure(Int fnid, Int arity) = reifyClosure;
    pure Void reifyUnionArgs(a union, [a] flds) = reifyUnionArgs;
    pure Void reifyClosureArgs(a clos, [a] args) = reifyClosureArgs;
}

"<argument name='value'>A value</argument>
<summary>Convert a value into a data representation of that value.</summary>
<prose>Convert a value into a data representation of that value.</prose>
<related><dataref>Data</dataref></related>
<related><functionref>reify</functionref></related>"
public Data reflect(a value) {
    return doReflect(getVM, value);
}

"<argument name='value'>A data representation</argument>
<summary>Convert a data representation back to the represented value.</summary>
<prose>Convert a data representation back to the represented value.</prose>
<related><dataref>Data</dataref></related>
<related><functionref>reflect</functionref></related>"
public a reify(Data val) {
    return reifyAux([], val);
}

private a reifyAux(var [(Data,a)] done, Data val) {
    for xs in done {
	if (identical(val,xs.fst)) {
	    return xs.snd;
	}
    }

    case val of {
	DInt(i) -> rv = subvert(i); push(done, (val,rv));
	| DString(str) -> rv = subvert(str); push(done, (val,rv));
	| DFloat(f) -> rv = subvert(f); push(done, (val,rv));
	| DArray(arr) -> rv = subvert(map(reify,arr));
	| DUnion(tag,arr) -> rv = reifyUnion(tag,size(arr));
	                     push(done, (val,rv));
			     reifyUnionArgs(rv, map(reifyAux@(done), arr));
	| DClosure(fn,arr) ->
	                     rv = reifyClosure(fn,size(arr));
	                     push(done, (val,rv));
			     reifyClosureArgs(rv, map(reifyAux@(done), arr));
    }
    return rv;
}

"<argument name='val'>A value</argument>
<summary>Print any value as a string</summary>
<prose>Prints any value as a string, including arrays, unions and closures. Note that what is printed is the run-time representation of the value, so <code>dump(just(5));</code> will print <samp>Tag1(5)</samp>, not <samp>just(5)</samp>.</prose>"
public Void dump(a val) {
    dumpAux(reflect(val));
    putStr("\n");
}

private Void dumpAux(Data val) {
    case val of {
	DInt(i) -> putStr(String(i));
	| DString(str) -> putStr(str);
	| DFloat(f) -> putStr(String(f));
	| DArray(arr) -> putStr("["); dumpArray(arr); putStr("]");
	| DUnion(tag,arr) -> putStr("Tag"+tag+"("); dumpArray(arr); putStr(")");
	| DClosure(fn,arr) -> putStr("FN"+fn+"("); dumpArray(arr); putStr(")");
    }
}

private Void dumpArray([Data] vals) {
    for x@i in vals {
	dumpAux(x);
	if (i<size(vals)-1) putStr(", ");
    }
}