Modular Manipulation of the Link-Time Environment

I’m in the process of hammering out a concrete design for Awelon, and my design efforts have taken me to some interesting places. My current application model looks like this:

  • An Awelon application consists of a set of anonymous modules.
  • Each module will directly manipulate the link-time environment.
  • When the link-time environment stabilizes, the runtime behavior can be extracted.

Modules collaboratively specify a runtime behavior. Each module is fully responsible for its own link-time behavior. This contrasts with more traditional approaches to modularity, where modules are passive objects to be integrated by some unspecified third party. The link environment provides the sandbox for the modules to work. It may provide stateful resources, but it’s ultimately confined.

This design would be problematic for a procedural programming model due to non-deterministic ordering issues. But Awelon is a reactive demand programming language, and thus has synchronous concurrency. All the effects are applied at the same logical time.

I imagine that most modules will not directly contribute to runtime behaviors. Instead, many modules will contribute knowledge or components to shared locations in the link environment, e.g. parts of a world map or dialog tree, components of a UI specification, pages for the web service, constraints, defaults, overrides. Developers may then use link-time metaprogramming to construct the runtime behavior.

The link environment is cleanly partitioned from the runtime environment using the type system, and may be discarded after use. Logically, the environment is still present (otherwise the extracted dynamic behavior would expire). But since the environment is constant, and the extracted behavior won’t change (without a corresponding change in code), the environment can be discarded. (Though we might keep it around for live programming.)

This design supports a style I call stone soup programming. The modules are the ingredients. Developers can easily toss modules into a project to extend behavior or contribute flavor. The modules will link themselves under their own power, without any built-in constraints model.

As a disadvantage: it’s easy to ruin a soup.

Direct composition of the ingredients (e.g. clam beef stew chowder) doesn’t always work out. It’s an experiment. To address this, Awelon enables decomposition of an application into multiple component apps, each of which build in a separate link environment then are applied or composed in the parent. Usefully, the integrated app is subject to further optimization.

Given high levels of link-time metaprogramming, isolating a problem can become a hassle. This issue is partially addressed by a good development environment (e.g. ability to browse the link environment) and partially by discipline (one responsibility, clear documentation). Decomposition might help.

Individually, each module goes through a similar process to parse and extract link-time behaviors. (By handling each module independently, we ensure that at least the parse is independent of the application, and we support caching.)

Overall, this system is simpler, more consistent, more transparent, and more flexible than my earlier efforts. Some of my earlier approaches had constraint solvers built into the linkers, effectively forcing developers to learn another programming model. Here, I might provide constraint solvers in the link environment, but their use is voluntary.

The main concern I have is that linking is now a first-class concern, and developers might not be used to that sort of staged reasoning. But I believe this can be addressed via user-defined syntax, e.g. creating languages for cases where linking becomes boiler-plate.

This entry was posted in Language Design, Modularity, Open Systems Programming, Security, State. Bookmark the permalink.

3 Responses to Modular Manipulation of the Link-Time Environment

  1. Can you give a less theoretical, concrete example using a wiki ide?

    For example, how do you control focus and what object gets focus after another gives it up? How do you support multiple foci so that each concurrently collaborating user has their own mouse, keyboard caret and Google Glasses?

    • dmbarbour says:

      I suppose ‘direct manipulation’ is misleading when it’s the modules doing it; I had forgotten the HCI connotations. The link time environment is isolated – it won’t observe a keyboard or mouse. But I’ll try to address your question anyway.

      In any direct manipulation system (in the HCI sense), we’ll have some model of user state. (I wrote some of my thoughts on user model state a while back.) Some of this state might be associated uniquely with the user, and some with the relationship between a user and an object.

      Keyboard carets, mouse pointers, user focus – such states belong to the user model. They certainly aren’t part of the object’s model. In a collaborative context, it might be useful to know where someone else is editing, so some of this user:object relationship state might be kept at the server. But that can still be kept separate from the object state, since it’s really about interaction between users (in another context, we might model shared user interactions with ‘rooms’ or similar).

  2. A procedural language doesn’t prevent link-time manipulation per se – if procedures are all it has. The problem with this approach in a classical procedural language would of course be global variables and top-level initialization expressions (e.g. like expressions at the top-level of a file in Lisp, or like GCC’s constructor functions.)

    Global variables could be replaced with thread-local ones, and implicit top-level expressions with explicit calls to main and other init functions. This opens up at least some forms of link-time manipulations for procedural PLs.

Leave a comment