The Cute Programming Language
main page: zagura.oneA multipurpose language aimed at simplicity (work very in progress)
-
Source
Table of Contents
Intro to Syntax
In Cute, instead of snake_case, kebab-case is used. Also, while the syntax is meant to make it look that way, Cute is NOT whitespace-sensitive
List of Reserved Keywords
my
, our
, has
, impl
,
and
, or
, not
, use
,
if
, elif
, else
, match
,
is
, mut
, const
, for
,
in
, extern
Also there's yes
& no
, but they're values & not just tokens
Operators
Binary Operators
+ - * / % and or
+
also concatenates strings or arrays, and also combines arrays with items
and
& or
are logical operators (they short-cirquit)
Unary Operators
- not
Comparison Operators
> < >= <= = /=
Operator precedence
- All unary operators
* / %
+ -
< > = >= <= /=
and or
The operators that can be overloaded are:
+ - * / % = not
If the =
is overloaded, /=
can be used to get the inverse result
Literals
By default, integers are written in base 10 (56
, 42
),
but can be written in any base less than 36,
by prepending them by the base number & a colon, like so: 16:00ff88
, 8:1244
, 2:010111010
Floats are written exactly like ints, but with a point somewhere in the number. Int literals are automatically converted into floats if a float is needed instead
Booleans are written as either yes
or no
Strings are written using single quotes ('
)
with some typical character escapes: \\, \', \n, \t, \0,
and unicode character escapes: \u1234
Example: 'Hello World!\n'
Arrays are written as [a, b, c, d, e]
Ranges are written as [a..b]
For Loops
Cute has a for-loop construct, but it's actually just a sugared-up version of map and filter from other languages (so it's actually an expression, not a statement). This is what multiplying every element in the list by 2 would look like:
for x in my-list: x * 2
And this is what getting a list of all the prime numbers from another list would look like:
for x in my-list if x >- is-prime: x
Lambdas
To write a lambda, prefix an expression with a comma-separated list of param names, between pipes:
|x, y| x + y * 2
Function Invocations
Functions are invoked like in most languages:
my-function(a, b, c)
,
but there's also a pipe-first syntax for chaining function calls:
a >- my-function(b, c)
.
To put any value after the >-
, use parentheses, like so:
a >- (|x| x * 2)
Definitions
You can define constants, functions, types & typeclasses.
Any definition starts with either my
(for private) or our
(for public)
- constant:
-
our some-name: SomeType = 69
- function:
-
our some-name(p0: Int, p1: Fpt): SomeType = 69
- type:
-
our :Maybe T = Yes(T) No
- typeclass:
-
our :: Ord T = has cmp(a: T, b: T): Ordering
The types of constants can be omitted thanks to type inference
Types
These are the builtin types:
- signed:
-
Int
,Int32
,Int16
,Int8
- unsigned:
-
Nat
,Nat32
,Nat16
,Nat8
- float:
-
Fpt
,Fpt32
- boolean:
-
Bool
- string:
-
Str
- closure:
-
|Int| Int
|Int, Int| Int
|x: Int, y: Int| Int
- array:
-
[Int]
- tuple:
-
(Int, Int)
(x: Int, y: Int)
()
- params:
-
Maybe Int
Map[Str, Int]
List Maybe (Str, Int)
Typeclasses
Typeclasses can be used in function definitions to require certain functions for the given types to be present when the defined function is invoked.
This is really good for writing generic functions, for example to operate on any types that constitute a map, this would be the typeclass:
our :: Map K, V, M = has get(self: M, key: K): Maybe V has set(self: M, key: K, value: V): ()
And this would be a generic function using the typeclass (Map[M, K, V]
):
our get-or[K, V, M]( self: M, key: K, default: || V, ): V :: Map[M, K, V] = self >- get(key) >- or-else(default)
Comments
Comments can't be just written anywhere, they must be put either before a field/function/type... declaration, to document it, or before an expression to form a commented expression, to explain the code
btw, insert comment here;
btw, insert comment here