Cyrup that may trigger syntactic diabetes.
main:(stdio){
stdio.print("hello world")
}
All syntaxes are defined with only a few special characters, not even a keyword.
There are a few basic rules.
:
is used for all kinds of declaration.- expressions after the
:
means data. - every data has its own representation.
Example declarations below:
a:int=1
b:2
c:Int(1)
f:(d:int, e:int){
=> d + e
}
Using declared data is the same as the other computer languages we're used to.
a = b
assigns 2 to a variablec.equals(a)
: returns truef(a, b)
: returns a + b = 3
if
statement has been replaced with ?
.
It's not the ternary operator condition? x : y
. There is only one operand required after ?
, like condition? x
.
There is no else
or :
. We use ||
instead. Append "|| y" behind the preceding conditional expression. It'll reach there when the condition is false.
(a > b) ? {
diff = a - b
} || (a < b) ? {
diff = b - a
} || {
diff = 0
}
?
also provide a property to expand namespace.
Codes below will call the method
only if instance
is truthy.
instance?.method()
instance? {
.method()
}
Using this property, switch
statement can be expressed as:
key? {
== 'w'? => moveUp()
== 'a'? => moveLeft()
== 's'? => moveDown()
== 'd'? => moveRight()
}
while
, for
statements have been replaced with *
.
It may seem quite new, but *
still is a multiplication. Let's see some examples first.
3 * {
print("reapeat only 3 times")
}
Please regard the product {}
multiplied by 3
as a "statment copied and called exactly 3 times".
{print("reapeat only 3 times")}
{print("reapeat only 3 times")}
{print("reapeat only 3 times")}
This looks inefficient, but let the compilers find an optimal way to run this code.
We can iterate elements of an array by using distributive property of expressions.
elems:={1,2,3,4}
(e:elems) * {
print("%d in elems", e)
}
The product above will ditribute {}
to each elements of elems
.
{print("%d in elems", 1)}
{print("%d in elems", 2)}
{print("%d in elems", 3)}
{print("%d in elems", 4)}
By now, I believe you can get the sense of how the statements below would work.
true * {
print("hello world!")
}
(i:1~10) * {
print("number %d", i)
}
true * {}
repeats forever, likewhile
. (thinktrue
is equivalent to infinite)(i:1~10) * {}
iterates from 1 to 10, likefor(i = 0; i < 10; i++){}
.
(WIP below)
Type and Class are data, with a notion of Storage Class denoted by @
.
Here is the example of type & class declaration with Storage Class.
int@type:i32
Int@class:(
data:int
.equals:(value:int)bool{
=> (data==value)
}
)
Naming conventions will determine whether the field is accessible.
The class example above implicitly defined accessibility of c:Int
members:
c.data
: This is an error, as symbol not defined as.data
.cdata
: This is regarded as a new variable, notc
's member.c.equals(2)
: This is a valid access, like a public method.
In this way, data is capsulized without explicitly notating public
or private
.
Storage Classes are also used for designating the data lifetime and scope
globalString@data := "string at data segement"
localString@stack := "string at stack segment"
dynamicString@heap:= "string at heap segment"