tclbdd

Check-in [444573ad82]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:correct name of 'fdd' package to 'fddd'. Add 'project' method to bdd base code - no driver nor tests yet.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:444573ad82c174b5dec749ffed80a9b9ce0c082c
User & Date: kbk 2013-12-14 23:20:44
Context
2013-12-17
15:53
Renamed the 'fdd' subpackage to 'fddd'. (Finite Domain Decision Diagram is correct.) Added the machinery to include it in the [package] mechanism. Added 'foreach_fullsat' to expand out truth tables for SAT terms, and added test cases for the same. Added 'fddd::support' method (no tests yet) to list the finite domain variables that appear in a query term. Added test cases for 'fddd::domain' and friends, and fixed the bugs that the test cases exposed. check-in: 80342a5576 user: kbk tags: trunk
2013-12-14
23:20
correct name of 'fdd' package to 'fddd'. Add 'project' method to bdd base code - no driver nor tests yet. check-in: 444573ad82 user: kbk tags: trunk
2013-12-13
20:22
Remove dribble from minterm loader. Fix variables-out-of-order check in minterm loader. Add minterm loader test vectors. check-in: 3194251647 user: kbk tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclBdd.c.

143
144
145
146
147
148
149


150
151
152
153
154
155
156
...
275
276
277
278
279
280
281







282
283
284
285
286
287
288
...
361
362
363
364
365
366
367

368
369
370
371
372
373
374
....
1749
1750
1751
1752
1753
1754
1755



























































































1756
1757
1758
1759
1760
1761
1762
static int BddSystemNegateMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				 int, Tcl_Obj* const[]);
static int BddSystemNotnthvarMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				    int, Tcl_Obj* const[]);
static int BddSystemNthvarMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				 int, Tcl_Obj* const[]);
static int BddSystemProfileMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,


				  int, Tcl_Obj* const[]);
