Aztec® Programming Language
Version 1.1 Alpha 2

Copyright © 2010-2017, Aztec Development Group, All Rights Reserved

Download Aztec

Search        Contact Us

But I need a break...

And I want to be a Paperback Writer.

- Lennon and McCartney

 

The Aztec Build process performs six separate compile steps for each source code module, as described in detail in the "Executing Compile-Time Logic" page. The first four steps are performed at the module and class level, and the last two are performed at the method level. With multiple modules, the six steps are woven together across the modules to move them all forward together through the six compile steps.

The net result of this multi-step build process is that there is a single compiler step dedicated to executing logic at the module and class level. There is no separate pre-processing language with Aztec. The compile-time logic is performed using the full Aztec language syntax, and supports full mathematical expression evaluation, calling (compiler) methods, assigning values to (compiler) data items, and using Aztec flow control statements.

The Aztec Framework also provides a large assortment of methods that can be called during this "compiler execution" step.

♦ Each primitive class provides a 'compiler' version of most of its methods.

♦ The framework also provides useful compiler methods in the following categories.

♦ Text File I/O

♦ System Level (Space utilities, Time, Log, Command Line Flag detection, and CompilerLoadModule())

♦ User Dialogs (Prompt, Text Edit, File Selection, Folder Selection)

The CompilerLoadModule() method queues up a source code module to be compiled along with the existing set of modules. The system compiles it in a well defined order based on the rules specified on the compile-time logic page mentioned above. The source code for the load module call can be in a file or it can be "dynamically created" at compile-time and passed to load module as a string.

Example Script Using Compile-Time Logic

This section discusses a fairly simple script which shows how to use some of the compile-time logic methods that are available, and also demonstrates a powerful capability of reading in data files at compile time. If a script reads in the contents of a text file during the compile phase and stores the data in one or more data items, the data will automatically be embedded in the byte code executable file. When the Aztec bytecode file is executed, the variables in question are automatically and immediately initialized with the contents of the text file that had been read in during the compile session. There are two important benefits to this approach.

♦ The text file(s) only need to be available during the compile session, since the contents are automatically embedded in the executable file.

♦ The more processing of the text data that is performed at compile-time, the faster the program will load at run-time.

♦ The contents of the data file can simply be read in record by record and assigned to a single string compiler variable, to be further parsed and processed at run-time.

♦ The contents of the data file can be parsed at compile time, initialization code for an array can be built up and then dynamically compiled once the entire initialization string is done.

♦ Both of the above approaches do not require the text file(s) at run-time, but the second approach will tend to load faster, and may provide a more elegant solution.

Of course, the real benefit of this approach is not realized when executing the Aztec Engine in an "interpret" mode (compile and execute in one shot). This is particularly beneficial when the script is compiled separately, and is very useful for help files, or any type of input data file that is static for a single release of the script/application.

In the example script shown below, the logic in the CompilerProcessDataFile() method creates array initialization code for a simple class that contains two strings. The method reads each record and builds a string containing Aztec source code to create an initialized array using the data from the file. The string will look something like this, depending on the data in the file.

public data<SimpleClass[]> SimpleClassArray = { new<SimpleClass('Str1a','Str2a')>, new<SimpleClass('Str1b','Str2b')>, new<SimpleClass('Str1c','Str2c')> }

The script calls the CompilerProcessDataFile() method at the module level during the Compiler Execution step. If successful, it then calls the CompilerLoadModule() method to compile the source code string as a standalone module, which causes the Build system to queue up the module to go through the entire set of six compiler steps as discussed above. Once this call is made successfully, "SimpleClassArray" becomes a valid global identifier, and it is used in the Main() method. The "dynamic" code to define and initialize the array is implemented in a separate module. Since the default visibility for global data items is 'module', the 'public' keyword is needed here so that the main module can see the array.

The Aztec source code for this example compile-time logic script is shown below.


    
#===========================================================================================
# Example Script: WhyCompileTime
# Demonstrates the use of compile-time logic and creates array dynamically during compile.
#===========================================================================================

#----------------------------------------------------------------------------------------
# Compiler variables to hold the array initialization code and name of the actual array.
# The code will ultimately create a global array variable named 'SimpleClassArray'.
#----------------------------------------------------------------------------------------
data<bool> compiler FileSuccess = false
data<string> compiler DataFileName = "AztecTest.txt"
data<string> compiler ClassArrayName = "SimpleClassArray"
data<string> compiler FullArrayInitCode = "public data<SimpleClass[]> " + ClassArrayName + " = { "

# Process data file at compile time and build up the array initialization code.
FileSuccess = CompilerProcessDataFile(DataFileName)
if ( FileSuccess )
{
# Dynamically compile the code to create and initialize the 'SimpleClassArray' array.
CompilerLoadModule(FullArrayInitCode,false)
}
else
{
CompilerWriteLog("Error reading data file '" + DataFileName + "'. Compile process was aborted.")
CompilerAbort()
}

# Compile-time method to read file, parse each record into two strings, and create array initialization string.
method<bool> compiler CompilerProcessDataFile(string FileName)
{
data<int> FileId
data<int> NumRecords = 0
data<bool> Success = false
data<string> Record
data<string> RecArrayInitCode

# Open the text file for processing and check for success.
FileId = CompilerOpenFile(FileName)
if ( FileId > 0 )
{
# Loop through entire text file and process each record one at a time.
while ( !CompilerEndOfFile(FileId) )
{
CompilerInc(@NumRecords)

# Read the record, parse it into two items, and create the 'new<>' code for this record.
Record = CompilerReadFile(FileId)
RecArrayInitCode = "new<SimpleClass('" + CompilerStrToken(Record,1) + "','" + CompilerStrToken(Record,2) + "')>"

# If we're not first line, precede with comma to separate from previous record.
if ( NumRecords > 1 )
{
RecArrayInitCode = "," + RecArrayInitCode
}

# Add the record level code to the full string of code.
CompilerStrAdd(@FullArrayInitCode,RecArrayInitCode)
}

# If we have at least one record, set success flag and append final '}' to array init code.
if ( NumRecords > 0 )
{
Success = true
CompilerStrAdd(@FullArrayInitCode,"}")
}
}

return(Success)
}

# Main is the script's run-time entry point. Sit in a loop and dump out array contents.
method Main()
{
data<int> Count
data<SimpleClass> MyClass

# Loop through array that was created and initialized "dynamically" at compile-time.
iterate ( Count in 1..SimpleClassArray.Size() )
{
# Get this object from the array and write it to console.
MyClass = SimpleClassArray[Count]
StdIO.Write(MyClass.Name1() + "," + MyClass.Name2())
}
}

# Simple example class to store contents of a single text record.
class SimpleClass
{
method SimpleClass(string Str1, string Str2)
{
Name1 = Str1
Name2 = Str2
}

method<string> Name1()
{
return(Name1)
}

method<string> Name2()
{
return(Name2)
}

data<string> Name1
data<string> Name2
}

Page UpPage DownCopyright © 2010-2017
Aztec Development Group
All Rights Reserved

Download Aztec