Lunar Programming Language

by David A. Moon
January 2017 - January 2018



Organizing Mechanisms

Lunar includes five organizing mechanisms: files, modules, types, functions, and macros. Most languages conflate one or more of these mechanisms, but in Lunar they are independent and orthogonal.

Files are the units of source code. This makes them the units of compilation and of loading executable code. Breaking a program into multiple files eases maintenance and delivery of the program, especially when different individuals or organizations are responsible for different files.

Modules are the units of global name scoping. A module can import named definitions from other modules. Breaking a program into multiple modules makes name conflict issues tractable.

Types are the units of data classification. A type is a dichotomy that classifies every object as either a member of the type or not a member of the type. Classes are the most important type of type in Lunar. A class defines the structure of its member objects as a set of named slots that can hold values. A class can inherit typeness and slots from other classes.

Functions are the units of behavior. In Lunar all functions are composite, being constructed at load time from one or more pieces of executable code called methods.

Macros are the units of language definition. A macro defines the syntax of a construct by specifying the procedure for parsing that construct, and defines the semantics of a construct by expanding into the implementation of that construct. The syntax of Lunar is not built into the compiler, but is entirely defined by macros (many of which are defined by the implementation rather than by the user, of course). The compiler is only concerned with the semantics of the primitive expressions. This enables users to define their own languages based on Lunar which are every bit as flexible, powerful, and clean as the base language.

A few examples of the orthogonality of these mechanisms:

The language semantics are as if a residential environment is being used, i.e. the compiler coexists with the user program in the same object space. New code can be constructed at run time and compiled into the environment of the running program (unless you build an application where that feature is disabled.)

The best source code editor would be a residential environment where the editor has full access to parsing functions and macro definitions, which it can use to understand the structure of the source text.

However, separate compilation is possible. In this case, at least the parts of the user program executed by user-written macros coexist with the compiler. However, the compiler outputs a "fasl file" consisting of instructions for loading the compiled user program into another environment. Previously compiled code can be loaded into a program at run time (unless you build an application where that feature is disabled.)

For the compiler to compile itself and the runtime, there can be a special compilation environment that uses module renaming to keep the currently executing compiler and runtime separate from the new compiler and runtime that are being compiled.

One could imagine an application builder that strips out all methods that are not called and all objects that are not accessed. This could include removing the compiler and the loader.


Previous page   Table of Contents   Next page



Creative Commons License
Lunar by David A. Moon is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Please inform me if you find this useful, or use any of the ideas embedded in it.
Comments and criticisms to dave underscore moon atsign alum dot mit dot edu.