The Basics
Ryna is an imperative, strongly-typed programming language with many common features. Here We will explain the main ones. All these should be enough to get you started writing basic code, but more complex features will be analyzed later in their own respective sections.
Literals
One of the main ways you can create values is by writing down explicit constants that the compiler will understand as basic types. These are called literals and are a very important concept in many languages, but more so in Ryna. Here are all the literals that tthe language supports.
Integers
Integers can be inputted in Ryna in a similar way as other languages:
881452 // Basic integer (no size limit)
-32 // Negative integers are also literals
0b1000110 // Binary integers (70 in this case)
0xFF1A // Hexadecimal integers (65306 in this case)
All these values are compiled to Int
values.
Floating Point numbers
Floating point numbers are more or less the same as in other languages:
1.56 // Basic float
-67.2 // Negative floats are also literals
1e10 // Scientific notation is allowed
2E-5
1.5e2
-2.2E-8
All these values are compiled to Float
values.
Logical values
The only logical literals Ryna supports are true
and false
. They are compiled to Bool
values.
Strings
Strings in Ryna are UTF-8 encoded and are inputted by using double quotes with the possibility of escape sequences. These would be some examples:
"This is an example"
"This is an example with \t tabs and line \n jumps"
"Also, you
can have
multiline
strings"
All these values are compiled to String
values.
Characters
Characters do not exist in Ryna as a class, but they can be used as Int
code points:
'w' // This is equal to 119
This can be used when iterating over code points.
Variables
In contrast to functional languages, Ryna does have support for variables and they are used as much as in any other imperative language. Constants are not implemented for now, but they might be introduced in a future release.
Definition
The syntax for variable definitions is as follows:
let name: Type = expression;
In let
statements, name
can be any alphanumeric identifier that does not begin with a number ("_" is also allowed),
Type
can be any valid type of the ones seen in the Type System section and expression
can be anything that is not a
statement. These would be some valid examples:
let example_1: Int = 3 + 6; // Simple definition
let example_2 = 3 + 6; // Here the Int type is inferred
let example_3 = "Test"; // A String type is inferred
Assignment
When you have already defined a variable, you can replace its value by using the =
operator:
let example: Int = 3 + 6;
example = 5; // Replace the value by 5
example = true; // ERROR: Bool is not bindable to Int
Getting values
To get the value of a variable, just use its name in the code. Note that you will get a Reference to the value instead of the value to prevent the user from making unnecessary copies:
let big = "Imagine this is a very big string ...";
let big_2: String = big; // ERROR: @String is not bindable to String
let big_3: @String = big; // Keeps a reference
let big_4: String = big.deref(); // Copies the original data
let big_5: &String = big.demut(); // Keeps a constant reference
Reference assignment
Sometimes you might need to change the underlying values of a mutable reference. An example of this would be trying to change an element inside an array
or mutating a class instance. For these cases you can use the :=
operator:
/*
Imagine a class Example that has an Int
attribute called attribute_1
*/
let example: Example = some_class_instance;
example.attribute_1() := 5; // This is only allowed using this operator
example.attribute_1() := "Test" // ERROR: String is not bindable to Int
Functions
You can also use functions in Ryna, as you might expect. Functions are called using the parentheses syntax used in most imperative languages, including angle brackets in the case of generics.
Operations
Just as most programming languages, Ryna has operators and operations. These encode operations with one, two o even more expressions called operands. Ryna supports four kind of operators:
- Prefix operators: the operator comes before a single expression (example:
-5
). - Postfix operators: the operator comes after a single expression (example:
5!
). - Binary (infix) operators: the operator comes betwwen two expressions (example:
1 + 2
). - N-ary operators: the operator has an opening and a closing delimiter. Operands are before and inside the delimiters (example:
mat[4, 5]
).
All these operators and operations can be defined in a similar way as functions. The syntax for generics varies depending on the type of operator and will be explained in their corresponding section.
Flow control
These are the flow-control operations that are allowed in Ryna.
If-else
The language supports if-else control flow with the following syntax:
// Else ifs and elses are optional
if condition {
[...]
} else if condition {
[...]
} else {
[...]
}
conditions must evaluate to Bool
.
While
While loops have the following syntax:
while condition {
[...]
}
conditions must also evaluate to Bool
. You can break
and continue
in while loops.
For
For loops are the most complicated of the three. To begin with, you need an Iterable
object, which is defined as
one that implements the Iterable
interface (more information about interfaces in their section). After this, you can write
the following:
// container must implement Iterable
for i in container {
[...]
}
if you want to make a custom class iterable you have to implement that Interface manually. You can break
and continue
in for loops.