static int BddSystemQuantifyMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				   int, Tcl_Obj* const[]);
static int BddSystemRestrictMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				   int, Tcl_Obj* const[]);
static int BddSystemSatcountMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				   int, Tcl_Obj* const[]);
................................................................................
};
const static Tcl_MethodType BddSystemProfileMethodType = {
    TCL_OO_METHOD_VERSION_CURRENT, /* version */
    "profile",			   /* name */
    BddSystemProfileMethod,	   /* callProc */
    DeleteMethod,		   /* method delete proc */
    CloneMethod			   /* method clone proc */







};
const static Tcl_MethodType BddSystemQuantifyMethodType = {
    TCL_OO_METHOD_VERSION_CURRENT, /* version */
    "quantify",			   /* name */
    BddSystemQuantifyMethod,	   /* callProc */
    DeleteMethod,		   /* method delete proc */
    CloneMethod			   /* method clone proc */
................................................................................
    { "nand3",     &BddSystemTernopMethodType,   (ClientData) BDD_TERNOP_NAND },
    { "nor",       &BddSystemBinopMethodType,     (ClientData) BDD_BINOP_NOR },
    { "nor3",      &BddSystemTernopMethodType,    (ClientData) BDD_TERNOP_NOR },
    { "notnthvar", &BddSystemNotnthvarMethodType, NULL },
    { "nthvar",    &BddSystemNthvarMethodType,    NULL },
    { "oneof3",    &BddSystemTernopMethodType,  (ClientData) BDD_TERNOP_ONEOF },
    { "profile",   &BddSystemProfileMethodType,   NULL },

    { "restrict",  &BddSystemRestrictMethodType,  NULL },
    { "satcount",  &BddSystemSatcountMethodType,  NULL },
    { "simplify",  &BddSystemSimplifyMethodType,  NULL },
    { "twoof3",    &BddSystemTernopMethodType,  (ClientData) BDD_TERNOP_TWOOF },
    { "unset",     &BddSystemUnsetMethodType,     NULL },
    { "|",         &BddSystemBinopMethodType,     (ClientData) BDD_BINOP_OR },
    { "|3",        &BddSystemTernopMethodType,    (ClientData) BDD_TERNOP_OR },
................................................................................
	countv[i] = Tcl_NewWideIntObj((Tcl_WideInt) v[i]);
    }
    ckfree(v);
    Tcl_SetObjResult(interp, Tcl_NewListObj(n, countv));
    ckfree(countv);
    return TCL_OK;
}



























































































 
/*
 *-----------------------------------------------------------------------------
 *
 * BddSystemQuantifyMethod --
 *
 *	Quantifies a BDD with respect to a particular set of variables.







>
>







 







>
>
>
>
>
>
>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
...
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
....
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
static int BddSystemNegateMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				 int, Tcl_Obj* const[]);
static int BddSystemNotnthvarMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				    int, Tcl_Obj* const[]);
static int BddSystemNthvarMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				 int, Tcl_Obj* const[]);
static int BddSystemProfileMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				  int, Tcl_Obj* const[]);
static int BddSystemProjectMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				  int, Tcl_Obj* const[]);
static int BddSystemQuantifyMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				   int, Tcl_Obj* const[]);
static int BddSystemRestrictMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				   int, Tcl_Obj* const[]);
static int BddSystemSatcountMethod(ClientData, Tcl_Interp*, Tcl_ObjectContext,
				   int, Tcl_Obj* const[]);
................................................................................
};
const static Tcl_MethodType BddSystemProfileMethodType = {
    TCL_OO_METHOD_VERSION_CURRENT, /* version */
    "profile",			   /* name */
    BddSystemProfileMethod,	   /* callProc */
    DeleteMethod,		   /* method delete proc */
    CloneMethod			   /* method clone proc */
};
const static Tcl_MethodType BddSystemProjectMethodType = {
    TCL_OO_METHOD_VERSION_CURRENT, /* version */
    "profile",			   /* name */
    BddSystemProjectMethod,	   /* callProc */
    DeleteMethod,		   /* method delete proc */
    CloneMethod			   /* method clone proc */
};
const static Tcl_MethodType BddSystemQuantifyMethodType = {
    TCL_OO_METHOD_VERSION_CURRENT, /* version */
    "quantify",			   /* name */
    BddSystemQuantifyMethod,	   /* callProc */
    DeleteMethod,		   /* method delete proc */
    CloneMethod			   /* method clone proc */
................................................................................
    { "nand3",     &BddSystemTernopMethodType,   (ClientData) BDD_TERNOP_NAND },
    { "nor",       &BddSystemBinopMethodType,     (ClientData) BDD_BINOP_NOR },
    { "nor3",      &BddSystemTernopMethodType,    (ClientData) BDD_TERNOP_NOR },
    { "notnthvar", &BddSystemNotnthvarMethodType, NULL },
    { "nthvar",    &BddSystemNthvarMethodType,    NULL },
    { "oneof3",    &BddSystemTernopMethodType,  (ClientData) BDD_TERNOP_ONEOF },
    { "profile",   &BddSystemProfileMethodType,   NULL },
    { "project",   &BddSystemProjectMethodType,   NULL },
    { "restrict",  &BddSystemRestrictMethodType,  NULL },
    { "satcount",  &BddSystemSatcountMethodType,  NULL },
    { "simplify",  &BddSystemSimplifyMethodType,  NULL },
    { "twoof3",    &BddSystemTernopMethodType,  (ClientData) BDD_TERNOP_TWOOF },
    { "unset",     &BddSystemUnsetMethodType,     NULL },
    { "|",         &BddSystemBinopMethodType,     (ClientData) BDD_BINOP_OR },
    { "|3",        &BddSystemTernopMethodType,    (ClientData) BDD_TERNOP_OR },
................................................................................
	countv[i] = Tcl_NewWideIntObj((Tcl_WideInt) v[i]);
    }
    ckfree(v);
    Tcl_SetObjResult(interp, Tcl_NewListObj(n, countv));
    ckfree(countv);
    return TCL_OK;
}
 
/*
 *-----------------------------------------------------------------------------
 *
 * BddSystemProjectMethod --
 *
 *	Projects away a set of variables from a BDD.
 *
 * Usage:
 *	$system project result vars expr
 *
 * Parameters:
 *	system - System of BDD's
 *	result - Name of a BDD that will receive the result
 *	var - List of integers giving positions of variables to project away.
 *	expr - Expression to simplify
 *
 * Results:
 *	Returns a standard Tcl result
 *
 * Side effects:
 *	Creates the named expression if successful
 *
 * This is the same operation as existential quantification. It is provided
 * for the convenience of Finite Domain Decision Diagrams, where it exists
 * as the relational 'project' operator.
 *
 *-----------------------------------------------------------------------------
 */
