A Scala library for Context-Dependent Environments, where a key-value environment is passed down a module hierarchy and each returned value depends on the key and the query’s origin. CDE is provably superior to existing parameterization schemes because it avoids introducing non-local source code changes when a design is modified, while also enabling features for large-scale design space exploration of compositions of generators.
User Guide
The library presents its key-value storage under an abstract class Parameters. Values stored in Parameters are each associated with a case object extends Field[T].
The main interface for user to create a Parameters object is using Config object. Its apply method takes (View, View, View) => PartialFunction[Any, Any] as a lookup table.
//Field MyKey1 contains value of type Int
case object MyKey1 extends Field[Int]
//Field MyKey2 contains value of type String, with default value "None"
case object MyKey2 extends Field[String]("None")
// The meaning of parameter (site, here, up) will be explained later
val p: Parameters = Config((site, here, up) => {
case MyKey1 => 0
case MyKey2 => "MyValue"
})
// Apply Paramaters object to Field to query
assert(p(MyKey1) == 0)
Parameter Overrides
We can use one Parameters to override another. Each single Config is like a row in a table, while each Field is a column in the table. To concat two table together, we have alter and orElse methods.
alter puts the rhs at bottom of the table and orElse puts the rhs at top of the table.
A query will inspect the table from bottom to up, row by row, until it finds the first row having the key defined.
For example: Config1.alter(Config2).alter(Config3) yields
Key1
Key2
Key3
…
Config1
V1
Config2
V2
V3
Config3
V4
And now p(Key1) == V2, p(Key2) == V3 and p(Key3) == V4.
The same Parameters can also be defined by Config3.orElse(Config2).orElse(Config1). There is also deprecated shorthand ++ for orElse, so Config3 ++ Config2 ++ Config1 is also valid.
Environment Reference
Each query contains the entire environment of where the query originates. This is pass to the lookup table of each Config by (site, here, up) arguments.
here dynamically refers to the current row of the table
up dynamically refers to the rows appearing up than the current row
site dynamically refers to the entire table. When it gets called by here or up queries, it still refers to the entire table instead of current row or upper half as indicated by here or up respectively.
For example, in the following Parameters
Key1
Key2
Key3
Key4
Config1
1
site(Key1)
Config2
2
here(Key1)
up(Key2)
Config3
3
The value for each key is
Key1: 3, given by Config3
Key2: 3, as it is value of Key1 in the entire table
Key3: 2, as it is value of Key1 defined in the current row
Key4: 3, as it is value of Key2 defined in the upper row, which is in turn value of Key1 defined in the table, which should be 3 as overriden by Config3.
If one config layer does not refer environment at all, alterMap and alterPartial can be used to avoid create a redundant Config object, as they accept Map and PartialFunction as their parameter.
Implementation Details
This section discusses the internal data structure used to track environment information. Normal reader can skip the section.
alter and orElse function wraps two operand as ChainParameters, which forms a binary tree when alter are called multiple times. Query on ChainParameters calls chain method.
The chain method traverses the tree by wrapping the right child in ChainView, which records up for later reference, and invoking chain on the left child. This happens recursively until a leaf node is found. Then if the requested key is not in the node, we can turn to chain of currently up node.
The following figure illustrates a querying process of Parameters constructed by C1.alter(C2).alter(C3).orElse(C4). chain is invoked on the node in blue, and ChainView generated is in red.
CDE
A Scala library for Context-Dependent Environments, where a key-value environment is passed down a module hierarchy and each returned value depends on the key and the query’s origin. CDE is provably superior to existing parameterization schemes because it avoids introducing non-local source code changes when a design is modified, while also enabling features for large-scale design space exploration of compositions of generators.
User Guide
The library presents its key-value storage under an abstract class
Parameters
. Values stored inParameters
are each associated with a case object extendsField[T]
.The main interface for user to create a
Parameters
object is usingConfig
object. Itsapply
method takes(View, View, View) => PartialFunction[Any, Any]
as a lookup table.Parameter Overrides
We can use one
Parameters
to override another. Each singleConfig
is like a row in a table, while eachField
is a column in the table. To concat two table together, we havealter
andorElse
methods.alter
puts the rhs at bottom of the table andorElse
puts the rhs at top of the table.A query will inspect the table from bottom to up, row by row, until it finds the first row having the key defined.
For example:
Config1.alter(Config2).alter(Config3)
yieldsConfig1
Config2
Config3
And now
p(Key1) == V2
,p(Key2) == V3
andp(Key3) == V4
.The same
Parameters
can also be defined byConfig3.orElse(Config2).orElse(Config1)
. There is also deprecated shorthand++
fororElse
, soConfig3 ++ Config2 ++ Config1
is also valid.Environment Reference
Each query contains the entire environment of where the query originates. This is pass to the lookup table of each
Config
by(site, here, up)
arguments.here
dynamically refers to the current row of the tableup
dynamically refers to the rows appearing up than the current rowsite
dynamically refers to the entire table. When it gets called byhere
orup
queries, it still refers to the entire table instead of current row or upper half as indicated byhere
orup
respectively.For example, in the following
Parameters
Config1
site(Key1)
Config2
here(Key1)
up(Key2)
Config3
The value for each key is
Config3
Key1
in the entire tableKey1
defined in the current rowKey2
defined in the upper row, which is in turn value ofKey1
defined in the table, which should be 3 as overriden byConfig3
.If one config layer does not refer environment at all,
alterMap
andalterPartial
can be used to avoid create a redundantConfig
object, as they acceptMap
andPartialFunction
as their parameter.Implementation Details
This section discusses the internal data structure used to track environment information. Normal reader can skip the section.
alter
andorElse
function wraps two operand asChainParameters
, which forms a binary tree whenalter
are called multiple times. Query onChainParameters
callschain
method.The
chain
method traverses the tree by wrapping the right child inChainView
, which recordsup
for later reference, and invokingchain
on the left child. This happens recursively until a leaf node is found. Then if the requested key is not in the node, we can turn tochain
of currentlyup
node.The following figure illustrates a querying process of
Parameters
constructed byC1.alter(C2).alter(C3).orElse(C4)
.chain
is invoked on the node in blue, andChainView
generated is in red.