DMM Varkon® Tutorial
A Beginner's Guide to the Varkon Parametric Modeling and CAD Application Development System
By David M. MacMillan


4.5. Editing and Compiling MBS Code

4.5.1. Introduction

When I first began to learn Varkon, I completely misunderstood the way in which the MBS code for the various modules and parts comprising a model were compiled. This misunderstanding was due, however, more to my "batch programmer's" way of looking at Varkon that to Varkon itself. The way in which Varkon handles compilation is actually quite intuitive. I'll describe first how I now believe Varkon is intended to be used, and later, for reference, note the way in which I was initially using it.

4.5.2. The Active Module

4.5.2.1. What is the Active Module?

All Varkon models are expressed entirely as a set of MBS modules. (A Varkon job consists of a model plus setting and other job-related information.) In every job, there is exactly one MBS module which may be distinguished as the active module. For example, if you start up a new job from scratch Varkon automatically creates an empty active module with contents similar to these:

GLOBAL DRAWING MODULE parriss2();


BEGINMODULE


ENDMODULE

Given an empty active module in a new project such as this, MBS statements may be added to create an active module that does something. MBS statements may be added by using interactive functions, (as described in section 4.5.X below) or by typing them in an MBS editing window (as described in section 4.5.Y below.)

It is clear that an active module is very closely tied to a job. A job's name is the same as the name of a job's active module. The active module for a job is the root of a tree of MBS modules which constitutes the job's model. A job requires a compiled .MBO object code form of an active module (either read from disk when reloading a job or held in memory as a job is interactively created or edited). In addition to its active module, a job also contains information on its settings (e.g. what views are defined, what pen is the default, etc.) This information is stored in the job's .JOB file. (e.g. job/test3d.JOB).

4.5.2.2. Compiling, Linking, and Running the Active Module

The active module is usually compiled, linked, and run automatically. (In the Linux version, an X Window System resource controls whether or not the active module is compiled, linked, and run automatically on edit from an edit session.) The active module is incrementally updated as interactive functions are executed.

Compiling, linking, and running the model are conceptually distinct steps. Function f220, "Compile All Sources," compiles all modules in the current project. There is an interactive function, f5, "Run Active Module," which runs a compiled and linked model. This function is available as a button in the drawing screen of the standard configuration. There is no function which compiles and links only those modules in the active module's dependency hierarchy which have been changed (i.e., there is no function akin to the UNIX "make" program).

In the default menu system, f220, "Compile All Sources," is available by first going to the "MAIN MENU 2D [or 3D]":

Click on the "mbs" button to bring up the "MBS" menu, then click on the "part" button to bring up the "PART" menu, and finally click on the "compile all" button to Compile All Sources. If the compilation is successful, you'll get a message to that effect on the main drawing window. (To remove this message, press the Tab key or the middle mouse button.)

4.5.2.3. Comments in the Active Module

Comments that may have been entered when editing an active module are discarded each time an active module is compiled. This has two consequences. First, obviously, active modules cannot be commented. Second, sections of code in active modules cannot be commented out. Code that has been commented out simply disappears on compilation.

Comments in named (not active) modules edited via function f217, "Edit Named Module in MBS Format," are preserved.

4.5.2.4. Location of the Active Module's Object Code

