Variables play a major role in any programming language. They represent different building blocks of a digital solution and can refer back to data or logic.
Some aspects of Simorg variables still follow the common rules of any programming language, but there are fundamental differences that make Simorg variables quite powerful.
Simorg uses <<<$>>> character befor an identifier to mark variable declaration.
What is common?
- Rule of Scope: Each variable needs to be defined using a unique identifier in a Shell (scope rule).
- Naming Conventions: Simorg variables follow naming conventions.
What is unique to Simorg?
- No Ownership: Simorg variables are data markers and they do not hold direct ownership of memory.
- Declaration not Definition: Variables are always declared and it's the responsibility of data to define them.
- Event-Driven: A Simorg variable represents an event, and this event only triggers if there is data. As we discussed, vibration is the combination of data and event.
- No Garbage Collection: Simorg variables are part of the structure of the program so no clean up or garbage collection is required.
Imagine a variable as a pipe that has inflow and outflow. Data can be seen as a stream of water which eventually flows into this pipe and exits from it. While data is passing through, it gains new characteristics that are inherited from these pathways.
Rule of Scope
Simorg variables, just like in any other CPL, are limited to their Shell (scope). It is not possible to declare two variables under the same scope with the same name.
For example, the following code is declaring three number variables,
{
1 $numA
2 $numB
3 $numC
// re-declaration is not allowed and will lead to
// a compile time error
4 $numA
}
Naming Conventions
Simorg is following the same good naming convention rules including,
- A name cannot start by a number but can include number.
- A name cannot contain special characters when being declared except for <<<_>>>.
$$$AlertBox type=INFO title=No Reserved Keywords message=Simorg does not have any reserved keyword so it is valid to use any word for your variable names.$$$
No Ownership
In a CPL, variables are linked to allocated memory either in the heap or the stack. This usually causes all sorts of problems in software engineering, e.g. dangling pointers, null pointer exceptions. Most of these problems can be categorized under memory ownership.
Of course, different languages have different solutions for this with their pros and cons, but the main problem is that the code we write (at compile time) does not give the respect that data and memory need. Simorg solves this problem by bringing a new idea of ownership. The mathematical-physical engine of Simorg gives it the ability to force data to flow inside the system. Actually, variables can be seen as the vessels/channels/pipes that the data is flowing inside. In Simorg it is the data itself that determines who can be its owner rather than the variable. A variable becomes an owner only when the data sees that it can be the owner. When data acquires a new owner, this new owner eventually gives a new characteristic to data, letting this cycle continue and letting data flow. In other words, variables can be seen as the layers/shells which are wrapping the data. Through these layers our data will have new characteristics. Data is the king in Simorg. According to this model, memory allocation and deallocation is always done by the engine whenever it is necessary, and in most cases it will be avoided.
Declaration not Definition
In a CPL, there is a difference between variable declaration and definition. Declaration is when the variable is given a known name and type, and definition is when a chunk of memory is assigned or, in other words, when the variable is implemented. The no-ownership model of Simorg allows it to give the responsibility of definition to data itself. When a program is executed it either receives its data from the constant variables that are initially defined (in physical systems this is known as Initial Conditions) or from different IOs of the system including network, file, etc. In both cases the engine is able to detect the data type with the help of special compiler syntaxes (for value literals) or later at run time when the data becomes available through IO.
Data then flows in the system and eventually reaches its destination. During this process data may pass through multiple variables causing them to Vibrate.
Event-Driven
Simorg is a fully event-driven programming language. We discussed the concepts in a previous chapter, but it is worth mentioning that everything in Simorg is an event, and the only thing that causes an event to emit/vibrate is data. This very simple rule made Simorg able to completely remove the abstract and unreal concepts of void, null, None, nil, etc. A variable is only usable when it is vibrating—and it vibrates when data is available. Being a direct result of the two previous rules, a Simorg variable represents both the data and the event/vibration when the data becomes available. When a variable vibrates, depending on the logic, we can use the data or skip it. More details about this will be given in future sections (dataflow DoNotCare operator). But it is important to know that a Vibration is guaranteed to have data.
No Garbage Collection
Simorg variables are part of the space of our application. This is important when you consider using them.
Data, on the other hand, is eventually moving into these spaces and flowing inside them. So this is detaching Simorg variables from the role of dealing with lifecycle of data.
It may help to understand them more if we completely forget about a functional universe in which the execution at some point starts and then ends. Unlike this approach, data is responsible for its own lifecycle and variables are just adding certain marks on data in certain points of execution, making it able to access new spaces of our application.
Variable Types
Data inside Simorg is directly linked to the reality of our universe. This connection is reflected not only in how data flows through the system, but also in how data-types are defined.
Simorg uses three Primitive data types <<<buffer>>>, <<<number>>> and <<<string>>>.
We call them primitive because they are the smallest units of memory in the engine. Technically, everything in memory is a <<<buffer>>> but creating two other primitives helps us avoid unnecessary details of type systems.
In next sections we will see how we can use them but now it's a good time to briefly touch upon the concept of Nothingness. It is important not to confuse Emptiness with Voidness/Nothingness. Emptiness is a state defined within existence and is a valid state for data because emptiness is always defined using a form of existence. For example empty String <<<"">>>, value <<<0>>> which represents the emptiness in numbers or value <<<0x>>> which represents empty buffer.
An important aspect of Simorg is that data is responsible for finalizing variable declaration by providing the final definition. This design removes the need for concepts like nil, null, undefined, None, and similar constructs of Nothingness that are common in CPLs.
We will explore this behavior in more detail in future chapters as we learn more about Simorg.
Variable Declaration
We will see more details later about dataflow operators and pipes, but for now let's just use a simple open-pipe dataflow operator, which is the most basic dataflow operator and just passes a vibration. The following syntax declares a variable called <<<myFirstVar>>> and pushes a default value of <<<"Hello World!">>> into it.
Create a text file called <<<variable.art>>> and put the following code in it:
"Hello World!" $myFirstVar
myFirstVar:?
By creating a variable, we are creating a data layer which is ready to wrap any incoming data. It gives a unique identity to incoming data identified by <<<myFirstVar>>>.
Lets keep the discussion about dataflows for Dataflow chapter but for now it is enough to share that data moves from left to right. Think of them as pool balls, when the left token vibrates, vibration naturally moves to the next element. So in line 1 the value literal "Hello World!" is vibrated and <<<myFirstVar>>> is receiving the vibration as it is next to it.
At the engine level <<<myFirstVar>>> is interpreted as a unique frequency which gives a unique identity to our data.
Then data enters into this variable through an operator <<<:>>>, aka Pipe Operator, and eventually causing the vibration of <<<myFirstVar>>>.
Run the app using, """ sim variable.art """ Hello World! !!!!
As soon as <<<myFirstVar>>> becomes available it vibrates, and the vibration is received by the logger (<<<:?>>> operator) and printed out in the console.
More details about these dataflow operators will be shared in the future chapters.
$$$AlertBox type=HINT title=Mathematical Beauty message= As you may have noticed, Simorg doesn't consider <<<=>>> as assignment operator, helping it to take back its mathematical identity being an equality check, relational operator. The reason is obvious as now data is flowing naturally and we don't need to manually assign it using an assignment operator.$$$
$$$AlertBox type=HINT title=What About Booleans? message= So what happened to boolean data type which is quite common in every single CPL? Well a boolean value is not actually a real data type but as it seems it found its way into CPLs due to an unpleasant mixture between control flows and dataflows. It is a virtual abstraction on top of data. Later we will see how Simorg completely removed the necessity of boolean values. After all Simorg is built on top of a decimal mathematical engine which is keeping distance from an artificial binary world as much as possible. Although we understand in short-term it may seem a bit strange to have a programming language without boolean values but the long-term benefit of this mindset is highly valuable. After all data itself is the ultimate form of reality and we don't need to impose our illusions on top of it.$$$
In next sections of this chapter we will discuss different primitive types. It is important to mention that advanced logic regarding each data type will be supported later using Plugin Artifacts.