The Atlas77 Programming Language
by Gipson62
This version of the documentation is currently only experimental and thoughts I gathered while developing the language. It may not reflect the current state of the language.
The documentation as a whole will be available offline in the compiler itself in future updates.
Introduction
Welcome to The Atlas77 Programming Language, an experimental book about the Atlas77 programming language. Experimental because I'm trying to gather and lay down my thoughts about the language as I develop it to normalize the language in itself. It could be compared to how C++ has its own version (C++11, C++14, C++17, C++20, etc.) with each having thousands of page of documentation to formalize the language.
Atlas77 is a statically typed, compiled programming language that I do in my free time. I hope to be able to use it for future projects. Don't expect it to be production-ready anytime soon.
Goals
- Having a
core/graphics
module that links to Vulkan/OpenGL/DirectX. - Having a
core/sdl
module that links to SDL. - Bootstrapping the compiler.
- Having a
core/ffi
module that allows interfacing with C libraries. - Having a
core/ffi
module that allows interfacing with Rust libraries. - Making a game with it.
- Linking to blue_engine
- It should work 😁
NB: This is a work in progress document. The syntax is subject to change.
Current Syntax of Atlas77
1. Introduction
Atlas77 is a simple, easy-to-use, and powerful programming language. It is designed to be easy to learn and use, while still being powerful enough to handle complex tasks. This document describes the syntax of Atlas77, including the rules for writing code in the language (WIP).
2. Hello, World!
Here is a simple "Hello, World!" program written in Atlas77:
import "std/io"
func main() -> int64 {
print("Hello, World!")
}
Do know that strings are not implemented yet, so this is just an example of how it will look like
Save this code to a .atlas
file, then run it directly with atlas run <FILE_PATH>
3. Comments
Comments in Atlas77 are similar to comments in other programming languages. There are two types of comments: single-line comments and multi-line comments.
3.1. Single-line Comments
Single-line comments start with //
and continue until the end of the line. For example:
// This is a single-line comment
let x: i64 = 5; // This is also a single-line comment
3.2. Multi-line Comments
Multi-line comments start with /*
and end with */
. For example:
NB: Multi-line comments aren't supported yet (you'll see a lot of WIPs in this document)
/*
This is a multi-line comment.
/*
NOTE: Multi-line comments can be nested.
*/
It can span multiple lines.
*/
Comments are parsed as tokens by the compiler, to allow future documentation features.
4. Variables
Variables in Atlas77 are either mutable or immutable. The design follows in some sense TypeScript/JavaScript, with the
const
& let
keywords. Variables can be declared using the let
keyword, which creates a mutable variable, or the
const
keyword, which creates an immutable variable.
import "std/io"
func main() -> int64 {
let x: i64 = 5;
x = 10;
print(x); // Output: 10
const y: i64 = 5;
y = 10; // Error: Cannot assign to a constant variable
}
5. Data Types
Atlas77 has several built-in data types, including integers, floating-point numbers, booleans, strings, and arrays. The following table lists the built-in data types in Atlas77:
Data Type | Description | State |
---|---|---|
i8 | 8-bit signed integer | 💤 |
i16 | 16-bit signed integer | 💤 |
i32 | 32-bit signed integer | 💤 |
i64 | 64-bit signed integer | ✅ |
isize | Platform-dependent signed integer | 💤 |
u8 | 8-bit unsigned integer | 💤 |
u16 | 16-bit unsigned integer | 💤 |
u32 | 32-bit unsigned integer | 💤 |
u64 | 64-bit unsigned integer | ✅ |
usize | Platform-dependent unsigned integer | 💤 |
f32 | 32-bit floating-point number | 💤 |
f64 | 64-bit floating-point number | ✅ |
bool | Boolean value (true or false ) | ✅ |
char | Unicode character | 💭 |
str | String | 💭 |
array | Array (syntax: [YourType] ) | 💭 |
Note: The
str
andarray
types will be mutable and resizable. More powerful types for both Strings and Arrays will be implemented in the future (e.g.,Vec<YourType>
for arrays &String
).
NB: The
char
type is not implemented yet, but it will be a 32-bit Unicode character.
NB 2: Since this is a VM-based language, all numeric types smaller than 64 bits (e.g., u8, u16, u32) are internally represented as 64-bit values for simplicity and consistency. However, they will behave as their original types, respecting their size and overflow semantics. In the future, packed types may be introduced to optimize memory usage for arrays (e.g.,
[u8]
could be represented as[u8x8]
,[u16]
as[u16x4]
, etc.). At present, the minimum memory size for numeric types is 8 bytes.
6. Functions
Functions in Atlas77 are defined using the func
keyword, followed by the function name, parameters, return type, and
body. The return type of a function is specified after the ->
symbol. For example:
import "std/io"
func add(x: int64, y: int64) -> int64{
return x + y;
}
func main() -> int64 {
let result: int64 = add(5, 10);
print(result); // Output: 15
}
7. Control Structures
Atlas77 supports several control structures, including if
statements, match
expression, while
loops, and for
loops. The syntax for these control structures is similar to other programming languages. For example:
Control Structure | Description | State |
---|---|---|
if statement | Conditional statement | ✅ |
match expression | Pattern matching expression | 💤 |
while loop | Loop with a condition | ✅ |
for loop | Loop over a range or collection | 💤 |
Note: Nested if-else (i.e.
if {} else if {} else {}
) isn't supported yet.
import "std/io"
func main() -> int64 {
let x: int64 = 5;
if x > 0 {
print("x is positive");
} else {
if x < 0 {
print("x is negative");
} else {
print("x is zero");
}
}
let i: i64 = 0;
while i < 5 {
print(i);
i += 1;
}
}
8. The standard library
Atlas77 comes with a relatively small standard library, which includes functions & types for input/output, file
handling, string & list manipulation, time & math functions. The standard library is imported using the import
keyword, followed by the library name. For example:
import "std/io"
func main() {
print("Hello, World!");
}
As of writing this document, the following standard libraries are available:
std/io
: Input/output functionsprint_int(i: i64)
: Print an integer to the consoleprint_float(f: f64)
: Print a floating-point number to the consoleprint_uint(u: u64)
: Print an unsigned integer to the consoleprint_bool(b: bool)
: Print a boolean value to the console
Yes it is very limited, but tbh
str
,array
& structs are still not implemented, so it's a bit hard to implement more complex functions.
9 Arrays
10. Enums
WIP
Example:
public enum Color {
Red = 1,
Yellow,
Green = 3,
Purple,
Blue = 5,
}
11. Class & Structs
WIP
Current state of std/fs
:
extern read_dir(path: str) -> [str]
extern read_file(path: str) -> str
extern write_file(path: str, content: str)
extern remove_file(path: str)
extern file_exists(path: str) -> bool
public class File {
private:
flag: i64;
content: str;
path: str;
public:
func create() -> File {
return new File {
flag: 0,
content: None,
path: "",
};
}
func read(path: str) -> File {
let file: Self = File::create();
file.path = path;
file.content = Some(read_file(path));
return file;
}
func write(&self, content: str) {
write_file(self.path, content);
}
func remove(&self) {
remove_file(self.path);
}
func exists(&self) -> bool {
return file_exists(self.path);
}
func read_dir(path: str) -> [str] {
return read_dir(path);
}
func read_file(path: str) -> str {
return read_file(path);
}
}
12. Generics
As of now generics are only implemented for external functions.
Example:
extern generic_func<T>(val: T) -> T
extern other_generic_func<T, G>(t: [T], g: [G]) -> [T]
[!NOTE] You can't return a generic that is not used in any parameter. Type inference is not implemented yet.
WIP
13. Traits
The name is still to be decided
Installation
Prerequisites
- Rust Compiler
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
NB: This is only for Unix-based systems (or WSL for Windows). For Windows, you can use Scoop
scoop install main/rust
Or directly from their website: Rust
Installation
Once Rust is installed, you can install Atlas77 using Cargo.
- Install it from Cargo
cargo install atlas_77
- Use it as a CLI
atlas_77 --help
- Enjoy!
Or you can clone the repository and build it yourself.
- Clone the repository
git clone https://github.com/atlas77-lang/atlas77.git && cd atlas77
- Build it
cargo build --release
- Use it as a CLI
./target/release/atlas_77 --help
Programming a Guessing Game
Setting up
First, create a new atlas77 file named guessing_game.atlas
Standard Library
note
All the standard library is a work in progress. Most of the modules aren't implement or finished yet. The documentation is here to give an idea of what the standard library will look like.
Module | Description |
---|---|
std/io | Input/output functions |
std/fs | File handling functions |
std/string | String manipulation functions |
std/list | List manipulation functions |
std/time | Time functions |
std/math | Math functions |
std/vec | Vector functions |
You can see what is implemented with the checkboxes below.
std/io
-
print<T>(val: T) -> unit
: Print a string to the standard output. -
println<T>(val: T) -> unit
: Print a string to the standard output followed by a newline. -
input() -> str
: Read a line from the standard input.
std/fs
-
File
: A file type that can be used to read and write files.
NB: The
File
type is not implemented yet.
-
open(filename: str, mode: str) -> File
: Open a file in the specified mode. -
read(file: File) -> str
: Read the content of a file. -
write(file: File, content: str) -> unit
: Write content to a file. -
close(file: File) -> unit
: Close a file. -
exists(filename: str) -> bool
: Check if a file exists. -
remove(filename: str) -> unit
: Remove a file. -
rename(old: str, new: str) -> unit
: Rename a file.
std/str
String
: A string type that can be used to manipulate strings.
NB: The
String
type is not implemented yet.
Implements
Indexable<char>
: A trait that defines theget
andset
methods.
NB: The
Indexable
trait is not implemented yet.
Methods
-
str_len(s: String) -> uint64
: Get the length of a string. -
concat(s1: String, s2: String) -> String
: Concatenate two strings. -
split(s: String, sep: str) -> List
: Split a string into a list of substrings. -
join(lst: List, sep: str) -> String
: Join a list of strings into a single string. -
replace(s: String, old: str, new: str) -> String
: Replace all occurrences of a substring in a string. -
to_upper(s: String) -> String
: Convert a string to uppercase. -
to_lower(s: String) -> String
: Convert a string to lowercase. -
trim(s: String) -> String
: Remove leading and trailing whitespace from a string. -
starts_with(s: String, prefix: str) -> bool
: Check if a string starts with a prefix. -
ends_with(s: String, suffix: str) -> bool
: Check if a string ends with a suffix. -
contains(s: String, sub: str) -> bool
: Check if a string contains a substring. -
find(s: String, sub: str) -> int64
: Find the index of the first occurrence of a substring in a string. -
rfind(s: String, sub: str) -> int64
: Find the index of the last occurrence of a substring in a string. -
slice(s: String, start: int64, end: int64) -> String
: Get a substring of a string.
Operators
-
+
: Concatenate two strings. -
[]
: Get a character from a string by index. -
[]=
: Set a character in a string by index.
std/list
-
len<T>(lst: [T]) -> uint64
: Get the length of a list. -
push<T>(lst: [T], val: T) -> unit
: Add an element to the end of a list. -
pop<T>(lst: [T]) -> T
: Remove and return the last element of a list. -
slice<T>(lst: [T], start: uint64, end: uint64) -> [T]
: Get a slice of a list. -
remove<T>(lst: [T], index: uint64) -> T
: Remove and return an element from a list by index.
std/vec
-
Vec<T>
: A vector is a dynamic array that can grow or shrink in size. It has a bunch of methods to manipulate the data.
Implements
-
Indexable<T>
: A trait that defines theget
andset
methods.
Methods
-
Vec(data: [T]) -> Vec<T>
: Create a new vector from a list. -
len() -> uint64
: Get the length of the vector. -
is_empty() -> bool
: Check if the vector is empty. -
push(val: T) -> unit
: Add an element to the end of the vector. -
pop() -> T
: Remove and return the last element of the vector. -
get(index: uint64) -> T
: Get an element from the vector by index. -
set(index: uint64, val: T) -> unit
: Set an element in the vector by index.
Operators
-
[]
: Get an element from the vector by index. -
[]=
: Set an element in the vector by index.
std/time
-
Time
: A time type that can be used to represent time. -
now() -> Time
: Get the current time. -
format(t: Time, fmt: str) -> str
: Format a time value as a string. -
sleep(ms: uint64) -> unit
: Sleep for the specified number of milliseconds. -
sleep_us(us: uint64) -> unit
: Sleep for the specified number of microseconds. -
sleep_ns(ns: uint64) -> unit
: Sleep for the specified number of nanoseconds. -
elapsed(start: Time, end: Time) -> uint64
: Calculate the elapsed time between two time values in milliseconds. -
elapsed_us(start: Time, end: Time) -> uint64
: Calculate the elapsed time between two time values in microseconds. -
elapsed_ns(start: Time, end: Time) -> uint64
: Calculate the elapsed time between two time values in nanoseconds. -
parse(s: str, fmt: str) -> Time
: Parse a string into a time value. -
add(t: Time, ms: uint64) -> Time
: Add milliseconds to a time value.
std/math
-
abs(x: int64) -> int64
: Compute the absolute value of a integer number. -
abs_f(x: float64) -> float64
: Compute the absolute value of a floating-point number. -
round(x: float64) -> int64
: Round a floating-point number to the nearest integer. -
random(min: int64, max: int64) -> int64
: Generate a random integer number in the range[min, max]
. -
pow(x: int64, y: int64) -> int64
: Computex
raised to the power ofy
. -
pow_f(x: float64, y: float64) -> float64
: Computex
raised to the power ofy
. -
min(x: int64, y: int64) -> int64
: Compute the minimum of two integer numbers. -
min_f(x: float64, y: float64) -> float64
: Compute the minimum of two floating-point numbers. -
max(x: int64, y: int64) -> int64
: Compute the maximum of two integer numbers. -
max_f(x: float64, y: float64) -> float64
: Compute the maximum of two floating-point numbers.