-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Welcome to the Orange wiki!
Orange is a statically typed compiled language built to be simple but still have enough features to be usable.
Just like most languages, Orange starts off execution at the main function.
fn main
println("Hello, World!")
end
Function headers start with the fn
keyword and the body ends with the end
keyword.
You'll notice that we don't have parentheses in the function header. Orange doesn't use parentheses in the syntax of function definitions.
Variables are declared using the let
keyword. We can perform basic arithmetic and assign values with familiar expression syntax from other languages.
fn main
let x int
let y int
y = 4
x = y * 2
print("The values of x and y are: ")
print(x) // 8
print(" and ")
println(y) // 4
end
You would also notice that the print
and println
functions can take integers or strings as their arguments. This is called polymorphism, a concept we will see more of in the language later on. The compiler internally creates a new instance of the function for each type of argument passed to it.
Here is the list of all the basic types that come with the language (as of Feb 2024):
-
int
- A signed integer. Always takes up 4 bytes. -
char
- A simple character. One byte. -
str
- An alias for a pointer to characters. -
void
- A zero-sized type. -
u64
- Takes up 8 bytes. Useful for hash algorithms or bit-optimised code -
any
- Represents any type. Can only be used as a pointer -&any
We can create pointers by prepending a type with &
. eg:
-
&int
points to an integer -
&char
points to a character. Similar tostr
, but the compiler will complain when assigning between the two types. -
&any
represents a generic pointer.any
types are not allowed to exist independently, therefore variables of this type cannot be dereferenced. - And similarly for any other type...
An important point to note is that Orange is strongly typed. This means that a variable of one type cannot be assigned to a variable of any other type. Thus, the following is not allowed:
let x char
let y &int
y = &x // ERROR
Every good programming language needs to have functions so that us mere mortals can write maintainable code.
fn double_it: int x -> int
return x * 2
end
Here, we have defined a simple function double_it
that takes an integer and returns an integer with the doubled value.
The syntax of the function header does not use parentheses. We have a colon :
instead. The argument has a type and the name after the type - int x
.
The return type in the signature is indicated by ->
. It is optional as we saw in fn main
, where the omission of the return type implies a return type of void
.
We can call the function normally in our main
function like so:
fn double_it: int x -> int
return x * 2
end
fn main
let y int
let x int
y = 4
x = double_it(y)
print("The values of x and y are: ")
print(x) // 8
print(" and ")
println(y) // 4
end
Apart from the builtin types, Orange lets us make our own types using the type
keyword.
type ComplexInt
let real int
let imag int
end
fn main
let c ComplexInt
c.real = 5
c.imag = 7
println(c.real) // 5
println(c.imag) // 7
end
Here, we have created a ComplexInt
type with two fields - real
and imag
. Fields are accessible using the dot .
operator. Types defined in Orange can have fields that use any type. Even the type itself.
type IntNode
let data int
let next &IntNode
end
As a bonus, the dot .
operator can also be used on a pointer to a type as well.
type IntNode
let data int
let next &IntNode
end
fn main
let node IntNode
let node_ref &IntNode
node_ref = &node
node_ref.data = 15
println(node.data) // 15
end
Here, we have created two variables node
and node_ref
of types IntNode
and &IntNode
respectively. Then, because we set node_ref
to point to node
, we can modify the contents of node
through node_ref
. We can see that accessing the data
field of node_ref
requires the same dot operator - node_ref.data
.
If you have dealt with linked lists in a low-level language like C before, you will know that they are useful only when coupled with the use of dynamic memory allocation.
Dynamic memory allocation is a way to hold onto some memory for an arbitrary amount of time. This is unlike regular variables in a function which go away after the return statement.
In Orange, dynamic memory allocation is done using the alloc
and free
functions.