MDL & Simlab:
Heir to SimScript? Simulation's SmallTalk?

J. Rodden
CIS 203, June 1994

Abstract

The evolution of programming languages and software development environments have greatly enhanced the set of tools available to the programmer. A brief survey of this evolution is presented along with a detailed analysis of one modern discrete time simulation language, Model Description Language (MDL). MDL is compared and contrasted to several major artificial languages and is found to incorporate various features from the field of programming languages.

Evolution of Software Development

The development of software systems has changed dramatically since the early days of digital computers which were programmed by physically switching the logic gate inputs. There has been a particularly explosive evolution in the power and type of tools used to develop software. This evolution began with the advent of high-level languages such as FORTRAN, ALGOL, and LISP which introduced an abstraction of the physical machine, a virtual machine. High-level languages also provided for easier debugging, maintenance, testing, and portability of software. Since the first high-level programming languages there have been literally hundreds of new ones created, each with its own design philosophy and intended problem domain.

As programming languages evolved, so did the environments and tools with which they were used and the means by which coded programs were entered into computers. At first there was only punched tape and punched cards, but in the 60's and 70's interactive terminals became available. Interactive terminals made line editors possible, followed by visual editors in the 70's and early 80's. Software development reached a new plateau in the late 80's and early 90's with a plethora of tools for the programmer-prototypers, Integrated Development Environments (IDE's), interactive debuggers (including source debuggers), and aides for achieving higher-level abstractions, machine and domain independence. Tools and strategies were created for bringing the notion of modularity and reuse, an important innovation in languages and programming methodology, to a higher level in which programs and program units themselves are "glued" together, known as Glue Oriented Programming (GlOP).

MDL's Basic Features

Model Description Language (MDL) is a lexically scoped, imperative simulation language that incorporates several elements from some of the major programming languages of the last 50 years. Originally designed in the mid 1980's at the University of California, Santa Cruz by Dr. Roger Wellington-Oguri under the supervision of Prof. R. Michael Tanner, the MDL definition is currently undergoing redefinition by Gil Fuchs and James Rodden under the supervision of Prof. Tanner.

Simulation Language

Foremost, MDL is a language for defining models using Systems Analysis Theory. The basic paradigm is that of a discrete time simulation. The only flow of control is an implicit cycle of execution in which all statements theoretically occur simultaneously. This provides the essence of discrete simulations-each value within the system is defined in terms of previous time steps and an initial state. Simula-67 and SimScript were also designed as simulation languages, but retained much of the flavor of contemporary procedural languages. For example, SimScript also has a built-in notion of time, but it is much less implicit.

Data Abstraction

The ability to abstract data by encapsulating its representation and operations was a significant development in the evolution of high-level languages. First introduced in Simula-67 in the form of type templates, called classes, they allow the operations on data to be syntactically associated with the data itself. However, without any data hiding enforcement the Simula-67 style class provides little more than a grouping of operations and data-multiple access paths to data are allowed.

The Modula-2 and Ada program units for abstraction, the module and package respectively, and ANSI C's file scoping mechanism are much more sophisticated because they provide for explicit exportation of a module's interface. Emphasis is placed on the interface by separating its definition from the implementation of the module. Modula-2 and Ada require that the two portions are compiled separately while ANSI C requires procedure prototypes which are usually contained in a separate header file. In all three languages only the interface is needed to utilize the module elsewhere in a program.

Separate interface and implementation definition has the advantage of enforcing strict data abstraction by not allowing a module's client to know anything about its implementation, but at a cost of efficiency in certain domains. A compromise solution is presented in C++ style classes-the interface and implementation are defined separately, but the memory size and layout is revealed along with the interface. Much of the reason for this compromise lies in the fact that C++ is an Object-Oriented Language whereas Modula-2, Ada and ANSI C are not, but it allows client code to directly include a module in the form of objects.

The abstraction unit of MDL is called a submodel. MDL's approach to data abstraction is most like that of ANSI C's file scoping mechanism, but contains elements of each method described above. The submodel abstraction is like Simula-67, ANSI C, and C++ in that elements of the implementation are revealed along with the interface definition, but interactions with each abstraction must strictly comply with its interface as in Modula-2 and Ada. All of these languages provide for code libraries which can be re-used as sub components to larger programs.

Named lambda-Functions

Most programming languages have one important design element in common-the Von Neumann architecture. They are all focused on the goal of efficient execution which means a close coupling with the sequential instruction state machine model. Although this basis does not restrict most domains, mathematics does not utilize or require state and can even be expressed better without state. The functional programming paradigm, based on mathematical functions rather than finite state machines, is widely popular among more abstract disciplines such as mathematics and linguistics.

The primary feature of functional programming is that any expression's value is based solely on the value of its sub expressions. Functions can be generated by recursively nesting expressions in order to create higher-order functions. The process of defining such functions is generally referred to as lambda-calculus and the results are known as lambda-expressions or lambda-functions. The two major examples of languages that support this paradigm are LISP and ML.

Systems Analysis Theory is a highly mathematical field that essentially constitutes a union between the functional nature of mathematics and the concept of sequential state from computer science. Because of this union, it is important to provide support for both the sequential state and functional models of computation in MDL. This is achieved by including a variation of lambda-functions, essentially named lambda-functions.

Simplicity and Efficiency for Domain

While theoretical soundness and elegance is fine for theoreticians, efficiency is the driving force in computer applications. This fact was acknowledged and addressed by the first widely used programming language, FORTRAN. In fact, it was FORTRAN's efficiency and simplicity of implementation that enabled it to become so widely accepted. Nearly every major computer language has had to address this issue and the non-acceptance of a language is often due to a poor mark with this yardstick.

At some point in each language's design a decision must be made as to whether it will be geared more towards a general or a restricted domain. In many cases, a well defined domain can make a restricted domain language more expressive and more efficient than a general purpose language for problems within the corresponding problem domain. An excellent example of this situation exists between SimScript and FORTRAN; SimScript is far better suited for and expressive of discrete simulations than FORTRAN.

MDL is extremely well suited for its domain, discrete time simulations. Its expressive power is nearly equivalent to that of the mathematical notation upon which it is based, and MDL requires little programming knowledge or experience because there are no programmatic constructs beyond systems theory other than syntax. Because the discrete time model is independent of the sequential ordering of execution, MDL can be easily mapped to any sequential imperative domain.

Support for Programming in the Large

As software systems have grown, the first programming model of a single programmer has become less effective and new ideas of how to deal with larger projects have evolved. This new realm of software development is known as Programming in the Large (PIL) and can be loosely defined as any project that few, if any, individuals understand completely. Such large projects usually involve multiple programmers and quite often have separate design and implementation teams.

The most common strategies for dealing with large systems development center around modular, top-down designs with clearly defined and strictly enforced interfaces between modules. A couple of the more recently accepted ideas are code re-use and Object-Oriented Programming. Each of these concepts can be manifested in several forms. For instance, an extension of Object-Oriented Programming at the operating system/application level is Glue Oriented Programming (GlOP), in which applications are "glued" together to form larger applications.

MDL's approach to data abstraction, the submodel, certainly supports PIL in a few important ways. From the perspective of top-down design and modularity, submodels represent a clean example of modular programming close to Modula-2 modules and Ada packages. From a slightly different perspective, the fact that submodels can be complete models (programs) in themselves makes it clear that MDL actually supports GlOP. This feature is further demonstrated by noting that each model/submodel only has access to its own local variables and those passed in via its interface-there aren't any global variables.

Heir to SimScript

MDL provides an even simpler and possibly more powerful expressiveness both in its syntax and its semantics than SimScript. This simplicity of expressive power is embodied in the fact that an MDL programmer need only specify the interactions within a model while a SimScript programmer must be aware of the flow of control through their simulation. Although MDL is primarily designed for discrete time simulations and SimScript is designed for discrete event simulations, MDL is functionally equivalent to SimScript. The crucial difference between MDL as a time simulator and SimScript as an event simulator is that MDL actually steps through each time tick and re-evaluates the model's values at each time step whereas SimScript maintains an event queue, jumps to the time for the next event, and pops it off the queue.

Even a first pass attempt to map MDL's paradigm to SimScript's reveals that MDL's simulation would lack only in efficiency because each time step is truly simulated instead of virtually simulated as in SimScript. Such a mapping would involve a state variable, an alarm, for each event indicating when it should next occur. At each time step, evaluate the alarm to see if it is time to activate the event. If the alarm value is greater than the time step value do nothing, otherwise let the event take place. Each event would need to "register" when it won't occur anymore so that the simulation can eventually stop.

A closer mapping between MDL and SimScript would require an event queue. The following MDL code implements a simple stack which could be transformed into a queue definition with relative ease. The stack shown is not very flexible in terms of its size, but this limitation is due only to the current MDL definition-one of the proposed additions to the language is an array construct which would allow greater ease in changing the stack size.

model stack: inputs: push: int. # MDL doesn't have boolean and pop: int. # enumerations doesn't work. pushVal: int. outputs: full: int. # MDL doesn't have boolean and empty: int. # enumerations doesn't work. topVal: int. constants: size: int setup to 5. # size of stack state variables: topPos: int setup to 0. # index to top of stack slot1: int setup to 0. # since current MDL doesn't have slot2: int setup to 0. # arrays, use separate state slot3: int setup to 0. # variables to simulate array. slot4: int setup to 0. # slot5: int setup to 0. # temporaries: isEmpty: int. # MDL doesn't have boolean and isFull: int. # enumerations doesn't work. newTop: int. dynamics: # ****** temporaries ****** isEmpty is [ 1 if (topPos == 0); 0 otherwise ]. isFull is [ 1 if (topPos == size); 0 otherwise ]. newTop is [ topPos - 1 if (isEmpty == 0) and (pop == 1); topPos + 1 if (isFull == 0) and (push == 1); topPos otherwise ]. # ****** state variables ****** topPos is the delay of newTop. slot1 is the delay of [ pushVal if (isFull == 0) and (push == 1) and (topPos == 1); slot1 otherwise ]. slot2 is the delay of [ pushVal if (isFull == 0) and (push == 1) and (topPos == 2); slot2 otherwise ]. slot3 is the delay of [ pushVal if (isFull == 0) and (push == 1) and (topPos == 3); slot3 otherwise ]. slot4 is the delay of [ pushVal if (isFull == 0) and (push == 1) and (topPos == 4); slot4 otherwise ]. slot5 is the delay of [ pushVal if (isFull == 0) and (push == 1) and (topPos == 5); slot5 otherwise ]. # ****** outputs ****** full is isFull. empty is isEmpty. topVal is [ slot1 if (isEmpty == 0) and (topPos == 1); slot2 if (isEmpty == 0) and (topPos == 2); slot3 if (isEmpty == 0) and (topPos == 3); slot4 if (isEmpty == 0) and (topPos == 4); slot5 if (isEmpty == 0) and (topPos == 5); 0 otherwise ]. end stack.

Simulation's SmallTalk

As described earlier, software development tools have undergone many changes as computational languages have undergone their own changes. The Integrated Development Environments (IDE's) of today are significantly more sophisticated than the line editors of twenty years ago. However, there was a major exception to the use of line editors at that time-the SmallTalk environment. The SmallTalk environment embodied a program editor, compiler, virtual machine and other features into a single system. The user interface to the system was highly graphical and most of the code was executed by an interpreter.

SmallTalk was a language and environment rolled into one. Similarly, MDL is wrapped in its own development and execution environment, called Simlab. Like SmallTalk, Simlab is a highly interactive system that integrates an editor, compiler and virtual machine. When run within the Simlab environment, MDL is compiled into a virtual machine language much like Modula-2's intermediate m-code for an interpretive machine. In this way, Simlab does for MDL and simulations what the SmallTalk environment did for the SmallTalk language.

Conclusion

Model Description Language (MDL) and its companion environment, Simlab, represent a synthesis of features of the major programming languages including several important innovations in language and software development. MDL's heritage is not limited to a single class of language, nor are the characteristics it has adopted only in a single area. While MDL lives within its own niche, it also possesses features that may enable it to extend well beyond its creators' vision.