When an active module is compiled, the compiled object code is held in memory (or perhaps an equivalent representation of the object code is held in memory - I'm not sure of the details). When a compiled active module is saved, this compiled object code is saved to disk in the job directory. Thus, saving the example above would result, on my system, in a file:

/home/dmm/varkon/app/test1/job/test3d.MBO

Although Varkon has the ability to derive equivalent MBS source code from MBS object code, when an active module is saved no such equivalent source code is written to disk. However, interactive function f144 writes an active module to a file in MBS format. This function is available in this standard menu system via: "MAIN MENU 2D" [or [MAIN MENU 3D"] -> VARIATION -> ACTIVE MODULE -> LIST -> FILE. It prompts for a filename which is a full UNIX pathname, but by default writes the active module into the job directory. Because comments are stripped off during the compilation of an active module, compiled modules saved to disk in MBS format have already had their comments stripped off.

4.5.2.5. Non-Interactively Created Active Modules

The active module is usually created interactively in the manner described above. It is possible to write a MBS module externally and make it the active module. To do this, write an MBS module (in the mbs source directory). Then compile it using mbsc. This should place the module's object file (modname.MBO) in the lib directory. Then copy this lib/modname.MBO object code to job/modname.MBO so that Varkon can find it.

The only advantage I can see in doing this is that it would allow preprocessing of the active module's source code (but not comments, which are stripped off during compilation).


4.5.3. Editing MBS within Varkon

4.5.3.1. Editing the Active Module

In the default configuration, editing the Active module is particularly easy. The "MBS" button which by default appears on the left of the main drawing screen invokes interactive function f216, "Edit Active Module in MBS Format."

This causes a window to be created containing the editor of your choice (in the Linux version, this is specified via a Varkon X Window System resource setting) with the contents of the active module in MBS format ready to be edited. For example:

(Aside: The example developed in this section is a part of a project to draw the rolling ball impulsed "free pendulum" clock of E.G. Parriss. For further details, see the Rolling Ball Web.)

To begin, let's draw a bounding box around our diagram-to-be. Since this diagram is of a clock with a seconds-beating pendulum approximately one meter in length, let's make this box slightly larger, say 1200mm square. One of many ways to do this would be to add the following MBS source text to the open edit session:

Write and save this text (:wq in the vi editor). If the Varkon X Window System resource varkon.mbsedit.autocompile is set to "True", then Varkon will automatically compile this modified active module. Note that it may be the case that the current drawing window is not appropriately sized or positioned for the changes you made. It may even appear that no changes were made (because you're looking at a part of the model where no changes were). To rescale the model so that everything is visible, press the "Auto" button in the standard menu system. This button invokes interactive function f194, "Autozoom," which resizes the view to fit the drawing window.

The results, autozoomed, should look like this:

To remove the "Active Module Compiled!" message, press the Tab key or the middle mouse button.

4.5.3.2. Editing a Part Module

The first thing we need in a pendulum clock is a pendulum. We could draw this within the active module, but since the pendulum is a well-defined component of the clock it is best to draw the pendulum in a separate module. This allows us to invoke the pendulum as a single "part" from the active module, which cleans up the structure of the active module. It also allows us to build a parametric representation of the pendulum. For example, we can specify the rotational position of our pendulum (rotation around its suspension or pivot point) and thereafter easily show a pendulum at any point of its swing.

Our simplified pendulum will actually take three parameters:

To create this pendulum by editing MBS code from within Varkon, assuming the default menu layout, go to the "MAIN MENU 2D" and press the "MBS" button. This brings up the "MBS" menu. Then press the "part" button to bring up the "PART" menu. Finally, press the "edit" button.

This will bring up a window which contains a button for each module which has already been defined, and an input field to name new modules. In the image below, it will be seen that I have already created the module "pendulum." I can thus simply click on "pendulum" to edit it. Had I not yet created this module, I could type "pendulum" in the input field and Varkon would create it for me."

The text of this very simple pendulum will be:

This MBS code introduces several Varkon modeling concepts not yet discussed. Very briefly, the way that this pendulum works is that a local coordinate system is constructed whose Z axis (pivot point in 2D) is coaxial with the axis of rotation of the pendulum. This local coordinate system is then made the active coordinate system:

csys_1p  (#1, "pendcsys", pivot, 0, 0, rotation);
mode_local (#1);

In this coordinate system, if it is not rotated relative to the global coordinate system under which this pendulum part will be invoked, the X axis will be horizontal and increase to the right, and the Y axis will be vertical and increase to the top. The Z axis isn't really represented in 2D, but it is used to specify rotation (it sticks straight out of the screen).

The pendulum that we draw will thus be based at (0,0) in this coordinate system and will extend downward, or in the negative Y direction.

To compile this module, write and quit the edit session (:wq in vi). A window will pop up asking you if you want to compile. Press "y".

If the compilation is successful, a message will be displayed indicating this:

(To remove this message, press the Tab key or the middle mouse button.)

Note that nothing has changed in the main drawing window. This is because this new module, pendulum.MBS, is not yet invoked by the active module (or by any other module in the tree descending from the active module). To add it to the model, it must be invoked via the "part" statement. For example, to place a pendulum in the drawing such that its center of rotation is 100mm right on X and 1,100mm up on Y, its length is 1,000mm, and its rotation 5 degrees counterclockwise, add a "part" statement to the active module so that the active module now looks like this:

GLOBAL DRAWING MODULE parriss2();

CONSTANT INT xmax=1200;
CONSTANT INT ymax=1200;

BEGINMODULE

  lin_free(#1,vec(0, 0), vec(xmax, 0));
  lin_free(#2,vec(xmax, 0), vec(xmax, ymax));
  lin_free(#3,vec(xmax, ymax), vec(0, ymax));
  lin_free(#4,vec(0, ymax), vec(0, 0));
  part(#5, pendulum(vec(100,1100), 1000, 5));

ENDMODULE

The drawing window now shows the pendulum:

Press the Tab key or the middle mouse button to remove the compilation message, and press the "Auto" button to autozoom, and the drawing now looks like this:

The pendulum's local coordinate system is shown by the two arrows near the top, and the pendulum itself is shown by the four lines defining a rotated, thin box.


4.5.3. Entering MBS via Interactive Functions

4.5.3.1. Interactive Editing in the Active Module

Interactive modification of the active module is straightforeward. Just perform interactive entity creation functions as described later in this tutorial in section 7. Simple 2D Drawing and 8. Simple 3D Geometric Modeling.

As entities (points, lines, curves, text, etc.) are created interactively, MBS equivalent statements are automatically added to the active module.

4.5.3.2. Interactive Editing in Other Modules (f217)

To be honest, I haven't figured out how to do this yet.


4.5.4. Specifying and Accessing Interactive Functions

Varkon contains many (over 200) functions which define interactive operations. Most of these functions map directly to MBS functions and procedures. f40, "Create lin_free in 2D," is an example of an interactive function which maps directly to an MBS procedure. However, not all MBS functions and procedures have corresponding interactive functions. sin() is an example of an MBS function which has no interactive function equivalent.

A few interactive functions, particularly those used only in explicit (non-generic) operation, have no MBS equivalent. This makes sense, as MBS is a generic, not explicit, modeling language. f202, "Drag Entity," is an example of an explicit-mode interactive function which does not have an MBS correspondence. f152, "Call a MACRO Module," is an example of a generic-mode interactive function which does not have an MBS correspondence.

The Varkon documentation for these functions is accessible in the Varkon manual through the "Interactive Functions" page. (This is probably obvious, but I keep forgetting where their manual pages are.)

These functions are divided into two categories based on their implementation language. The majority of the functions are written in C and are built in to the Varkon executable. These functions are numbered f1, f2, ... fn. The rest of the functions are written in MBS. These functions are named; e.g., "dxf_in. The object files (.MBO) for these MBS-language interactive functions reside in:

VARKON_ROOT/lib

At the present release, none of the MBS-written functions are documented.

All interactive functions are accessed through Varkon user interface constructs (menus, toolbars, function keys). The user sees no difference between C and MBS functions. However, they are specified differently when building user interfaces.

The C language functions are specified directly via their function number in user interface definitions. For example, in the standard Varkon menu setup, the menus.INC menu definition file includes the following menu:

m49 = "EDIT"
      "edit",m81
      "trim",f6
      "drag",f202
      "move",f209
      "mirror",f211
      "rotate",f203
      "copy",f210;

This defines a menu whose title is "EDIT" and which contains a button including, among others, "drag". This "drag" button is associated with the function f202, "Drag Entity."

Interactive functions, of course, prompt for their input interactively.

The MBS language functions are accessed in a slightly different manner. For example in the standard Varkon menu setup, the menus.INC menu definition file includes the following menu:

m44 = "DXF-2D"
      "import",p388
      "export",f92;

This menu, titled "DXF-2D", includes two buttons. The second of these buttons, "export", invokes the C language function f92, "Create DXF-file." The first of these bottons, "import", uses the "p" "action" specifier to invoke the LOCAL, GLOBAL, or BASIC (but not MACRO) module named by the text string "t388". Taking a look at the standard user interface include file texts.INC, we find the definition of t388:

t388 = "dxf_2D"

This text string defines the name (function name and file name, which are identical) of the MBS-language function "dxf_2D". Varkon will use this information to invoke the .MBO object file located in:

VARKON_ROOT/lib


4.5.4. Writing and MBS in External Files

4.5.4.1. Description

This is how I first, mistakenly, approached Varkon model building. My perspective is that of a programmer comfortable with command-line operation and with the powerful UNIX utilities such as make. When I first discovered Varkon, I was immediately attracted to it because it represents models as programs; to me this is intuitively the right method. I then immediately looked for a compiler, and found one (mbsc). Compiler in hand, I started writing MBS code (both active and subsidiary modules).

I soon discovered, however, that if I changed and recompiled a Varkon module outside of Varkon (e.g., by using the vi editor from the Linux command line to edit the module and then compiling it by invoking mbsc from the Linux command line) that changes to my model did not take effect when I ran the model using the f5 ("Run Active Module") function (when I pressed the "run" button). However, I could cause my model to be completely compiled and displayed by editing the MBS module interactively (pressing the MBS button, thus invoking f216, "Edit Active Module in MBS Format"). I thus got into a pattern of editing my subsidiary modules outside of Varkon, compiling them, then editing the active module from within Varkon and simply terminating the edit (immediately :wq). This does work, but it isn't straightforeward.

As a result, I thought that Varkon employed static linkage between its modules. It does not; Varkon employs dynamic (run-time) linking. However, Varkon does cache called modules in RAM when they are compiled from within Varkon. When a module is edited from within Varkon using f217, "Edit Named Module in MBS Format," or f216, "Edit Active Module in MBS Format," the edit function clears the PM (i.e., the model) cache. This forces new .MBO compiled object for the module to be loaded. It was this behavior that I was unwittingly invoking in the external compilation method described above.

MBS has a function, "clear_pm()", which clears the PM cache. If the first actual modeling statement of the active module is "clear_pm()", then each time the model is run (the Run button is pressed, invoking function f5, "Run Active Module") the PM cache will be cleared and the entire model will be reloaded from .MBO compiled object. A model so constructed can be reasonably maintained with edits and compiles from the Linux command line, external to Varkon.

Although external compilation is not the natural way to use Varkon, it may under certain circumstances offer advantages. For example, using Linux utilities such as the make program compilation maintenance system, the rcs revision control system, the sed stream editor, the Awk string-oriented programming language, and the Linux shell, it is possible to implement arbitrary preprocessing on any text. One example of the utility of such preprocessing might be a situation where "boilerplate" statements must be added to all documents, yet where these statements are subject to change.

4.5.4.2. Example

First, let's write a short MBS module named "line", putting it in an external file in the mbs directory named "line.MBS". The name of the module and the name of the file must be identical. This module will simply draw a line; it takes no parameters.

GLOBAL DRAWING MODULE line();
BEGINMODULE
lin_free(#1,vec(10, 10), vec(60, 40));
ENDMODULE

Then compile this module using the mbsc MBS compiler:

mbsc line

The compilation should complete with no errors. This will leave an object file, line.MBO, in the mbs directory. If an mbsc shell script was set up, as described in section 3.6. mbsc Setup, then this object file will be automatically copied into the job directory, where Varkon can find it. Otherwise, it is necessary to copy the object file to the job It is necessary, therefore, to copy the object file to the job directory manually: cp line.MBO ../job

To see how an externally created and compiled MBS module such as line is used, start the Varkon system and create a new 2D Drawing job within the test1 project. Edit the MBS as described in section 4.5.3 above and create an active MBS module with the following contents:

GLOBAL GEOMETRY MODULE test2d();
BEGINMODULE
clear_pm(); part(#1,line():PEN=2);
ENDMODULE

The clear_pm() statement clears the PM cache, causing the entire model to be re-loaded from compiled source (.MBO files) on disk. The part statement is used to create a part which consists of a call to the user-written "line()" module. All user-written modules must be called via the part() construct.


Legal Matters

With the exception of any material noted as being in the public domain, the text, images, and encoding of this document are copyright © 1998 by David M. MacMillan.

The author has no relationship with Microform AB, and this Tutorial is neither a product of nor endorsed by Microform AB.

"Varkon" is a registered trademark of Microform AB, Sweden.

This document is licensed for private, noncommercial, nonprofit viewing by individuals on the World Wide Web. Any other use or copying, including but not limited to republication in printed or electronic media, modification or the creation of derivative works, and any use for profit, is prohibited.

This writing is distributed in the hope that it will be useful, but "as-is," without any warranty of any kind, expressed or implied; without even the implied warranty of merchantability or fitness for a particular purpose.

In no event will the author(s) or editor(s) of this document be liable to you or to any other party for damages, including any general, special, incidental or consequential damages arising out of your use of or inability to use this document or the information contained in it, even if you have been advised of the possibility of such damages.

In no event will the author(s) or editor(s) of this document be liable to you or to any other party for any injury, death, disfigurement, or other personal damage arising out of your use of or inability to use this document or the information contained in it, even if you have been advised of the possibility of such injury, death, disfigurement, or other personal damage.

All trademarks or registered trademarks used in this document are the properties of their respective owners and (with the possible exception of any marks owned by the author(s) or editor(s) of this document) are used here for purposes of identification only. A trademark catalog page lists the marks known to be used on these web pages. Please e-mail dmm@lemur.com if you believe that the recognition of a trademark has been overlooked.


Version 1.5, 1998/06/17. Feedback to dmm@lemur.com
http://www.database.com/~lemur/vk-mbsedit.html


Go to the: