simple() void {

a=1 //immutable variable
b``=2 //mutable variable
b`=3 //Modify a mutable variable

c``=$int
d``=$u8[123] //128 byte array
e``=$int //int is either 32 or 64bits. Currently always 64bit.
f``=$int[10] //10 element array of 8bytes/64bits. 80byte in total
$$int g, h=5 //Both g and h are mutable.

puts("Simple")
puts(itoa(h)) //Both of these functions are defined in internal.dio
//itoa converts an int to c string using u8[23] (a 23 byte unsigned array)
//puts is a C function that puts a string into stdout.
//C functions are unsafe and will eventually require the unsafe keyword.

assert(SimpleEnum.a == 0)
assert(SimpleEnum.b == 1)
assert(SimpleEnum.c == 2)

assert(BitFlags.a == 1)
assert(BitFlags.b == 2)
assert(BitFlags.c == 4)
}

enum SimpleEnum { a, b, c}
bitnum BitFlags { a, b, c}

class SimpleClass {
int? a, b //both are nullable
int c?, d //only c is nullable
f32 f //float
f64 g //double
h=25 //int literal, doesn't take up space in the class
i = "Also a literal"
this() { puts("SimpleClass Constructor")} //May change into _Constructor()
this { puts("SimpleClass Destructor")} //May change into _Destructor()
test(=d) void {
//You don't have to do anything. The parameter d is the same type as the member d
//It is then automatically assigned. Very useful in constructors
}
static StaticFunc() void {
puts("StaticFunc")
}
}

globalVar``=5 //mutable global var

TestFunc(int plainInt, nullableInt?, mutableInt`, outVariable``; f64 f) f64
{
//1: mutable params may be modified
//2: out params MUST be modified
//3: types are seperated by semicolon
//4: Return type is at the end
mutableInt`= nullableInt ?? plainInt //If the left side of ?? is null use the right side
outVariable`=5
return f*2.1
}
//temp``=0; TestFunc(1, null, temp`, outVar``, 1.2) //outVar is automatically declared

branch() void
{
puts("branch")
//ALL for loops must have curly braces
for i to 3
{
puts(itoa(i))
}
puts("")
for element in [4, 8, 5, 2]
{
puts(itoa(element))
}
puts("")
z``=5
for z<8 //Acts like a while loop
{
puts(itoa(z))
z++
}
puts("True") if z > 5 //single line if statement
if z<5 //If also must have curly brances unless in single line form above
{
puts("Less than 5")
}
else {
puts("z >= 5")
}

//instead of 1>5 ? 25 : 68 we do the following
result = if(1>5, 25, 68)
puts(itoa(result))
}

math() void {
puts("math")
t = 1!=2 //true
f = 1==2 //false
if t
{
puts("t is true")
}
if f! //not operator goes at the end
{
puts("f is false")
}
a ``= 0~ //bitwise compliment is also after the value. a == -1
//common operators exist
a+=2 //is 1
puts(itoa(a))
puts(itoa(--a))
puts(itoa(1<<2))
}
array() void
{
puts("array")
a=[3, 5, 7, 9, 4]
puts("2:")
for i in a[2:] //7 9 4
{
puts(itoa(i))
}
puts(":3")
for i in a[:3] //3, 5, 7
{
puts(itoa(i))
}
puts("1:3")
for i in a[1:3] //5, 7
{
puts(itoa(i))
}
}

struct PlainOldData1 { int a, b, c }
struct PlainOldData2 { int d, e, f }
struct PlainOldDataInherit : PlainOldData1, PlainOldData2
{
int g
}
interface SimpleAddInterface
{
get(int v) int
}

//Classes MAY NOT inherit structs, but they can implement interfaces
class SimpleAddClass : SimpleAddInterface
{
int value
this(int v) {value `= v}
get(int v) int { return v+value }
}
PrintSimpleAddInterface(SimpleAddInterface g) void {
puts("PrintSimpleAddInterface")
puts(itoa(g.get(4)))
}

templatedAdd$T(T a, b) int { return a+b }
class Rect$T {
T left, top, right, bottom
Intersect(T x, y) bool
{
return (x>=left && x<=right) && (y>=top && x<=bottom)
}
}

errorExample(int a) int | error //For now only one type and error is allowed
{
return error if a > 10
return a * 2;
}

struct OpOverloadStruct
{
int a, b
_Operator + (int v) int { return a+v }
_Operator * (int v) int { return a*v }
_Operator[](int v) int {return v } //Read version
_Operator[](int k, v) int {return a*1000+b*100+k*10+v } //Write version
_Operator[](string k, v) int { Write(k); WriteLine(v); return a } //Write version
Head[](string k, v) int { Write(v); WriteLine(k); return b }
Head[](string k) int { return a*b }
_Operator += (int v) int { a+=v; return a }
}
_Operator - (OpOverloadStruct a; int v) int { return 68 }

OutideFunc(OpOverloadStruct d`; int v) void {
d.a `= v
}
OutideFunc(OpOverloadStruct d`; string v) void {
puts(v)
}

_Extend { OutideFunc }

OperatorOverloadTest() int
{
v``=$OpOverloadStruct
v.a `= 3
v.b `= 7
assert(v[5] == 5)
assert(v+5 == 8)
assert(v*5 == 15)
assert((v[5]`=4) == 3754)
v["He"]`="llo"
v.Head["He"]`="llo"
assert(v.Head["He"] == 21)
v+=2
assert(v.a==5)

OutideFunc(v`, 35)
assert(v.a==35)
v.OutideFunc(41)
assert(v.a==41)
v.OutideFunc("OperatorOverloadTest Successful")
return 0
}

lambda_static(_StaticFunc(int a) int cb) int { return cb(25)*2 }
lambda_typical(_Func(int a) int cb) int { return cb(4) + 30 }

lambda_example() void
{
a``=100
assert(lambda_static(v => v+5)==60)
assert(lambda_typical(v => 6000+a+v)==6134)
}

//internal.dio is a good example of how to use c code and create a wrapper

main() int {
simple()
branch()
math()
array()
lambda_example()

PrintSimpleAddInterface($SimpleAddClass(20))
puts(itoa(templatedAdd(250, 7)))
puts(itoa(templatedAdd$u8(250, 7)))

OperatorOverloadTest()

varThatIsntALiteral ``= 25
a ``=$u8[varThatIsntALiteral] //this uses malloc since size isn't known at compile time due to not using a literal
//a[30]`=5 //Run time error here if we uncomment
a.Resize(50)
a[30]`=5 //ok

b = errorExample(6) ## {
puts("Shouldn't get here")
return -1;
}
puts(itoa(b))
c = errorExample(16) ## {
puts("Always gets here")
return 0;
}
puts("Never gets here")
return -2
}