a first-order continuation-like structure), a method stack, an exception stack, and a loop stack (loops can
break and co ntinue). Therefore, there are no less than 17 leaf configuration items, each containing important
information about the state of the program. Moreover, 10 of them, those within threads, can have multiple
instances, depending upon the number of threads that are alive at a given moment. Thus, the total number
of leaf configuration items at any given moment is 7+n∗10, where n is the number of threads t that moment.
The a dvantage of representing configurations as nested “soups”, is that, like in MSOS [29], subsequent
semantic equations a nd rules will only need to mention those configuration items that are needed for those
particular e quations and rules, as oppo sed to having to mention the entire configuratio n, whether needed
or not, like in conventional SOS. We can add or remove elements from the configuration multiset as we
like, only impacting rules that use those particular c onfiguration items. Rules that do not need the changed
configurations items do not need to be touched. This is one impo rtant aspect of K’s modularity.
There are two optional conventions/guidelines regarding the use of config urations that help increase the
modularity of K language definitions. By convention, configuration labels must b e distinct in the initial
configuration, so that the configurations they wrap can be uniquely identified even when the exact paths
to them are not completely specified. Also, equations and rules are allowed to add new configuration
item instances (a necessary process when, for example, creating threads) only at the same nesting level as
originally declared in the nested config uration. These conventions are crucial for K’s context transformation
process; essentially, equations and rules in a K definition are unambiguously and automatically modified by
completing partial configuration contexts to “fit” the current configuration. This optional process, explained
in detail in [33], gives an additional degree of modularity to K definitions. For example, suppose that initially
KOOL was not c oncurrent and had no statements that can a bruptly change the control, such as return of
methods, exceptio ns, break/continue of loops, so there was no need for a multi-layered configuration; in other
words, suppose that a ll co nfiguration items were initially part of the top level configuration. Then the rule
for variable lookup (defined also in Appendix D) would match the environment and the store at the same
configuration level. Adding threads and control-changing statements to the language would, unfortunately,
break the e xisting definition of variable lookup, because now each of the involved configuration items a re
located at different levels in the configura tion, so the previous rule would not match a nymore. With context
transformers, no change needs to be done in the existing rule for variable lookup when the structure of
the configuration changes. The correct environment will b e matched (and not the environment of another
thread), because the context transformers are resolved following a “greedy” depth-first strategy.
3.2 K Computations: y-Separated Nested Lists of Tasks
An important configuration item, present in many K definitions and “wr apped” in configurations with the
ConfigLabel k, is the computation, denoted by the syntactic category K. Computations generalize abstract
syntax trees (ASTs) by adding a special list construct y :
K ::= KLabel(List
,
[K]) | List
·
y
[K]
KLabel ::= (one per language construct, plus auxiliary ones as needed)
The first construct scheme for K abstractly captures any prog ramming language syntax, under the form of
abstract syntax trees, provided that one adds one KLabel for each language construct. In addition to the
language syntax, one may include in KLabel additional labels for semantic rea sons and for “heating/cooling”
reasons (explained below). If one wants more K syntactic categories, then one can do that, too, but, for
simplicity, we prefer to keep only one in this paper. It is often mor e intuitive to call the language constructs
taking no arguments constants and write them as “leaves” in K structures; e.g., ski p instead of skip(); we
therefore may tacitly assume an additional syntactic subcategory of K called KConstant, for constructs
such as skip, 0, 1, true, etc. Also, for executability reasons, it may be useful to define another s yntactic
subc ategory of K, called KResult, for “finished computations” ; this may contain certain constants, such as
0, 1, true, etc., but also computations which are proper terms, such as λ . (x, e) (written in AST form).
We take the liberty to write syntax either in AST form, like in “λ . (x, e)” and “if then else (b, s
1
, s
2
)”,
or in more re adable mixfix form, “λx.e” and “if b then s
1
else s
2
”. In our Ma ude implementation of K
16
University of Illinois at Urbana-Champaign
Department of Computer Science UIUCDCS-R-2007-2926 and College of Engineering UILU-ENG-2007-1827