static int
BddSystemProjectMethod(
    ClientData clientData,	/* Operation to perform */
    Tcl_Interp* interp,		/* Tcl interpreter */
    Tcl_ObjectContext ctx,	/* Object context */
    int objc,			/* Parameter count */
    Tcl_Obj *const objv[])	/* Parameter vector */
{
    Tcl_Object thisObject = Tcl_ObjectContextObject(ctx);
				/* The current object */
    BddSystemData* sdata = (BddSystemData*)
	Tcl_ObjectGetMetadata(thisObject, &BddSystemDataType);
				/* The current system of expressions */
    int skipped = Tcl_ObjectContextSkippedArgs(ctx);
				/* The number of args used in method dispatch */
    BDD_BeadIndex u;		/* Expression to quantify */
    int varc;			/* Number of variables to project away */
    Tcl_Obj** varv;		/* Indices of variables to project away */
    int vIndex;			/* Variable number from Tcl */
    BDD_VariableIndex* v;	/* Variables to quantify */
    BDD_BeadIndex result;	/* Result of the quantification */
    BDD_VariableIndex i;

    /* Check syntax */

    if (objc != skipped+3) {
	Tcl_WrongNumArgs(interp, skipped, objv, "name varList expr");
	return TCL_ERROR;
    }
    if (FindNamedExpression(interp, sdata, objv[skipped+2],
			    &u) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_ListObjGetElements(interp, objv[skipped+1],
			       &varc, &varv) != TCL_OK) {
	return TCL_ERROR;
    }
    v = ckalloc(varc * sizeof(BDD_VariableIndex));
    for (i = 0; i < varc; ++i) {
	if (Tcl_GetIntFromObj(interp, varv[i], &vIndex) != TCL_OK) {
	    ckfree(v);
	    return TCL_ERROR;
	}
	v[i] = (BDD_VariableIndex) vIndex;
	if (i > 0 && v[i] <= v[i-1]) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("variables are not in "
						      "increasing order\n",
						      -1));
	    Tcl_SetErrorCode(interp, "BDD", "VarsOutOfOrder", NULL);
	    ckfree(v);
	    return TCL_ERROR;
	}
    }

    result =
	BDD_Quantify(sdata->system, BDD_QUANT_EXISTS, varc, v, u);

    ckfree(v);
    SetNamedExpression(sdata, objv[skipped], result);
    BDD_UnrefBead(sdata->system, result);
    return TCL_OK;
}
 
