==========================
--- Pre-processor commands ---
==========================
The initial and primary purpose for creating the pre-processor was to provide content scoping / environment scoping via scope opening and closing tags:
<? //this is an opening tag
//content in here is only included in the compiled source when building for this environment
?> //this is a closing tag
simple enough right?
---
This next lead to some other simple text editing, such as using [] for arrays.
someFunction(myArray[tIndex].someAttribute)
becomes on compile:
someFunction(myArray(tIndex).someAttribute)
---
Then normalization of native dbpro commands to always use ()
typically commands which return a value use (), commands which do not return a value do not use ():
position object tObj, 1, 1, 1
object position x(tObj)
I dislike inconsistency. So, the preprocessor will expand commands like so:
@positionObject(tObj, 1, 1, 1)
@objectPositionX(tObj)
back into:
position object tObj, 1, 1, 1
object position x(tObj)
technically speaking, it looks to the left for any non-whitespace content when determining if the command returns a value in order to keep the () or not.
@objectPositionX(tObj)
would transpile into:
object position x tObj
which is invalid syntax, but I don't know of any valid use case where you would use such commands on a line by itself without actually assigning or passing their return to anything.
myVariable = @objectPositionX(tObj)
would transpile into:
myVariable = object position x(tObj)
which is correct and valid.
someFunction(@objectPositionX(tObj))
would transpile into:
someFunction(object position x(tObj))
which is correct and valid.
You can also nest them:
@positionObject(thisObj, @objectPositionX(thatObj), @objectPositionY(thatObj), @objectPositionZ(thatObj))
((at one point it did have issues with splitting single character segments like the 'X' in @objectPositionX(), I am unsure if this was ever corrected to be honest))
For the most part, I've stopped using this feature, because all the @ symbols started to feel too noisy, but I've left the functionality in.
---
Next in order for the pre-processor to properly handle references and dependencies across multiple source files, I implemented a $require command:
$require myRelativePathFilename.dbx
$require myOtherBasicSource.dba
which is just used the same as you would (and instead of) #include
---
Some more array fun: $push()
myArray[].$push(myVariable)
will be converted to:
array insert at bottom myArray()
myArray() = myVariable
also valid:
dim myUDTarray[] as myUDT
myVariable as myUDT
myVariable.propA = "foo"
myVariable.propB.attrC = 123
myUDTarray[].$push(myVariable)
---
Lastly, $construct and $new:
My framework uses a sort of loose object oriented by convention approach. This is of course not an actual implementation of objects or classes, mostly it is a "consistent"

method of naming organization.
I'll go more into this later when discussion the framework, but to address these pre-processor commands, I came up against a memory leak involving strings in UDTs which these commands provide a quick shorthand method to resolve.
type someSubData
attributeA as string
attributeB as string
endtype
type CLASS_sceneEntity
propA as string
propB as float
propC as someSubData
endtype
GLOBAL new_sceneEntity as CLASS_sceneEntity
new_sceneEntity.propA = "myDefaultValue"
new_sceneEntity.propB = 1.23
new_sceneEntity.propC.attributeA = "anotherDefaultString"
do
tEntity as CLASS_sceneEntity
tEntity = new_sceneEntity // <----- right here.
print tEntity.propA + " :: " + tEntity.propC.attributeA
loop
now watch the memory usage go up and up and up till crash.
However, the following does not suffer from the memory leak:
type someSubData
attributeA as string
attributeB as string
endtype
type CLASS_sceneEntity
propA as string
propB as float
propC as someSubData
endtype
GLOBAL new_sceneEntity as CLASS_sceneEntity
new_sceneEntity.propA = "myDefaultValue"
new_sceneEntity.propB = 1.23
new_sceneEntity.propC.attributeA = "anotherDefaultString"
do
tEntity as CLASS_sceneEntity
tEntity.propA = new_sceneEntity.propA
tEntity.propB = new_sceneEntity.propB
tEntity.propC.attributeA = new_sceneEntity.propC.attributeA
print tEntity.propA + " :: " + tEntity.propC.attributeA
loop
thus, $construct and $new:
type someSubData
attributeA as string
attributeB as string
endtype
type CLASS_sceneEntity
propA as string
propB as float
propC as someSubData
endtype
$construct CLASS_sceneEntity{
propA = "myDefaultValue"
propB = 1.23
propC.attributeA = "anotherDefaultString"
}
do
tEntity = $new CLASS_sceneEntity
print tEntity.propA + " :: " + tEntity.propC.attributeA
loop
which is converted to:
type someSubData
attributeA as string
attributeB as string
endtype
type CLASS_sceneEntity
propA as string
propB as float
propC as someSubData
endtype
do
tEntity as CLASS_sceneEntity
tEntity.propA = "myDefaultValue"
tEntity.propB = 1.23
tEntity.propC.attributeA = "anotherDefaultString"
print tEntity.propA + " :: " + tEntity.propC.attributeA
loop
eliminating the need for a bunch of globals, and saving some memory and a ton of keystrokes on larger classes.
--------------
We'll that's the pre-processor in a nutshell. feel free to request additional features for it, though I can't guarantee a timeline on it

http://games.joshkirklin.com/sulium
A single player RPG featuring a branching, player driven storyline of meaningful choices and multiple endings alongside challenging active combat and intelligent AI.