Yet Another Useless Language Part 3 — Variables

This is the third part of the YAUL series. For your convenience you can find other parts in the table of contents in Part 1 — Introduction

Today we will implement class for holding values in YAUL language


We do not have static typing, so every variable will need to be able to store three different types of values: integers, strings, and arrays. This means that all operations will need to check what type of variable they are working with — adding numbers will be different than adding strings. So let’s begin.

We have one field representing the value. We also have copy constructor — its implementation is in fact overly complicated (because we don’t need to explicitly copy integers or strings), but it shows how we would like to handle different types of value. We also have helper functions for checking types and values. We could simplify them, but let it be for now.

Accessing array

This is the code for accessing array elements:

We explicitly check types when accessing values. For arrays we extract value by element index, for strings we extract specified character. We do not handle more sophisticated cases here, like surruogate pairs.

We also define methods to access elements using SimpleObject as an index variable:

Basic operators

Let’s now implement basic functions:

All of them are rather trivial. Addition for numbers works as usual, for strings it joins them, for arrays it catenates them. Other operators works only for numbers.


Comparison operators are pretty trivial:

Numbers and strings are compared using .NET functions. For arrays we first compare their length, and then we compare their contents.

True or false

We can also convert objects to boolean values:

Number is true only when it is not zero. String is true when it is not null or empty. Array is true when it is not empty.


For completeness we implement equality operators:

And we are done. To be sure that we implemented everything correctly we should implement tests.


Now we are able to perform basic operations on our values. Since every variable will be represented using just this one type, we don’t need to handle different representation cases and implement casting.