GMC introductory guide and specification

GMC (or Grendel MUD C if you will) is a language similar to C, devised for the sole purpose of powering the scripted parts of the Grendel MUD Server.

It has support for variables, control structures, (nested) functions and external variables/traps.

The system consists of a compiler, an assembler and a virtual machine setup which can be called from an application, in this case Grendel.

Syntax

The GMC language is in many respects quite like C, with some simplifications and exceptions.

The most important supported language constructs:

  • global and local variables

  • function definitions

  • loops (only for currently)

  • 'include' files

  • basic flow control (if statements)

  • valid integer and boolean expressions

Compiler

The GMC compiler works in four distinct passes.

In the first pass, the source files are scanned and parsed, and basic syntax checking is performed.

The second pass performs type checking and coercion.

In the third pass an optimizer performs some basic optimizations: dead-code elimination, algebraic simplication (constant elimination) and some flow-of- control optimizations.

The fourth and final pass is the code generator, where assembly code for the stack machine is written to a file.

Assembler

The assembler simply converts the "human readable" assembly code to a binary format (this includes translating the labels for jumps/calls).

Additionally, the assembler performs some simple optimizations (in a section commonly known as the 'peephole optimizer'), to reduce the number of instructions.

Virtual Machine

The VM of the GMC language is a fully functional stack machine processor with some 40+ opcodes in its instruction set.

Internally the machine consists of a stack utilizing the Delphi 'variant' type.

Apart from the stack there are a number of registers - the stack pointer, the base pointer, and the program counter (or instruction pointer). Only the first two can be accessed directly from the assembler.

Lastly there is a data segment present. Its size is defined through the assembler directive '$DATA'.

'Getting out' of the VM

The VM has support for a number of mechanisms to help a program 'get out' of the environment and have some interaction with the calling application.

These mechanisms are:

  • System traps

  • Signals and sleep

  • External variables

  • External methods

The system trap (in the form of do("some expression")) can be set to a userspecified function by the calling application. The trap can do with the string expression as it sees fit.

Signals are used to "suspend" the execution of the program until some condition has been met (e.g. a signal has been raised) in another part of the server (wether that be native or scripted code). The sleep function suspends the program until a certain tickcount has been reached.

External variables are a construct to associate external data with names or expressions in the GMC language.

External methods are methods within a class, that are registered before a script is executed. In a script they are represented by a function without a body ('float cos(float x);' for example). These 'callbacks' are somewhat dangerous, as there is no mechanism to check the validity of the parameters specified in the declaration, nor the values provided at the time of calling.

Types

GMC only allows basic (primitive) types - thus compound and structured types or arrays are not included in the language.

The following basic types are supported:

  • int

    Mapped to the pascal type integer

  • bool

    Alias for int

  • float

    Mapped to the pascal type single

  • string

    Mapped to the pascal type LongString

  • void

    Should not be used for basic identifiers

  • external

    A special type; it has no strict semantic meaning in itself, but will evaluate to a callback to the shell surrounding (or calling, if you will) the VM. This callback will take care of the necessary checks (including or excluding typing) and return a value associated with the external.

Example 4. Associating a variable with the environment

external ch;
ch = "Grimlord";

Executing this snippet will have the external callback trying to associate the string value "Grimlord" with some enviroment. If this association succeeds, the resulting value will be placed in 'ch'.

Example 5. De-referencing an external value

x = ch.alignment;

Again, this will have the callback trying to associate the member variable 'alignment' with the (already associated) variable 'ch'. Care must be taken that this member variable does actually exist, or hell will fall down and chaos will ensue.

Common entry points

An 'entry point' is a position in your script code that has a common syntax or structure, and can be easily identified by the calling process. These entry points can be viewed as seperate blocks of code that are called when a particular event is triggered.

Below you will find some common entry points that are used throughout the server code.

  • void onTick(external ch)

    Called every second

  • void onAct(external ch, external target, string arg)

    Called when ch receives some action arg from target

  • void onFight(external ch, external target)

    Called every fight tick

  • void onDeath(external ch, external target)

    Called when ch dies at the hands of target

  • void onReset(external ch)

    Called when ch resets (spawns)

  • bool onBlock(external ch, external target, string dir)

    Called when target tries to leaves the room where ch is (in direction dir). Returns true when blocking

  • void onGive(external ch, external target, external obj)

    Called when target gives obj to ch

  • void onEmoteTarget(external victim, external actor, string arg)

    Called when victim is target of an emote executed by actor (e.g. slap victim). The name of the emote (Name:-field from system\socials.dat, e.g. 'SLAP') will be in arg.

    Note

    When an entry point onEmoteTarget exists, the default emote handling (as defined in checkSocial() in mudsystem.pas) will not be used.

  • void onGreet(external ch, external target)

    Called when target enters the room where ch is