/*
 *-----------------------------------------------------------------------------
 *
 * BddSystemQuantifyMethod --
 *
 *	Quantifies a BDD with respect to a particular set of variables.

Name change from library/tclfdd.tcl to library/tclfddd.tcl.

1
2
3
4
5
6
7
8
9
10
..
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
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
...
215
216
217
218
219
220
221
222
#package require tclbdd 0.1

namespace eval fdd {
    namespace export domain interleave concatenate
}

#-----------------------------------------------------------------------------
#
# The next few procedures are for working with domain descriptions, which
# describe a finite, multivalued domain within a BDD. A domain description
................................................................................
#	    represent values in the given domains. The list appears in
#	    order by variable index. It consists of alternating domain
#	    names and bit positions in values in the domain (with
#	    position zero being the least significant bit).
#
#-----------------------------------------------------------------------------

# fdd::domain --
#
#	Defines a new finite domain
#
# Usage:
#	fdd::domain name width ?endian?
#
# Parameters:
#	name - Name of the domain
#	width - Log base 2 of the number of distinct values.
#	endian - 'littleendian' (default) if the values are to be
#		 encoded in BDD's with the least significant bit first.
#		 'bigendian' if they are to be encoded with the most
#		 significant bit first
#
# Results:
#	Returns a domain description.

proc fdd::domain {name width {endian littleendian}} {
    switch -exact -- $endian {
	littleendian {
	    set l {}
	    for {set i 0} {$i < $width} {incr i} {
		lappend l $name $i
	    }
	}
................................................................................
	bigendian {
	    set l {}
	    for {set i [expr {$width-1}]} {$i >= 0} {incr i -1} {
		lappend l $name $i
	    }
	}
	default {
	    return -code error -errorcode [list FDD BadEndian $endian] \
		"unknown endian \"$endian\": must be bigendian or littleendian"
	}
    }
    return [list [dict create $name $width] $l]
}

# fdd::interleave --
#
#	Interleaves some number of finite domains so that their bit positions
#	in a BDD alternate.
#
# Usage:
#	fdd::interleave ?description...?
#
# Parameters:
#	Zero or more domain descriptions whose bits are to be interleaved.
#	All domains in the descriptions must be distinct.
#
# Results:
#	Returns a domain description of the interleaved domains.
#
# Errors:
#	{FDD DuplicateName $name} if any domain is not distinct
#
# The domains are interleaved by taking one bit from the first domain,
# one from the second, and so on. If they are of differing length, then
# the process ceases taking bits from the shorter ones when they run out.

proc fdd::interleave {args} {
    set N 0
    set names {}
    set bits {}
    foreach domain $args {
	dict for {name width} [lindex $domain 0] {
	    if {[dict exists $names $name]} {
		return -code error -errorcode [list FDD DuplicateName $name] \
		    "domain named \"$name\" appears in multiple places"
	    }
	    incr N $width
	    dict set names $name $width
	    lappend bits [lindex $domain 1]
	}
    }
................................................................................
	    }
	    incr i
	}
    }
    return [list $names $scrambled]
}

# fdd::concatenate --
#
#	Concatenates the descriptions of a set of finite domains
#
# Usage:
#	fdd::concatenate ?description...?
#
# Parameters:
#	Zero or more finite domain descriptions.
#
# Results:
#	Returns a description with the bits of the domains concatenated
#	together.
#
# Errors:
#	{FDD DuplicateName $name} if any domain is not distinct

proc fdd::concatenate {args} {
    set N 0
    set names {}
    set bits {}
    foreach domain $args {
	dict for {name width} [lindex $domain 0] {
	    if {[dict exists $names $name]} {
		return -code error -errorcode [list FDD DuplicateName $name] \
		    "domain named \"$name\" appears in multiple places"
	    }
	    incr N $width
	    dict set names $name $width
	}
	lappend bits [lindex $domain 1]
    }
................................................................................
    set chain {}
    foreach b $bits {
	lappend chain {*}$b
    }
    return [list $names $chain]
}

# fdd::reader --
#
#	Makes a call to the BDD engine to construct a minterm corresponding
#	to a tuple in a finite domain.
#
# Usage:
#	fdd::reader sysName termName layout domain ?domain...?
#
# Parameters:
#	sysName - Name of the system of BDD's
#	termName - Name of the term to be constructed
#	layout - Description of the finite domain
#	domain - One or more domain names, in the order in which values
#	         will appear in an input tuple.
................................................................................
#
# To the prefix should be appended the values of the domain elements,
# in the order in which their domains appeared on this command.
#
# Example:
#
# set desc \
#     [fdd::concatenate \
#         [fdd::domain var 3 bigendian] \
#         [fdd::interleave \
#             [fdd::domain stmt 5] [fdd::domain stmt2 5]]]
#  set r [fdd::reader sys reads $desc stmt var]
#
# leaves desc set to:
#
#    {var 3 stmt 5 stmt2 5} 
#    {var 2 var 1 var 0 stmt 0 stmt2 0 stmt 1 stmt2 1 stmt 2 stmt2 2 
#     stmt 3 stmt2 3 stmt 4 stmt2 4}
#
................................................................................
# which (when two additional args are catenated on the end), asks the BDD
# system "construct a minterm named 'reads', where variable zero is set from
# parameter 1, the 2**2 bit, variable 1 from parameter 1 the 2**1 bit,
# variable 2 from parameter 1 the 2**0 bit, variable 3 from parameter 0 the
# 2**0 bit, variable 5 from parameter 0 the 2**1 bit ... variable 11 from
# parameter 0 the 2**4 bit."

proc fdd::reader {sysName termName layout args} {
    set i 0
    foreach name $args {
	dict set cmdpos $name $i
	incr i
    }
    set result {}
    set p 0
................................................................................
	}
	incr p
    }
    set cmd [list $sysName load $termName $result]
    return $cmd
}

package provide tclfdd 0.1


|







 







|




|












|







 







|






|





|









|





|






|







 







|




|









|

|






|







 







|





|







 







|
|
|
|
|







 







|







 







|
1
2
3
4
5
6
7
8
9
10
..
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
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
...
215
216
217
218
219
220
221
222
#package require tclbdd 0.1

namespace eval fddd {
    namespace export domain interleave concatenate
}

#-----------------------------------------------------------------------------
#
# The next few procedures are for working with domain descriptions, which
# describe a finite, multivalued domain within a BDD. A domain description
................................................................................
#	    represent values in the given domains. The list appears in
#	    order by variable index. It consists of alternating domain
#	    names and bit positions in values in the domain (with
#	    position zero being the least significant bit).
#
#-----------------------------------------------------------------------------

# fddd::domain --
#
#	Defines a new finite domain
#
# Usage:
#	fddd::domain name width ?endian?
#
# Parameters:
#	name - Name of the domain
#	width - Log base 2 of the number of distinct values.
#	endian - 'littleendian' (default) if the values are to be
#		 encoded in BDD's with the least significant bit first.
#		 'bigendian' if they are to be encoded with the most
#		 significant bit first
#
# Results:
#	Returns a domain description.

proc fddd::domain {name width {endian littleendian}} {
    switch -exact -- $endian {
	littleendian {
	    set l {}
	    for {set i 0} {$i < $width} {incr i} {
		lappend l $name $i
	    }
	}
................................................................................
	bigendian {
	    set l {}
	    for {set i [expr {$width-1}]} {$i >= 0} {incr i -1} {
		lappend l $name $i
	    }
	}
	default {
	    return -code error -errorcode [list FDDD BadEndian $endian] \
		"unknown endian \"$endian\": must be bigendian or littleendian"
	}
    }
    return [list [dict create $name $width] $l]
}

# fddd::interleave --
#
#	Interleaves some number of finite domains so that their bit positions
#	in a BDD alternate.
#
# Usage:
#	fddd::interleave ?description...?
#
# Parameters:
#	Zero or more domain descriptions whose bits are to be interleaved.
#	All domains in the descriptions must be distinct.
#
# Results:
#	Returns a domain description of the interleaved domains.
#
# Errors:
#	{FDDD DuplicateName $name} if any domain is not distinct
#
# The domains are interleaved by taking one bit from the first domain,
# one from the second, and so on. If they are of differing length, then
# the process ceases taking bits from the shorter ones when they run out.

proc fddd::interleave {args} {
    set N 0
    set names {}
    set bits {}
    foreach domain $args {
	dict for {name width} [lindex $domain 0] {
	    if {[dict exists $names $name]} {
		return -code error -errorcode [list FDDD DuplicateName $name] \
		    "domain named \"$name\" appears in multiple places"
	    }
	    incr N $width
	    dict set names $name $width
	    lappend bits [lindex $domain 1]
	}
    }
................................................................................
	    }
	    incr i
	}
    }
    return [list $names $scrambled]
}

# fddd::concatenate --
#
#	Concatenates the descriptions of a set of finite domains
#
# Usage:
#	fddd::concatenate ?description...?
#
# Parameters:
#	Zero or more finite domain descriptions.
#
# Results:
#	Returns a description with the bits of the domains concatenated
#	together.
#
# Errors:
#	{FDDD DuplicateName $name} if any domain is not distinct

proc fddd::concatenate {args} {
    set N 0
    set names {}
    set bits {}
    foreach domain $args {
	dict for {name width} [lindex $domain 0] {
	    if {[dict exists $names $name]} {
		return -code error -errorcode [list FDDD DuplicateName $name] \
		    "domain named \"$name\" appears in multiple places"
	    }
	    incr N $width
	    dict set names $name $width
	}
	lappend bits [lindex $domain 1]
    }
................................................................................
    set chain {}
    foreach b $bits {
	lappend chain {*}$b
    }
    return [list $names $chain]
}

# fddd::reader --
#
#	Makes a call to the BDD engine to construct a minterm corresponding
#	to a tuple in a finite domain.
#
# Usage:
#	fddd::reader sysName termName layout domain ?domain...?
#
# Parameters:
#	sysName - Name of the system of BDD's
#	termName - Name of the term to be constructed
#	layout - Description of the finite domain
#	domain - One or more domain names, in the order in which values
#	         will appear in an input tuple.
................................................................................
#
# To the prefix should be appended the values of the domain elements,
# in the order in which their domains appeared on this command.
#
# Example:
#
# set desc \
#     [fddd::concatenate \
#         [fddd::domain var 3 bigendian] \
#         [fddd::interleave \
#             [fddd::domain stmt 5] [fddd::domain stmt2 5]]]
#  set r [fddd::reader sys reads $desc stmt var]
#
# leaves desc set to:
#
#    {var 3 stmt 5 stmt2 5} 
#    {var 2 var 1 var 0 stmt 0 stmt2 0 stmt 1 stmt2 1 stmt 2 stmt2 2 
#     stmt 3 stmt2 3 stmt 4 stmt2 4}
#
................................................................................
# which (when two additional args are catenated on the end), asks the BDD
# system "construct a minterm named 'reads', where variable zero is set from
# parameter 1, the 2**2 bit, variable 1 from parameter 1 the 2**1 bit,
# variable 2 from parameter 1 the 2**0 bit, variable 3 from parameter 0 the
# 2**0 bit, variable 5 from parameter 0 the 2**1 bit ... variable 11 from
# parameter 0 the 2**4 bit."

proc fddd::reader {sysName termName layout args} {
    set i 0
    foreach name $args {
	dict set cmdpos $name $i
	incr i
    }
    set result {}
    set p 0
................................................................................
	}
	incr p
    }
    set cmd [list $sysName load $termName $result]
    return $cmd
}

package provide tclfddd  0.1