Designing the Aquamarine Programming Language - Part I

Writing a programming language have always been quite a fascinating thing for me. From drafting the syntax to implement the code translator (either a compiler or an interpreter) to writing a "standard library", every part of the development of a programming language is an interesting journey into interacting with your computer, as you are indeed "fighting your way" to a new method communicating with your computer.

Lexical Synopsis

I have brainstormed quite a lot of syntax for my programming language (and actually quite verbose 😅). 

 Variables are declared with the let keyword, as expected. Everything is immutable by default in Aquamarine, so to make a variable mutable, the keyword mutable is to be added. For example:

let a oftype string = "Hello World!";
mutable let b oftype int32 = 0; 

This also means that Aquamarine is a statically-typed programming language, where the type of a certain variable is declared using the oftype keyword.

A programming language is probably incomplete without iteration structures. As such, Aquamarine has support for for and while loops. There are actually two types of for-loops, one for "iterative indexes" and one for "for each element in collection", if you will.

for (a oftype int16 = 1; i < 10; i++) {
}
foreach (element oftype int32 in list) {
}

While loops are of the following syntax:

while (output.peek().is_some()) {
    output.next();
}

Functions are defined using the function keyword (surprise, surprise) and they take zero or more parameters. The params keyword signifies the beginning of a parameter list, and returns specify the return type of the function. There is also a keyword called yeets (definitely not inspired from the yeet thing in Rust 😂) that specifies the errors that the function may yeet.

function increment
  params (a oftype int16)
  returns int16
  yeets ArithmeticOverflowError {
  a += 1;
  a
}

Similar to Rust, the last line of a function signifies the return value. The function block is typically bounded with curly braces.

As you may infer from the above examples, statements in the Aquamarine programming language are to end with a semicolon.

Keywords

There are quite some keywords that have appeared in the above examples, indeed:

for
foreach
function
in
let
mutable
oftype
params
returns
while
yeets

All of these are so-called strict keywords, where they are not to be used as identifiers in any circumstances. Perhaps I will add support for "raw identifiers", for lifting this limitation to a certain extent. The keyword list will be updated as more lexical structures are documented in the blogs. 😉

Primitive Data Types

There are some primitive data types in the Aquamarine programming language. You may have seen some above as aforementioned, but now, here is the complete list of primitive data types (to be updated, perhaps? 🤔):
bool
char
int8
int16
int32
int64
nint
nuint
uint8
uint16
uint32
uint64
string

nint and nuint are signed and unsigned integers of native width. That corresponds to an int32 or uint32 on a 32-bit system, or int64 and uint64 on 64-bit systems, so on and so forth.


I guess that is it for now... quite a mouthful to include for the first blog of the series. 😅 Expect some more posts on the design of the Aquamarine programming language, before the actual implementation of the code translator series of blogs. See you all in the next one!

Comments

Popular posts from this blog

Building RustLand - A Professional IDE for Rust I