SIMPL+ Tips and Tricks

Advertisements

I’ve spent the last week or so diving into Crestron SIMPL+ and have been reminded what a quirky language it is.  Here are some of the concepts I’ve been bitten by.

No Forward References

In somewhat of a throwback to the days of Turbo Pascal, SIMPL+ doesn’t allow you to reference a function or variable before it is declared.  This means you end up with most utility functions written near the top of the file and manager functions near the bottom.  For example, the Trim function must be declared before the ProcessConfigLine function that uses it:

String_Function Trim (STRING text)
{
    // ...
    Return(Mid(text, i, j - i + 1));
}

Integer_Function ProcessConfigLine (STRING text)
{
    STRING temp[100];

    // Trim spaces, comments, and newlines
    temp = Trim(text);

    // ...
}
Advertisements

If you try to move Trim below ProcessConfigLine, the compiler spits out:

Error 1400 [Line 7] - Illegal Assignment

This is likely due to the design of the SIMPL+ compiler (SPlusCC) as it appears to only do a single-pass of the program.  However, you can still write recursive functions:

Integer_Function Fib (INTEGER n)
{
    If (n < 3)
    {
        Return(1);
    }
    Return(Fib(n - 1) + Fib(n - 2));
}

Calling Fib(23) returns 28,657 in roughly one second.  Unfortunately, anything above Fib(23) overflows Signed_Integer.

Structures May Not Include Other Structures

From the help file, Structures may only contain: IntegerLong_IntegerSigned_IntegerSigned_Long_Integer, and String fields.  Also, String arrays are not allowed, but Integer arrays may be 1 or 2 dimensional.  Classic example:

STRUCTURE PhoneBookEntry
{
    STRING Name[50];
    STRING Address[100];
    STRING Number[50];
};

If you wanted a structure that could store multiple numbers per name, you’d have to create additional fields:

STRUCTURE PhoneBookEntry
{
    STRING Name[50];
    STRING Address[100];
    STRING Number1[50];
    STRING Number2[50];
}

If you pass a structure into a function, it is passed by reference, which leads to the next topic…

No Pointers

Advertisements

Representing complex data structures in memory using SIMPL+ is a bit of a challenge when you can’t reference anything directly.  References do exist (in the case of passing a structure or string array into a function) but they aren’t exposed by the language.  One way around this is to use the index into a record set as the pointer.

For example, say we have a phonebook we’re trying to display to the user.  But it can have multiple layers of folder structure.

STRUCTURE PhoneBookEntry
{
    INTEGER Type;
    INTEGER Index;
};

STRUCTURE FolderEntry
{
    STRING  Name[100];
    INTEGER Index[100];
};

STRUCTURE NumberEntry
{
    STRING Name[100];
    STRING Number[50];
};

Here we’ve defined our structures while staying within the limitations of what they may contain.  We can index from one record set into another to create the essence of references. For example, say we start with PhoneBookEntry[1] represents the root folder of the phonebook: Type would be set to 1 (to indicate it’s a folder), and Index would be set to 1 (to point into the FolderEntry table).  Now we check FolderEntry[1] (since Type=1 told us Index=1 pointed there).  FolderEntry[1] tells us the name of the current folder (say “Contacts”) and a list of up to 100 entries that can be stored there in Index.  These entries can be other folders or number entries since they point back into PhoneBookEntry.  A value of 0 is used to indicate empty or unused space within the folder.

We would need to develop some utility functions to make this less of a headache than it is.  To list the contents of a folder, we might write:

PhoneBookEntry PhoneBook[200];
FolderEntry    Folders[100];
NumberEntry    Numbers[100];

Function ListFolderContents (INTEGER i)
{
    INTEGER j;

    For (j = 1 To 100)
    {
        // Check for non-empty slots
        If (Folders[i].Index[j] > 0)
        {
            If (PhoneBook[Folders[i].Index[j]].Type = 1) // Folder
            {
                Trace("[%s]",
                    Folders[PhoneBook[Folders[i].Index[j]].Index].Name);
            }
            Else // Name and Number
            {
                Trace("%s - %s",
                    Numbers[PhoneBook[Folders[i].Index[j]].Index].Name,
                    Numbers[PhoneBook[Folders[i].Index[j]].Index].Number);
            }
        }
    }
}
Advertisements

As you can see, working around not having pointers can look a little ugly.  That’s all I have time to write down for today, but there is still more quirkiness to document in Crestron’s SIMPL+ compiler

One comment

  1. While Simpl+ doesn’t allow pointers, it does allow you to define function arguments ByRef. This acts like a pointer in the sense that if you modify the argument inside the function, it will be changed when the function exits.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s