Language Idea

Tuples

Tuples are the product types. They basically are an ordered lists containing other types. This also means that tuples can be nested. Tuple values can be stored simply by putting the memeber values continuosly on the stack or heap. Tuples are used mainly for functions to get multiple parameters and mutiple return values. There are named and unnamed tuples. The named tuples are only used for accessing members.

Unnamed tuple types can be written by listing the members between parenthesis separated by commas. Named tuple types are the same but every type should be fallowed by a valid id. Unnamed tuple values are created by listing values between parentheses. Their type is deduced at compile time. Named tuple values are created with assignment syntax. Tuples can be cast to any named tuples with the same types included without any runtime cost.

(int, double) a = (5, 2.5);
(int, double) b = (2, 5.5);

a = b;
// cannot access members

(int x, double y) c = (5, 2.5);
(int u, double v) d = (2, 5.5);

c = d;

assert(c.x == 2);
assert(d.u == 2);

(int, double) n = (x = 5, y = 2.5);
(int, double) o = (u = 2, v = 5.5);

n = o;
// cannot access members

assert(((int u, double v) a).u == 2)
assert(((int u, double v) c).u == 2)

Functions

Funcions return one value for one other. Multiple parameters and return values are achieved by using tuples. This nicely represents the mathematical background and does not come with syntax overhead or runtime cost. When a function is called, the return value is allocated on the stack, then the parameters are pushed abowe it, and then the function is executed. The return keyword breaks the function execution.

Functions access the parameter with the in name and the returning value with the out name. The return something is actually a syntax candy to assign a value to the out and then break the execution. Also when in or out have members, they can be accessed directly. The lookup for the names sorts in and out to the end. Functions can be declared with the returning type, an id and the parameter type. They can be called by simply writing the value next them.

void one int {
	print in;
}

int two void {
	out = 0;
}

void three void {
	one two;
}

int simpleAdd(int a, int b) {
	return a + b;
}

(int, int) semiAdd(int a, int b, int c, int d) {
	return (simpleAdd(a, b), simpleAdd(c, d));
}

int totalAdd(int, int, int, int) {
	return simpleAdd semiAdd in;
}

Contracts

Function contract are used to check pre and post conditions on the parameters and returned values. The pre block is executed when the parapeters were pushed into the stack and only sees the in value. The post block when the function returned and only sees the out value. Wether they get compiled into the binary should depend on compilers settings. They should only be used for debugging purposes.

double combine(double x, double y) pre {
	assert(x < 100);
	assert(y < x);

} body {
	return sqrt(x - y);

} post {
	assert(out > 0);
	assert(out < 10);
}