README

This is the introduction to ApLang, a tool designed to help you excel in your AP Computer Science Principles class and score higher on your AP test.

The purpose of this guide is not to replace your teacher but to get you acquainted with ApLang and serve as a reference while you are programming. It assumes you have some very basic knowledge of programming but are still a beginner.

Back in the early days of personal computing, computers often came with a manual that was absolutely indispensable. It was difficult to accomplish much without that manual. Let this guide be your modern equivalent—your go-to resource for learning ApLang.

Some of ApLangs syntax is garbage. Sorry about that...I did not design it. It was designed lovingly by committee at Collage Board head quarters.

Standard Library Documentation

This book also contains the documentation for the standard library. Documentation explains how each standard library module's functions work.

About

ApLang was created using the programming language Rust. Rust was chosen primarily for its ability to "run anywhere" (thanks to LLVM <3) and its excellent package manager, Cargo. ApLang is an interpreted language, meaning it is executed without being compiled first, making it easy to use and accessible to as many people as possible.

Installation

This section will guide you through the process of setting up aplang.

Troubleshooting

If you encounter any issues during the installation process, here are a few troubleshooting tips:

  • If you have trouble installing Visual Studio Code, please refer to the official documentation

  • Command not found: If you see a "command not found" error when running cargo or aplang, ensure that your terminal’s PATH environment variable includes the directory where Cargo installs binaries. This is usually $HOME/.cargo/bin on Unix-like systems or %USERPROFILE%\.cargo\bin on Windows. You may need to add this directory to your PATH manually.

  • Rust or Cargo not installed: If Cargo is not installed, double-check that you followed the installation steps correctly. Make sure you have a stable internet connection and that you followed all prompts during installation.

  • Permissions issues: If you encounter permissions issues, try running the command with sudo (on Unix-like systems) or as an administrator (on Windows). However, be cautious with using sudo and only use it when necessary.

Install ApLang

With Cargo (All Platforms)

Step 1: Install Rust and Cargo

Before you can install aplang, you need to have Rust and Cargo installed on your computer. Cargo is the package manager and build system for the Rust programming language, and it comes bundled with Rust.

1.1 Install Rust and Cargo

  1. Visit the Rust installation page: Open your web browser and go to https://rustup.rs.

  2. Follow the installation instructions: The Rust installation page will automatically detect your operating system and provide you with detailed instructions on how to install Rust and Cargo. Follow the instructions provided for your specific operating system (Linux, macOS, or Windows).

  3. Complete the installation: The installer will guide you through the installation process. Make sure to follow all the steps, including any prompts to modify your system’s PATH environment variable. This will ensure that Cargo commands are available in your terminal or command prompt.

  4. Restart your terminal or command prompt: After installation, restart your terminal (Linux or macOS) or command prompt (Windows) to make sure the changes take effect.

1.2 Verify the Installation

To confirm that Rust and Cargo are installed correctly, open your terminal (Linux or macOS) or Command Prompt/PowerShell (Windows) and run:

cargo --version

If the installation was successful, this command will display the version of Cargo installed, such as cargo 1.65.0 (0e8d5a6 2022-09-27).

Step 2: Install the aplang Binary

Now that you have Cargo installed, you can install the aplang binary.

2.1 Install aplang Using Cargo

  1. Open your terminal or Command Prompt: Make sure your terminal (Linux/macOS) or Command Prompt/PowerShell (Windows) is open.

  2. Run the installation command: Type the following command and press Enter:

    cargo install aplang
    

    Cargo will fetch the aplang package from the online registry, compile it, and install it on your system. This process may take a few minutes, depending on your internet speed and system performance.

  3. Wait for the installation to complete: Cargo will display messages as it compiles and installs the binary. Once the process is complete, you should see a message indicating that aplang has been installed successfully.

Step 3: Verify the Installation of aplang

After installation, you should verify that aplang is correctly installed and can be used as a standalone program.

3.1 Check the Installation

  1. Run the aplang command: In your terminal or Command Prompt, type the following command and press Enter:

    aplang --version
    

    If installed correctly, this command will display the version of aplang that you installed, confirming that the installation was successful.

Step 4: Use aplang as a Standalone Program

Now that aplang is installed, you can use it as a standalone program.

4.1 Running aplang

To run aplang, simply type aplang followed by any arguments or options you want to use. For example:

aplang --help

This command will display the help information for aplang, showing you the available commands and options.

Troubleshooting

Configure Your Development Environment

To start working on aplang projects, it is recommended to use Visual Studio Code (VS Code). Git is not strictly required, but it is highly recommended for version control.

Step 1: Install GitHub Desktop and Git VCS

Install GitHub Desktop

  1. Download GitHub Desktop:

  2. Install GitHub Desktop:

    • Windows/macOS: Run the installer and follow the prompts to complete the installation.
    • Linux: See your individual distributions documentation for installation information.
    • Git version control should automatically be installed by GitHub Desktop.

Step 2: Install Visual Studio Code (VS Code)

Install VS Code on Windows

  1. Visit the VS Code download page: VS Code Download.

  2. Download the installer for Windows: Click on the "Windows" download link.

  3. Run the installer: Double-click the installer file (VSCodeSetup-x64-<version>.exe).

  4. **Follow the on-screen installation prompts.

    • Make sure to check "Add to PATH"
    • Also check "Register code as an editor for supported file types"
    • OPTIONAL: "Add to context menu"

Install VS Code on Linux

  1. Install VSCode with your distro's package manager

Install VS Code on macOS

  1. Visit the VS Code download page: VS Code Download.

  2. Download the installer for macOS: Click on the "macOS" download link to download a .zip file.

  3. Install VS Code:

    • Open the .zip file to extract the contents.
    • Drag the extracted Visual Studio Code.app file to your "Applications" folder.

Step 3: Set Up a Project Directory

Create a GitHub Repository with GitHub Desktop

  1. Open GitHub Desktop: Launch the GitHub Desktop application.

  2. Create a New Repository:

    • Click on "File" > "New Repository."
    • Fill in the repository name and choose the local path where you want to create the repository.
      • We recommend using the default path.
    • Click "Create Repository."

Open the Project Directory in VS Code

Using GitHub Desktop:

  • In GitHub Desktop, make sure your repository is selected.
  • Click on the "Repository" menu, then select "Open in Visual Studio Code." This will open the repository in VS Code.

Alternative Method:

  • If the "Open in Visual Studio Code" button is not available, click on the "Show in Explorer" (Windows) or "Show in Finder" (macOS) button to open the repository folder in your file explorer.
  • Right-click the folder and select "Open with Code" (if this option is available) or open VS Code, click on "File" > "Open Folder..." and navigate to your repository directory.

Create the main.ap File

  1. Open VS Code: Launch Visual Studio Code.

  2. Create a New File: Click on "File" > "New File" or press Ctrl + N (Cmd + N on macOS).

  3. Add Code: Enter the following code into your file

    DISPLAY("Hello World!")
    
  4. Save the File: Click on "File" > "Save As..." or press Ctrl + S (Cmd + S on macOS). Name the file main.ap and save it in your project directory.

  5. (Recommended): Also Enable autosave from from the "File" context menu.

Step 4: Install the VSCode Extension

  1. Find the Extension in the Visual Studio Marketplace: It is available here

    • Alternatively, search for ApLang in the "Extensions" tab in Visual Studio Code
  2. Install the Extension: Press the install Install button.

Step 5: Run the main.ap File with the aplang Binary

  1. Open Integrated Terminal in VS Code:

    • Go to "View" > "Terminal" or press Ctrl + `.
  2. Run the File: In the terminal, navigate to the directory containing main.ap and run the file using the aplang binary. You should see the output Hello World! in your console.

Conclusion

Congratulations! You have successfully setup an aplang project. You can now begin to develop more complex programs using aplang. You are ready to begin following along with the rest of this book.

Troubleshooting

Basics

Congratulations! You have successfully installed ApLang and configured your development environment! If you haven't done that yet, please see the Installation section.

Introducing the .ap file! For legal reasons, .ap doesn't stand for Advanced Placement; it stands for something else... uh... Apple Pie! Yep!

Disclaimer: The term ".ap" is a proprietary file extension of ApLang, hereinafter referred to as "Apple Pie." Any resemblance to actual file extensions, past or present, is purely coincidental. By using the ".ap" file extension, you agree to bake, metaphorically or otherwise, a delicious apple pie, and hereby release ApLang and all affiliates from any claims, demands, or disputes arising from or in connection with your pie-making activities. All rights reserved. Terms and conditions apply. Batteries not included. Consult your local baker for details.

The main.ap file is where you place your code. If you have not created it yet please do so now. It does not have to be called main.ap but that is the conventional name. It must end with a .ap file extension. When you are ready to run your code, you will call the interpreter that you just installed. Run the following command in your console to execute your code:

aplang main.ap

aplang will then execute your file. Watch your console for any output your code may produce.

Hello World

Welcome to your first ApLang program! We'll start with the classic "Hello, World!" example, a simple program that displays text on the screen. This program introduces the DISPLAY procedure, which you can use to print text.

// This is a comment.
// Comments are ignored by the interpreter.

// Display text on the console
DISPLAY("Hello, World!")
//      ^^^^^^^^^^^^^^^^
//          String Literal

Let's break this down:

  • DISPLAY: This procedure (sometimes called a function) outputs the text you provide to the console.
  • "Hello, World!": The text inside the quotation marks is called a "String Literal." A string is a sequence of characters. In this case, "Hello, World!" is the string we want to display.

Comments

Comments are an essential part of programming. They help you and others understand your code by providing explanations or notes. In ApLang, comments are not executed as part of your program; They are completely ignored by the interpreter.

There are two types of comments in ApLang:

Line Comments

Line comments start with // and continue until the end of the line.

// This is a line comment. It explains the code below.
DISPLAY("Hello, World!")

Block Comments

Block comments start with /* and end with */. Everything between these markers is ignored by the interpreter.

/* 
This is a block comment.
It can span multiple lines.
*/
DISPLAY("Hello, World!")

Commenting Guidelines

Writing good comments is an important skill for making your code more readable and maintainable. Here are some guidelines for writing effective comments:

  • DO: Use comments to explain complex or non-obvious sections of code.
  • DO: Use comments to provide context on why certain decisions were made.
  • DO: Document design decisions, especially any trade-offs or compromises.
  • DON'T: Use comments as a substitute for clear and descriptive variable or function names.
  • DON'T: Write comments that simply restate what the code does; focus on the "why."

Example of Effective Comments

Let's look at an example of how to use comments effectively:

// Poor Commenting:
// Increment the margin by 2
margin <- margin + 2

// Better Commenting:
// Increase margin to account for the 2-pixel border of the render box
margin <- margin + 2

// Best Comment:
// Account for 2-px border of render box
margin <- margin + 2

In the first example, the comment just restates what the code does, which is redundant. The improved version explains why the margin is increased, providing valuable context.

Types

ApLang, like many programming languages, uses various types to represent different kinds of data. Understanding these types is fundamental to writing effective programs.

Values

In ApLang, a value is a piece of data that has a type. The main types of values you will encounter are:

  • Number: Represents floating-point numbers.
  • String: Represents text.
  • Boolean: Represents a truth value, either TRUE or FALSE.
  • List: Represents a series of values.

Numbers

Numbers in ApLang are similar to numbers in mathematics. They can be whole numbers (integers) or have a decimal point (floating-point numbers). In ApLang, all numbers are represented as f64, which means they are 64-bit floating-point numbers. This allows for a wide range of values, both large and small, with high precision.

DISPLAY(42)      // This is a number.
DISPLAY(3.1415)  // This is also a number, with a decimal point.

Strings

A string is a sequence of characters, used to represent text. Strings are created by placing text inside quotation marks (").

DISPLAY("Hello, ApLang!")  // This is a string.

Strings can contain letters, numbers, symbols, and spaces. They are very useful for storing and manipulating text data.

Example: Creating and Displaying Strings

// Create a string variable
my_text <- "This is a string."

// Display the string
DISPLAY(my_text)

In the example above, my_text is a variable that stores the string "This is a string.". The DISPLAY procedure outputs the value of my_text to the console.

Booleans

A Boolean is a type that can have one of two values: TRUE or FALSE. Booleans are often used in conditional statements to control the flow of a program based on certain conditions.

DISPLAY(TRUE)   // This is a boolean value.
DISPLAY(FALSE)  // This is another boolean value.

Booleans are essential for making decisions in your programs. For example, you can use them to check if a condition is met and then execute different code based on the result.

Example: Using Booleans in Conditional Statements

is_ready <- TRUE

// Check if is_ready is TRUE
IF (is_ready) {
    DISPLAY("Ready to go!")
} ELSE {
    DISPLAY("Not ready yet.")
}

In this example, the program checks the value of is_ready. If it is TRUE, it displays "Ready to go!" Otherwise, it displays "Not ready yet."

Lists

A list is a collection of values. Lists in ApLang are versatile and can hold multiple values of different types, but they are unique in that they are the only type passed by reference rather than by value. This means when you pass a list to a function or assign it to another variable, you are referencing the same list in memory, not copying it.

Creating a List

Lists are created using square brackets ([]) with values separated by commas:

my_list <- ["a", "b", "c", "d"]
DISPLAY(my_list)

This list contains four string elements: "a", "b", "c", and "d".

Understanding Lists as References

Since lists are passed by reference, modifying a list in one place affects all references to that list.

numbers <- [1, 2, 3]
more_numbers <- numbers

// Modify the list through more_numbers
APPEND(more_numbers, 4)

DISPLAY(numbers)  // Output: [1, 2, 3, 4]
DISPLAY(more_numbers)  // Output: [1, 2, 3, 4]

In this example, numbers and more_numbers both refer to the same list in memory. When we append 4 to more_numbers, numbers is also affected because they reference the same data.

Example: Using Lists

// Create a list of numbers
my_numbers <- [10, 20, 30, 40]

// Accessing elements
DISPLAY(my_numbers[1])  // Output: 10
DISPLAY(my_numbers[3])  // Output: 30

// Modifying elements
my_numbers[2] <- 25
DISPLAY(my_numbers)  // Output: [10, 25, 30, 40]

In the example above, my_numbers is a list of numbers. We can access elements using an index (starting at 1) and modify elements by assigning a new value to a specific index.

Expressions

Expressions are a core concept in ApLang. They represent values or computations that produce values. In ApLang, you can use expressions to perform arithmetic operations, manipulate strings and lists, call functions, and evaluate logical conditions. This chapter will introduce you to the different types of expressions available in ApLang and how to use them effectively.

Arithmetic Expressions

Arithmetic expressions in ApLang allow you to perform basic mathematical operations. ApLang supports the following arithmetic operators:

  • + (addition)
  • - (subtraction)
  • * (multiplication)
  • / (division)
  • MOD (modulo)

Example: Arithmetic Operations

// Addition
sum <- 5 + 3
DISPLAY(sum)  // Output: 8

// Subtraction
difference <- 10 - 4
DISPLAY(difference)  // Output: 6

// Multiplication
product <- 7 * 2
DISPLAY(product)  // Output: 14

// Division
quotient <- 8 / 2
DISPLAY(quotient)  // Output: 4

// Modulo (remainder of division)
remainder <- 9 MOD 4
DISPLAY(remainder)  // Output: 1

In these examples, each expression calculates a result using arithmetic operators and assigns the result to a variable.

String and List Concatenation

ApLang supports string and list concatenation using the + operator. Concatenation combines two strings or two lists into one.

Example: String Concatenation

greeting <- "Hello, "
name <- "World!"
full_greeting <- greeting + name
DISPLAY(full_greeting)  // Output: "Hello, World!"

Example: List Concatenation

list1 <- [1, 2, 3]
list2 <- [4, 5, 6]
combined_list <- list1 + list2
DISPLAY(combined_list)  // Output: [1, 2, 3, 4, 5, 6]

These examples show how the + operator can be used to concatenate strings and lists, creating a new string or list that combines the contents of both operands.

Function Calls as Expressions

Function calls in ApLang are expressions that evaluate to the return value of the function. You can use function calls wherever expressions are allowed.

Example: Using Function Calls

PROCEDURE square(x) {
    RETURN x * x
}

result <- square(4)
DISPLAY(result)  // Output: 16

In this example, square(4) is an expression that calls the square function with the argument 4 and returns the result.

Logical Expressions

Logical expressions evaluate to boolean values (TRUE or FALSE) and are used to make decisions in your programs. ApLang supports several logical operators:

  • NOT (logical negation)
  • AND (logical conjunction)
  • OR (logical disjunction)

Example: Logical Operations

a <- TRUE
b <- FALSE

// Logical NOT
not_a <- NOT a
DISPLAY(not_a)  // Output: FALSE

// Logical AND
and_result <- a AND b
DISPLAY(and_result)  // Output: FALSE

// Logical OR
or_result <- a OR b
DISPLAY(or_result)  // Output: TRUE

Logical expressions are crucial for controlling the flow of your program using conditional statements.

Comparison Expressions

Comparison expressions are used to compare values and produce boolean results. ApLang supports the following comparison operators:

  • == (equal to)
  • != (not equal to)
  • > (greater than)
  • < (less than)
  • >= (greater than or equal to)
  • <= (less than or equal to)

Example: Comparison Operations

x <- 5
y <- 10

DISPLAY(x == y)   // Output: FALSE
DISPLAY(x != y)   // Output: TRUE
DISPLAY(x > y)    // Output: FALSE
DISPLAY(x < y)    // Output: TRUE
DISPLAY(x >= y)   // Output: FALSE
DISPLAY(x <= y)   // Output: TRUE

These expressions evaluate to TRUE or FALSE based on the comparison of x and y.

Combined Expressions

Expressions in ApLang can be combined to perform more complex calculations or evaluations. By using parentheses () to group expressions, you can control the order of operations.

Example: Combining Expressions

a <- 2
b <- 3
c <- 4

result <- (a + b) * c  // Parentheses change the order of operations
DISPLAY(result)  // Output: 20

In this example, the expression (a + b) is evaluated first, followed by multiplication by c, resulting in 20.

Conclusion

Expressions are a powerful tool in ApLang, enabling you to perform a wide range of operations and calculations. By mastering arithmetic, string, list, logical, and comparison expressions, you can create more dynamic and efficient programs. Remember to use parentheses to control the order of operations to ensure your expressions evaluate as intended.

Variables

Variables in ApLang are used to store and manage data. By assigning values to variables, you can reference and manipulate them throughout your program. This chapter will introduce you to the basics of variables, including how to create them, assign values, and use them effectively.

Creating Variables

To create a variable in ApLang, you use the assignment operator <-. This operator assigns the value on the right-hand side to the variable on the left-hand side.

// Create a variable named 'x' and assign it the value 10
x <- 10
DISPLAY(x)  // Output: 10

In the example above, the variable x is created and assigned the value 10. You can think of x as a label that points to the value 10.

Variable Naming

Variable names in ApLang can contain letters, digits, and underscores (_). However, they must start with a letter. Good variable names are descriptive and make your code easier to understand.

// Create a variable with a descriptive name
apples_in_basket <- 5
DISPLAY(apples_in_basket)  // Output: 5

Reassigning Variables

Variables in ApLang are mutable, meaning their values can be changed after they are created. To change the value of a variable, simply use the assignment operator <- again with a new value.

// Create a variable and assign a value
count <- 1
DISPLAY(count)  // Output: 1

// Reassign the variable with a new value
count <- 2
DISPLAY(count)  // Output: 2

In this example, the variable count is initially set to 1 and then changed to 2.

Using Variables in Expressions

Variables can be used in expressions just like literal values. You can perform operations with variables and assign the result to another variable or even back to the same variable.

// Create variables
a <- 5
b <- 3

// Use variables in expressions
sum <- a + b
DISPLAY(sum)  // Output: 8

// Update variable value using itself
a <- a + 1
DISPLAY(a)  // Output: 6

Here, sum is assigned the result of adding a and b. The variable a is then updated by adding 1 to its current value.

Variable Scope

The scope of a variable is the region of your program where the variable is accessible. In ApLang, variables have a local scope, which means that a variable defined in a function (or procedure in ApLang's case) is accessible only within that function. Contrary to many programming languages, ApLang does not have global variables.

x <- 10
y <- 5
z <- 4 // 'z' defined here is NOT accessible in max()

PRODECURE max(x, y) {
    IF (x >= y) {
	    a <- x // 'a'  is not accessible outside of max()
    } ELSE {
	    a <- y // 'a' is also not accessible outside of max()
    }
    // Trying to access 'z' here would result in an error
    // DISPLAY(z) // Error: 'z' is not defined
    
    RETURN a
}

// Trying to access 'a' here would result in an error
// DISPLAY(a) // Error: 'a' is not defined

In this example, the variable a is defined inside the PROCEDURE block and cannot be accessed outside of it. In the same way, z is defined outside of the PROCEDURE block and cannot be accessed inside of it.

Conclusion

Variables are fundamental to programming in ApLang. They allow you to store, modify, and use data dynamically. By understanding how to create variables, reassign values, and use variables within their scope, you will be able to write more flexible and powerful programs.

Control Flow

Control flow refers to the mechanisms that determine the order in which statements and instructions are executed in a program. In ApLang, control flow structures allow you to make decisions and repeat tasks based on specific conditions, making your code more dynamic and responsive to different situations.

Think of control flow like navigating a city using a map. Just as you might choose different routes based on traffic, weather, or your destination, control flow in programming lets your code choose different paths based on the data it receives and the conditions it encounters.

Control flow includes:

  • Making Decisions: Similar to deciding whether to take an umbrella based on the weather forecast, your program can execute certain blocks of code only when specific conditions are met.
  • Repeating Tasks: Just as you might wash each dish in a sink full of dirty dishes until they’re all clean, loops in programming allow your program to repeat operations multiple times without having to write the same code repeatedly.
  • Branching Execution: This is like choosing a detour if a road is blocked. Your program can direct its execution to different parts of the code based on logical conditions, ensuring it behaves correctly under various circumstances.

In this chapter, we will explore the various control flow structures available in ApLang, including conditionals and loops, which allow you to guide the execution path of your code effectively, just like making decisions and finding the best route on a journey.

IF Statements

IF statements are a fundamental control flow structure in ApLang. They allow your program to make decisions and execute specific blocks of code based on certain conditions. Using IF, ELSE IF, and ELSE, you can create flexible programs that respond dynamically to different inputs and scenarios.

IF

The IF statement checks a condition and executes a block of code if the condition evaluates to TRUE. It’s the most basic form of decision-making in your program.

Syntax

IF (condition) {
    // Code to execute if the condition is TRUE
}

Example: Basic IF Statement

x <- 10

IF (x > 5) {
    DISPLAY("x is greater than 5")
}
// Output: "x is greater than 5"

In this example, the condition (x > 5) is TRUE, so the code inside the IF block is executed, displaying "x is greater than 5."

ELSE

The ELSE statement is used to execute a block of code if the condition in the preceding IF statement evaluates to FALSE. It provides an alternative path of execution.

Syntax

IF (condition) {
    // Code to execute if the condition is TRUE
} ELSE {
    // Code to execute if the condition is FALSE
}

Example: IF-ELSE Statement

x <- 3

IF (x > 5) {
    DISPLAY("x is greater than 5")
} ELSE {
    DISPLAY("x is not greater than 5")
}
// Output: "x is not greater than 5"

Here, the condition (x > 5) is FALSE, so the code inside the ELSE block is executed, displaying "x is not greater than 5."

ELSE IF

The ELSE IF statement allows you to check multiple conditions sequentially. If the initial IF condition is FALSE, the program checks the ELSE IF condition. You can chain multiple ELSE IF statements together to handle various scenarios.

Syntax

IF (condition1) {
    // Code to execute if condition1 is TRUE
} ELSE IF (condition2) {
    // Code to execute if condition1 is FALSE and condition2 is TRUE
} ELSE {
    // Code to execute if none of the above conditions are TRUE
}

Example: IF-ELSE IF-ELSE Statement

x <- 5

IF (x > 5) {
    DISPLAY("x is greater than 5")
} ELSE IF (x == 5) {
    DISPLAY("x is equal to 5")
} ELSE {
    DISPLAY("x is less than 5")
}
// Output: "x is equal to 5"

In this example, the program first checks if x is greater than 5. Since this is FALSE, it moves to the ELSE IF condition (x == 5), which is TRUE. The code inside the ELSE IF block is executed, displaying "x is equal to 5."

Nesting IF Statements

You can nest IF statements within each other to create more complex decision-making structures. This is useful for checking multiple conditions in a hierarchical manner.

Example: Nested IF Statements

x <- 10
y <- 20

IF (x > 5) {
    IF (y > 15) {
        DISPLAY("x is greater than 5 and y is greater than 15")
    } ELSE {
        DISPLAY("x is greater than 5 but y is not greater than 15")
    }
} ELSE {
    DISPLAY("x is not greater than 5")
}
// Output: "x is greater than 5 and y is greater than 15"

In this example, the first IF statement checks if x is greater than 5. Since it is TRUE, the program moves inside this IF block and checks the next IF statement to see if y is greater than 15. Since both conditions are TRUE, it displays "x is greater than 5 and y is greater than 15."

Conclusion

IF, ELSE IF, and ELSE statements are powerful tools in ApLang, allowing you to control the flow of your program based on conditions. By mastering these constructs, you can write programs that respond dynamically to a wide range of inputs and situations, making your code more flexible and adaptable.

Loops

Loops are fundamental control flow structures in ApLang that allow you to repeat a block of code multiple times. Loops are particularly useful when you want to perform a repetitive task or iterate over a collection of items without writing the same code multiple times. In ApLang, there are two main types of loops: REPEAT TIMES and REPEAT UNTIL.

REPEAT TIMES

The REPEAT TIMES loop allows you to execute a block of code a specified number of times. This type of loop is useful when you know in advance how many times you want to repeat an operation.

Syntax

REPEAT n TIMES {
    // Code to repeat
}

Here, n is the number of times the code block should be executed.

Example: REPEAT TIMES Loop

// Display "Hello, World!" 3 times
REPEAT 3 TIMES {
    DISPLAY("Hello, World!")
}
// Output:
// Hello, World!
// Hello, World!
// Hello, World!

In this example, the REPEAT TIMES loop runs the code inside the block three times, each time displaying "Hello, World!".

Example: Using a Counter

// Initialize counter
counter <- 0

// Repeat 5 times, incrementing the counter each time
REPEAT 5 TIMES {
    counter <- counter + 1
    DISPLAY(counter)
}
// Output:
// 1
// 2
// 3
// 4
// 5

In this example, the loop repeats five times, incrementing the counter by 1 on each iteration and displaying its value.

REPEAT UNTIL

The REPEAT UNTIL loop executes a block of code repeatedly until a specified condition becomes TRUE. This type of loop is useful when you want to repeat an operation until a certain condition is met, but you don't know in advance how many iterations it will take.

Syntax

REPEAT UNTIL (condition) {
    // Code to repeat
}

The loop continues to execute as long as the condition is FALSE. Once the condition evaluates to TRUE, the loop stops.

Example: REPEAT UNTIL Loop

// Initialize variable
count <- 0

// Repeat until count is equal to 5
REPEAT UNTIL (count == 5) {
    count <- count + 1
    DISPLAY(count)
}
// Output:
// 1
// 2
// 3
// 4
// 5

In this example, the loop runs until count equals 5. With each iteration, count is incremented by 1 and displayed. When count reaches 5, the loop stops.

Example: Using a Condition

// Initialize variables
balance <- 100
goal <- 200

// Double the balance until it reaches the goal
REPEAT UNTIL (balance >= goal) {
    balance <- balance * 2
    DISPLAY(balance)
}
// Output:
// 200

In this example, the loop doubles the balance on each iteration and displays it. The loop continues until balance is greater than or equal to the goal of 200.

Conclusion

Loops are an essential tool for automating repetitive tasks in ApLang. The REPEAT TIMES loop is ideal when you know how many times you need to repeat an operation, while the REPEAT UNTIL loop is perfect for scenarios where the number of iterations depends on a condition. By mastering these looping constructs, you can create more efficient and dynamic programs.

FOR EACH Loop

The FOR EACH loop in ApLang is used to iterate over the elements of a list. This type of loop is ideal when you want to perform an operation on each element of a list without manually managing loop counters or indices. The FOR EACH loop simplifies code that processes each item in a collection, making your programs easier to read and maintain.

Syntax

FOR EACH item IN list {
    // Code to execute for each item
}
  • item represents the current element in the list for each iteration of the loop.
  • list is the collection of elements you want to iterate over.

Example: Basic FOR EACH Loop

// Define a list of numbers
numbers <- [1, 2, 3, 4, 5]

// Iterate over each number in the list and display it
FOR EACH number IN numbers {
    DISPLAY(number)
}
// Output:
// 1
// 2
// 3
// 4
// 5

In this example, the FOR EACH loop iterates over each element in the numbers list and displays it. The loop executes once for each element in the list.

Example: Performing Operations on List Elements

// Define a list of words
words <- ["apple", "banana", "cherry"]

// Iterate over each word in the list and display it in uppercase
FOR EACH word IN words {
    DISPLAY(word + " in uppercase is " + TO_UPPER(word) + "!")
}
// Output:
// apple in uppercase is APPLE!
// banana in uppercase is BANANA!
// cherry in uppercase is CHERRY!

In this example, the FOR EACH loop iterates over the words list and displays each word, demonstrating how to concatenate strings within the loop.

Example: Modifying Elements Within the Loop

// Define a list of numbers
numbers <- [1, 2, 3, 4, 5]

// Initialize an empty list to hold doubled values
doubled_numbers <- []

// Iterate over each number in the list, double it, and add it to the new list
FOR EACH number IN numbers {
    doubled_numbers <- doubled_numbers + [number * 2]
}

DISPLAY(doubled_numbers)
// Output: [2, 4, 6, 8, 10]

In this example, the FOR EACH loop doubles each number in the numbers list and appends the result to a new list called doubled_numbers. The loop efficiently processes each element and builds a new list of doubled values.

Nesting FOR EACH Loops

You can nest FOR EACH loops to iterate over multiple lists or to perform more complex operations on lists of lists.

// Define a list of lists
matrix <- [[1, 2], [3, 4], [5, 6]]

// Iterate over each row in the matrix
FOR EACH row IN matrix {
    // Iterate over each element in the current row
    FOR EACH element IN row {
        DISPLAY(element)
    }
}
// Output:
// 1
// 2
// 3
// 4
// 5
// 6

In this example, the outer FOR EACH loop iterates over each row of the matrix, and the inner FOR EACH loop iterates over each element in the current row, displaying all elements in the matrix.

Conclusion

The FOR EACH loop is a powerful and versatile tool in ApLang, allowing you to iterate over lists and perform operations on each element with ease. By using FOR EACH loops, you can write cleaner and more efficient code, especially when working with collections of data. Mastering this loop will enable you to handle a wide range of programming tasks involving lists in ApLang.

BREAK and CONTINUE in Loops

In ApLang, loops like REPEAT, REPEAT UNTIL, and FOR EACH give you the ability to control the flow of the loop execution using the BREAK and CONTINUE keywords.

BREAK

The BREAK keyword allows you to exit a loop entirely before it naturally finishes. Once the BREAK statement is encountered, the program will immediately stop executing the current loop and move to the next statement after the loop.

Here's an example of using BREAK in a loop:

REPEAT 10 TIMES {
    IF (i == 5) {
        BREAK
    }
    DISPLAY(i)
}
// This will display numbers from 1 to 4 and then stop

In this example, the loop will terminate when the value of i reaches 5, and no further iterations will be performed.

CONTINUE

The CONTINUE keyword is used to skip the current iteration of a loop and move to the next one without breaking out of the loop completely. Once the CONTINUE statement is encountered, the program will stop the current iteration and start the next iteration of the loop immediately.

Here's an example of using CONTINUE:

REPEAT 10 TIMES {
    IF (i == 5) {
        CONTINUE
    }
    DISPLAY(i)
}
// This will display numbers from 1 to 4 and 6 to 10, skipping 5

In this case, when the value of i is 5, the CONTINUE statement will skip displaying i and jump to the next iteration, so 5 will not be printed.

Using BREAK and CONTINUE in FOR EACH

Both BREAK and CONTINUE can also be used in FOR EACH loops to manage the flow of list iteration. Here's an example:

FOR EACH item IN myList {
    IF (item == "skipThis") {
        CONTINUE
    }
    IF (item == "stopHere") {
        BREAK
    }
    DISPLAY(item)
}

In this example, the CONTINUE statement skips the iteration where item equals "skipThis", and the BREAK statement stops the loop entirely when item equals "stopHere".

Conclusion

The BREAK and CONTINUE keywords give you finer control over loop execution in ApLang. Whether you need to prematurely exit a loop or skip over specific iterations, these commands provide essential tools for managing complex looping conditions.

Procedures

Procedures in ApLang are a way to encapsulate a block of code that performs a specific task. Think of procedures as a box: you can put values into the box (inputs), the box does something with those values, and then gives you a result (output). Procedures help make your programs more organized, reusable, and easier to understand.

What is a Procedure?

A procedure is a reusable block of code that performs a particular function or task. You can define a procedure once and then use it (or "call" it) multiple times throughout your program, providing different inputs each time. This helps reduce code duplication and makes your program easier to manage.

Defining a Procedure

To define a procedure in ApLang, use the PROCEDURE keyword followed by the procedure’s name and a pair of parentheses (). Inside the parentheses, you can specify any parameters that the procedure takes as input. The code block inside the curly braces {} is the body of the procedure, which contains the instructions that the procedure will execute.

Syntax

PROCEDURE procedure_name(parameter1, parameter2, ...) {
    // Code to execute
    RETURN result
}

Example: Defining a Simple Procedure

// Define a procedure to add two numbers
PROCEDURE add(a, b) {
    sum <- a + b
    RETURN sum
}

In this example, the add procedure takes two parameters, a and b, adds them together, and returns the result. The RETURN statement specifies the value that the procedure outputs.

Calling a Procedure

Once a procedure is defined, you can call it by using its name followed by parentheses containing any arguments you want to pass to it. The procedure will execute its code block using the provided arguments and return a result.

Example: Calling a Procedure

// Call the 'add' procedure with arguments 3 and 4
result <- add(3, 4)
DISPLAY(result)  // Output: 7

In this example, the add procedure is called with the arguments 3 and 4. The procedure returns 7, which is then displayed.

Reference vs. Value

When passing parameters to procedures in ApLang, it's important to understand the difference between passing by reference and passing by value:

  • Pass by Value: When a parameter is passed by value, the procedure receives a copy of the argument. Changes made to this parameter inside the procedure do not affect the original argument. In ApLang, numbers, strings, and booleans are passed by value.

  • Pass by Reference: When a parameter is passed by reference, the procedure receives a reference to the actual argument, not a copy. Any changes made to this parameter inside the procedure will affect the original argument. In ApLang, lists are passed by reference.

Example: Pass by Value

PROCEDURE modify_number(n) {
    n <- n + 10
    DISPLAY(n)  // Output: 15
}

num <- 5
modify_number(num)
DISPLAY(num)  // Output: 5

In this example, num is passed by value to the modify_number procedure. Inside the procedure, the local copy of n is modified, but the original num remains unchanged outside the procedure.

Example: Pass by Reference

PROCEDURE add_to_list(lst) {
    APPEND(lst, 4)
    DISPLAY(lst)  // Output: [1, 2, 3, 4]
}

my_list <- [1, 2, 3]
add_to_list(my_list)
DISPLAY(my_list)  // Output: [1, 2, 3, 4]

In this example, my_list is passed by reference to the add_to_list procedure. Inside the procedure, the list is modified, and this change affects the original my_list outside the procedure.

Using Procedures to Organize Code

Procedures are a powerful way to organize your code by breaking it down into smaller, manageable pieces. Each procedure can focus on a specific task, making your code easier to read, debug, and maintain.

Example: Using Procedures to Break Down a Task

// Define a procedure to multiply two numbers
PROCEDURE multiply(a, b) {
    product <- a * b
    RETURN product
}

// Define a procedure to calculate the area of a rectangle
PROCEDURE calculate_area(length, width) {
    area <- multiply(length, width)
    RETURN area
}

// Call the 'calculate_area' procedure
area <- calculate_area(5, 10)
DISPLAY(area)  // Output: 50

In this example, two procedures are defined: multiply and calculate_area. The calculate_area procedure uses the multiply procedure to compute the area of a rectangle. By using procedures, the code is modular and easy to understand.

Procedures with No Return Value

Not all procedures need to return a value. Sometimes, you might want a procedure to perform an action without giving back a result. In ApLang, procedures that do not have a RETURN statement simply execute their code and then finish.

Example: Procedure with No Return Value

// Define a procedure to display a greeting
PROCEDURE greet(name) {
    DISPLAY("Hello, " + name + "!")
}

// Call the 'greet' procedure
greet("Alice")  // Output: "Hello, Alice!"

In this example, the greet procedure takes a parameter name and displays a greeting. It does not return any value; it simply performs an action.

Conclusion

Procedures are like a toolbox in ApLang, allowing you to encapsulate reusable blocks of code that perform specific tasks. By understanding how ApLang passes parameters—by reference for lists and by value for other types—you can better manage how your procedures interact with data. Whether you’re returning values or simply performing actions, procedures are an essential tool for building robust and maintainable programs in ApLang.

Modules

As you begin to write larger and more complex programs, organizing your code will become increasingly more important. (The Rust Book)

This is where modules come in. Modules help to encapsulate implementation details, which means they hide the internal workings of your code. By doing this, modules allow you to expose only the parts of the code that are necessary for the user, keeping the rest private. This makes it easier to understand and maintain your programs by breaking them down into smaller, more manageable building blocks.

Every .ap file in ApLang is also considered a module. In ApLang, there are two types of modules: Standard Library Modules and User Modules.

Standard Library Modules

Standard Library Modules come built-in with ApLang and are written in Rust. These modules provide essential functionality that you can use in your programs. Standard Library Modules and their functions follow a convention of using SCREAMING_CASE for their names. Here’s how you can import them:

// Import all functions from a standard library module
IMPORT MOD "MATH"

// Now, we can use functions from the MATH module

// Import just the INPUT function from the IO module
IMPORT "INPUT" FROM MOD "IO"

// Import the FILE_CREATE and FILE_READ functions from the FS (file system) module
IMPORT ["FILE_CREATE", "FILE_READ"] FROM MOD "FS"

User Modules

User Modules are modules written by you, the programmer, using ApLang. These modules also have the .ap file extension, and you can specify their path when importing them. Here’s an example:

// main.ap

// Importing a specific function from a user module using its relative path
IMPORT "myFunction" FROM "./myModule.ap"

// This is equivalent to the previous statement
IMPORT "myFunction" FROM "myModule.ap"

// Importing a whole nested module
IMPORT "./nested/myNestedModule.ap"

In contrast to Standard Library Modules, user-defined functions and modules should be written in camelCase rather than SCREAMING_CASE. This helps distinguish user code from the standard library code.

Directory Structure Example

To better visualize how modules are organized, let's look at a simple project directory tree:

/my_project
|-- main.ap
|-- myModule.ap
|-- nested/
|   |-- myNestedModule.ap

Exporting Functions

By default, functions in ApLang are private, meaning they can't be accessed outside of the file they're defined in. To make a function accessible to other modules, you need to use the EXPORT keyword before PROCEDURE. Here’s how you can export a function:

// myModule.ap
EXPORT PROCEDURE myFunction() {
    // does something
}
If you are exporting Procedures that require other Modules, you must import the Module Inside the Procedure that you want to export, or you must import the Module inside the main file that calls the Procedure.

This Behavior Might Change In The Future

Importing the Module inside the Procedure

// main.ap
IMPORT MOD "module.ap"

myModuleFunction() // Function defined in module.ap

// module.ap
IMPORT MOD "TIME" // This import will not translate to main.ap

myModuleFunction() {
	IMPORT MOD "TIME" // You need to import TIME here
	TIME()
}

Importing the Module Inside Main

// main.ap
IMPORT MOD "module.ap"
IMPORT "TIME" // Or you can import TIME here

myModuleFunction() // Function defined in module.ap

// module.ap
IMPORT MOD "TIME" // This import will not translate to main.ap

myModuleFunction() {
	TIME()
}

Exporting Values

You cannot directly export variables in ApLang. If you want to share a variable across modules, you need to wrap it in a function:

EXPORT PROCEDURE myFavoriteNumber() {
    RETURN 8
}

By exporting this procedure, other modules can call myFavoriteNumber() to get the value 8.

Conclusion

Modules are a powerful tool in ApLang that help you organize and manage your code more effectively. By encapsulating implementation details, modules make it easier to break down complex programs into smaller, reusable components. Whether you're using built-in Standard Library Modules or creating your own User Modules, understanding how to import, export, and structure your code will allow you to build more robust and maintainable projects. As your programs grow, leveraging modules will become essential for keeping your codebase clean and efficient.

Other

ASCII Escape Codes

When writing strings in programming, there are times you need to represent characters that can't be typed directly, such as newlines or tabs. To handle these situations, ASCII escape codes provide a way to "write the un-writable." Escape codes allow you to include special or unprintable characters in your strings by using a sequence that starts with a backslash (\).

Valid Escape Codes

CODEDescription
\\Backslash (\)
\nNewline
\rCarriage Return
\tTab
\"Double Quote (")

Error Anatomy

When you're writing code, you're bound to run into errors. It's just a fact of life. While they might look complicated at first, error messages are really just the program's way of telling you something went wrong, and our way of giving you clues on how to fix it. Let's break one down together.

Here's a super simple example of one:

Error: aplang::runtime

  x Invalid Variable
   ,-[./examples.ap/main.ap:1:1]
 1 | var
   : |
   : `-- Could not find variable
 2 |
   `----
  help: Make sure to create the variable `var` before you use it

error: process didn't exit successfully: `target\debug\aplang.exe -d all ./examples.ap/main.ap` (exit code: 1)

Let's break this down step by step:

  1. Error type: Error: aplang::runtime

    The very first line tells you what type of error occurred. This will often tell you the general category of the error, like a runtime error or a syntax error. In our case, this is a runtime error.

  2. Error code: x Invalid Variable

    Right below the error type, you'll usually find a more succinct description of the error. It's like a headline that summarizes the problem in a few words. In our case, it's telling us that a variable that we tried to use is invalid.

  3. Error Location (File and Line Number): [./examples.ap/main.ap:1:1]

    This part tells you where the error occurred. It's usually in the format [file_path:line_number:column_number]. In our case, the error occurred in the file main.ap at line 1, column 1.

    When Importing code from a Module, the file_path will always show the main file, even if the error is in the Module. This is subject to change.
  4. Code Snippet:

    1 | var
      : |
      : `-- Could not find variable
    2 |
    

    The code snippet is a little snapshot of your code around the error. There is often a little pointer and a message that tells you almost exactly what went wrong. Here, it's showing us that the error occurred on line 1, where we tried to use the variable var.

  5. Help Message: help: Make sure to create the variable `var` before you use it

    Finally, the help message will often give you a hint on how to fix the error. It's the most common fix for the error you're seeing. In our case, it's telling us to create the variable var before we use it.

Some Confusing Errors

  1.  Error:   x (todo) Expected from following specific imports, found
     |
    
    For this one, check your import statements. You most likely forgot the word `MOD` after `IMPORT`.

    This error message is subject to be fixed

  2. Error:   x expected primary, instead found {
    |
    ,-[main.ap:1:14]
    1 | someProcedure( {
    :              ^ |
    :              | `-- primary expected here
    :              `-- consider checking your upstream code
    2 |
    `----
    help: a primary is made up of the following set:
            [expression | ident | literal | list]
    

    This error is telling us that it expected a primary, but instead found a {. In this case, we missed a closing parenthesis ).

Core Module Documentation

IMPORTED BY DEFAULT

The Core module provides essential functions for user interaction, list manipulation, and generating random numbers.

Table of Contents


Functions


DISPLAY

Outputs the given value to the console.

Parameters:

  • value: Any The value to be displayed.

Returns:

  • NULL

Example Usage:

DISPLAY("Hello, world!")
DISPLAY(123)

DISPLAY_NOLN

Outputs the given value to the console without creating a newline.

Parameters:

  • value: Any The value to be displayed.

Returns:

  • NULL

Example Usage:

DISPLAY_NOLN("Hello, world!")
DISPLAY_NOLN(123)
// Hello, world!123

INPUT

Prompts the user for input and returns the entered value as a string.

Parameters: None

Returns:

  • String: The input provided by the user.

Example Usage:

user_input <- INPUT()
DISPLAY(user_input)

INSERT

Inserts a value into a list at a specified index.

Parameters:

  • list: List The list in which to insert the value.
  • i: Number The index at which to insert the value (indexed starting at 1).
  • value: Any The value to insert.

Returns:

  • NULL

Example Usage:

my_list <- [1, 2, 4]
INSERT(my_list, 3, 3)
DISPLAY(my_list) // [1, 2, 3, 4]

APPEND

Appends a value to the end of a list.

Parameters:

  • list: List The list to which the value will be appended.
  • value: Any The value to append.

Returns:

  • NULL

Example Usage:

my_list <- [1, 2, 3]
APPEND(my_list, 4)
DISPLAY(my_list) // [1, 2, 3, 4]

REMOVE

Removes a value from a list at the specified index and returns the removed value.

Parameters:

  • list: List The list from which the value will be removed.
  • i: Number The index of the value to remove (indexed starting at 1).

Returns:

  • Value: The value that was removed.

Example Usage:

my_list <- [1, 2, 3, 4]
removed <- REMOVE(my_list, 2)
DISPLAY(removed) // 2
DISPLAY(my_list) // [1, 3, 4]

LENGTH

Returns the length of a list.

Parameters:

  • list: List The list whose length will be returned.

Returns:

  • Number: The length of the list as a number.

Example Usage:

my_list <- [1, 2, 3]
list_length <- LENGTH(my_list)
DISPLAY(list_length) // 3

RANDOM

Generates a random integer between two numbers (inclusive).

Parameters:

  • a: Number The lower bound.
  • b: Number The upper bound.

Returns:

  • Number: A random integer between a and b.

Example Usage:

random_number <- RANDOM(1, 10)
DISPLAY(random_number) // Random number between 1 and 10

File System Module Documentation

IMPORT MOD "FS"

The File System module provides functions for interacting with the file system, including checking paths, reading/writing files, and managing directories.

Table Of Contents


Functions


PATH_EXISTS

Checks whether a given path exists.

Parameters:

  • path: String The path to check.

Returns:

  • Bool: TRUE if the path exists, FALSE otherwise.

Example Usage:

exists <- PATH_EXISTS("/home/user/file.txt")
DISPLAY(exists)

PATH_IS_FILE

Checks if a given path is a file.

Parameters:

  • path: String The path to check.

Returns:

  • Bool: TRUE if the path is a file, FALSE otherwise.

Example Usage:

is_file <- PATH_IS_FILE("/home/user/file.txt")
DISPLAY(is_file)

PATH_IS_DIRECTORY

Checks if a given path is a directory.

Parameters:

  • path: String The path to check.

Returns:

  • Bool: TRUE if the path is a directory, FALSE otherwise.

Example Usage:

is_dir <- PATH_IS_DIRECTORY("/home/user/")
DISPLAY(is_dir)

FILE_CREATE

Creates a new file at the specified path. Returns TRUE if the file was created successfully.

Parameters:

  • file_path: String The path where the file should be created.

Returns:

  • Bool: TRUE if the file was created, FALSE if there was an error.

Example Usage:

success <- FILE_CREATE("/home/user/new_file.txt")
DISPLAY(success)

FILE_READ

Reads the contents of a file as a string. Returns NULL if the file cannot be read.

Parameters:

  • file_path: String The path of the file to read.

Returns:

  • String: The contents of the file, NULL If the file cannot be read.

Example Usage:

contents <- FILE_READ("/home/user/file.txt")

IF (contents == NULL) {
    DISPLAY("Failed to read file.")
} ELSE {
    DISPLAY(contents)
}

FILE_APPEND

Appends the given content to the end of a file. Returns TRUE if successful.

Parameters:

  • file_path: String The path of the file.
  • contents: Value The content to append.

Returns:

  • Bool: TRUE if the content was successfully appended, FALSE otherwise.

Example Usage:

success <- FILE_APPEND("/home/user/file.txt", "New content to add.")
DISPLAY(success)

FILE_OVERWRITE

Overwrites the contents of a file with the provided content. Returns TRUE if successful.

Parameters:

  • file_path: String The path of the file.
  • contents: Value The content to overwrite the file with.

Returns:

  • Bool: TRUE if the content was successfully written, FALSE otherwise.

Example Usage:

success <- FILE_OVERWRITE("/home/user/file.txt", "Overwritten content.")
DISPLAY(success)

DIRECTORY_READ

Reads the contents of a directory and returns a list of file paths.

Parameters:

  • path: String The path of the directory to read.

Returns:

  • List A list of file paths in the directory.

Example Usage:

files <- DIRECTORY_READ("/home/user/")

FOR EACH file IN files {
    DISPLAY(file)
}

DIRECTORY_CREATE

Creates a new, empty directory at the provided path. Does not create parent directories.

Note: To create a directory and all its missing parents at the same time, instead use DIRECTORY_CREATE_ALL. Parameters:

  • path: String The path of the directory to be created.

Returns:

  • Bool Is TRUE if creation was successfull FALSE otherwise.

Errors When:

  • User lacks permissions to create directory at path.
  • A parent of the given path doesn't exist.
  • path already exists.

Example Usage:

success <- DIRECTORY_CREATE("some/dir")
DISPLAY(success)

DIRECTORY_CREATE_ALL

Creates a new, empty directory at the provided path. Will create parent directories.

Parameters:

  • path: String The path of the directory to be created.

Returns:

  • Bool Is TRUE if creation was successfull FALSE otherwise.

Errors When:

  • If any directory in the path specified by path does not already exist and it could not be created otherwise.

Example Usage:

success <- DIRECTORY_CREATE_ALL("some/dir")
DISPLAY(success)

DIRECTORY_REMOVE_ALL

Be very cautious when using this function!

Removes a directory at this path, after removing all its contents.

Parameters:

  • path: String The path of the directory to be removed.

Returns:

  • Bool Is TRUE if creation was successfull FALSE otherwise.

Example Usage:

success <- DIRECTORY_REMOVE_ALL("some/dir")
DISPLAY(success)

DIRECTORY_REMOVE

Removes an empty directory.

Parameters:

  • path: String The path of the directory to be removed.

Returns:

  • Bool Is TRUE if creation was successfull FALSE otherwise.

Errors When:

  • path doesn't exist.
  • path isn't a directory.
  • The user lacks permissions to remove the directory at the provided path.
  • The directory isn't empty.

Example Usage:

success <- DIRECTORY_REMOVE("some/dir")
DISPLAY(success)

Time Module Documentation

IMPORT MOD "TIME"

The Time module provides functions for getting the current time and pausing execution for a specified duration.

Table of Contents


Functions


TIME

Returns the current time in milliseconds since the UNIX epoch (January 1, 1970).

Parameters: None

Returns:

  • Number: The current time in milliseconds

Example Usage:

current_time <- TIME()
DISPLAY(current_time)

SLEEP

Pauses the execution of the program for a specified number of milliseconds.

Parameters:

  • duration: Number The duration to sleep in milliseconds.

Returns:

  • NULL

Example Usage:

DISPLAY("Sleeping for 2 seconds...")
SLEEP(2000)
DISPLAY("Awake now!")

Math Module Documentation

IMPORT MOD "MATH"

The Math module provides a variety of mathematical functions, including trigonometric, hyperbolic, exponential, logarithmic, rounding, and clamping functions. It also includes important constants like PI, E, and TAU.

Table of Contents


Functions


SIN

Calculates the sine of an angle in radians.

Parameters:

  • angle: Number The angle in radians.

Returns:

  • Number: The sin of the given angle

Example Usage:

result <- SIN(1.5708) // Approx value of PI/2
DISPLAY(result)

COS

Calculates the cosine of an angle in radians.

Parameters:

  • angle: Number The angle in radians.

Returns:

  • Number: The cosine of the given angle.

Example Usage:

result <- COS(0)
DISPLAY(result)

TAN

Calculates the tangent of an angle in radians.

Parameters:

  • angle: Number The angle in radians.

Returns:

  • Number: The tangent of the given angle.

Example Usage:

result <- TAN(0.7854) // Approx value of PI/4
DISPLAY(result)

ASIN

Calculates the arc sine of a value.

Parameters:

  • value: Number The input value, must be between -1 and 1.

Returns:

  • Number: The arc sine in radians of the given angle.

Example Usage:

result <- ASIN(0.5)
DISPLAY(result)

ACOS

Calculates the arc cosine of a value.

Parameters:

  • value: Number The input value, must be between -1 and 1.

Returns:

  • Number: The arc cosine in radians of the given angle.

Example Usage:

result <- ACOS(0.5)
DISPLAY(result)

ATAN

Calculates the arc tangent of a value.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The arc tangent in radians of the given angle.

Example Usage:

result <- ATAN(1)
DISPLAY(result)

ATAN2

Calculates the arc tangent of y/x, using the signs of both values to determine the correct quadrant.

Parameters:

  • y: Number The y-coordinate.
  • x: Number The x-coordinate.

Returns:

  • Number: The arc tangent of y/x.

Example Usage:

result <- ATAN2(1, 1)
DISPLAY(result)

SINH

Calculates the hyperbolic sine of a value.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The hyperbolic sine of the given value.

Example Usage:

result <- SINH(1)
DISPLAY(result)

COSH

Calculates the hyperbolic cosine of a value.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The hyperbolic cosine of the given value.

Example Usage:

result <- COSH(1)
DISPLAY(result)

TANH

Calculates the hyperbolic tangent of a value.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The hyperbolic tangent of the given value.

Example Usage:

result <- TANH(1)
DISPLAY(result)

ASINH

Calculates the inverse hyperbolic sine of a value.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The inverse hyperbolic sine of the given value.

Example Usage:

result <- ASINH(1)
DISPLAY(result)

ACOSH

Calculates the inverse hyperbolic cosine of a value.

Parameters:

  • value: Number The input value, must be greater than or equal to 1.

Returns:

  • Number: The inverse hyperbolic cosine of the given value.

Example Usage:

result <- ACOSH(1)
DISPLAY(result)

ATANH

Calculates the inverse hyperbolic tangent of a value.

Parameters:

  • value: Number The input value, must be between -1 and 1.

Returns:

  • Number: The inverse hyperbolic tangent of the given value.

Example Usage:

result <- ATANH(0.5)
DISPLAY(result)

EXP

Calculates the exponential of a value (e^value).

Parameters:

  • value: Number The input value.

Returns:

  • Number: The result of e^value.

Example Usage:

result <- EXP(1)
DISPLAY(result)

LOG

Calculates the logarithm of a value with a specified base.

Parameters:

  • value: Number The input value.
  • base: Number The base of the logarithm.

Returns:

  • Number: The logarithm of value to the base base.

Example Usage:

result <- LOG(8, 2)
DISPLAY(result)

LOG10

Calculates the base-10 logarithm of a value.

Parameters:

  • value: Number: The input value.

Returns:

  • Number The base-10 logarithm of the given value.

Example Usage:

result <- LOG10(100)
DISPLAY(result)

LOG2

Calculates the base-2 logarithm of a value.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The base-2 logarithm of the given value.

Example Usage:

result <- LOG2(8)
DISPLAY(result)

ROUND

Rounds a number to the nearest whole number.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The rounded value.

Example Usage:

result <- ROUND(2.7)
DISPLAY(result)

FLOOR

Rounds a number down to the nearest whole number.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The rounded-down value.

Example Usage:

result <- FLOOR(2.7)
DISPLAY(result) // 2

CEIL

Rounds a number up to the nearest whole number.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The rounded-up value.

Example Usage:

result <- CEIL(2.1)
DISPLAY(result) // 3

INT

Truncates the decimal part of a number.

Parameters:

  • value: Number The input value.

Returns:

  • Number: The truncated value.

Example Usage:

result <- INT(2.7)
DISPLAY(result) // 2

CLAMP

Clamps a number between a minimum and maximum value.

Parameters:

  • value: Number The input value.
  • min: Number The minimum value.
  • max: Number The maximum value.

Returns:

  • Number: The clamped value.

Example Usage:

result <- CLAMP(15, 1, 10)
DISPLAY(result) // 10

PI

Returns the value of PI.

Returns:

  • Number: The value of PI (3.14159...).

Example Usage:

pi_value <- PI()
DISPLAY(pi_value)

E

Returns the value of Euler's number (e).

Returns:

  • Number: The value of Euler's number (2.71828...).

Example Usage:

e_value <- E()
DISPLAY(e_value)

TAU

Returns the value of TAU (2 * PI).

Returns:

  • Number: The value of TAU (6.28318...).

Example Usage:

tau_value <- TAU()
DISPLAY(tau_value)

String Module Documentation

IMPORT MOD "STRING"

This module provides various string manipulation functions that allow for conversion, splitting, transformation, and inspection of strings.

Table of Contents


Functions


TO_NUMBER

Converts a string to a number (f64). Returns NULL if the conversion is not possible.

Parameters:

  • raw: String The string to convert.

Returns:

  • Number: The converted number, NULL If the conversion fails.

Example Usage:

number <- TO_NUMBER("123.45")

IF (number == NULL) {
    DISPLAY("Conversion failed.")
}

TO_BOOL

Converts a string to a boolean. Returns NULL if the conversion is not possible.

Parameters:

  • raw: String The string to convert.

Returns:

  • Bool: The converted boolean, NULL If the conversion fails.

Example Usage:

boolean <- TO_BOOL("TRUE") // you can also use "true" here

IF (boolean != NULL AND boolean == TRUE) {
    DISPLAY("It's true!")
}

SPLIT

Splits a string into a list of strings based on a pattern.

Parameters:

  • raw: String The string to split.
  • pattern: String The delimiter used to split the string.

Returns:

  • List: A list of strings obtained by splitting the original string.

Example Usage:

parts <- SPLIT("apple,banana,orange", ",")

FOR EACH item IN parts {
    DISPLAY(item)
}

// apple
// banana
// orange

TO_UPPER

Converts a string to uppercase.

Parameters:

  • raw: String The string to convert.

Returns:

  • String: The converted uppercase string.

Example Usage:

upper_case <- TO_UPPER("hello")

DISPLAY(upper_case) // "HELLO"

TO_LOWER

Converts a string to lowercase.

Parameters:

  • raw: String The string to convert.

Returns:

  • String: The converted lowercase string.

Example Usage:

lower_case <- TO_LOWER("HELLO")

DISPLAY(lower_case) // "hello"

TRIM

Removes leading and trailing whitespace from a string.

Parameters:

  • raw: String The string to trim.

Returns:

  • String: The trimmed string.

Example Usage:

trimmed <- TRIM("  hello  ")

DISPLAY(trimmed) // "hello"

CONTAINS

Checks if a string contains a given substring.

Parameters:

  • raw: String The string to search.
  • pattern: String The substring to search for.

Returns:

  • Bool: TRUE if the substring is found, FALSE otherwise.

Example Usage:

contains <- CONTAINS("hello world", "world")

IF (contains) {
    DISPLAY("Found it!")
}

REPLACE

Replaces all occurrences of a substring with another substring.

Parameters:

  • raw: String The string to modify.
  • from: String The substring to replace.
  • to: String The substring to replace with.

Returns:

  • String: The modified string with replacements.

Example Usage:

replaced <- REPLACE("hello world", "world", "everyone")

DISPLAY(replaced) // "hello everyone"

STARTS_WITH

Checks if a string starts with a given prefix.

Parameters:

  • raw: String The string to check.
  • prefix: String The prefix to check for.

Returns:

  • Bool: TRUE if the string starts with the prefix, FALSE otherwise.

Example Usage:

starts <- STARTS_WITH("hello", "he")

IF (starts) {
    DISPLAY("Starts with 'he'")
}

ENDS_WITH

Checks if a string ends with a given suffix.

Parameters:

  • raw: String The string to check.
  • suffix: String The suffix to check for.

Returns:

  • Bool: TRUE if the string ends with the suffix, FALSE otherwise.

Example Usage:

ends <- ENDS_WITH("hello", "lo")

IF (ends) {
    DISPLAY("Ends with 'lo'")
}

JOIN

Joins a list of strings into a single string, separated by a given separator.

Parameters:

  • list: List The list of strings to join.
  • separator: String The separator to use between elements.

Returns:

  • String: The joined string.

Example Usage:

joined <- JOIN(["apple", "banana", "orange"], ", ")

DISPLAY(joined) // "apple, banana, orange"

SUBSTRING

Extracts a substring from a string, starting at a given position and of a specified length.

Parameters:

  • raw: String The original string.
  • start: Number The starting index (1-based).
  • length: Number The length of the substring.

Returns:

  • String: The extracted substring.

Example Usage:

substring <- SUBSTRING("hello world", 1, 4)

DISPLAY(substring) // ello

TO_CHAR_ARRAY

Converts a string into a list of single-character strings.

Parameters:

  • raw: String The string to convert.

Returns:

  • List: A list where each element is a single-character string.

Example Usage:

char_array <- TO_CHAR_ARRAY("hello")

FOR EACH char in char_array {
  DISPLAY(char)
}

// h
// e
// l
// l
// o

IO Module Documentation

IMPORT MOD "IO"

The IO module provides functions for formatted user input, output, and string formatting.

Table of Contents


Functions


INPUT_PROMPT

Prompts the user with a custom message and returns the user's input as a string.

Parameters:

  • prompt: String The prompt message to display to the user.

Returns:

  • String: The user's input as a string.

Example Usage:

user_input <- INPUT_PROMPT("Enter your name: ")
DISPLAY(user_input)

FORMAT

Formats a string by replacing placeholders ({}) with values from a list.

Parameters:

  • fstring: String The format string with {} as placeholders.
  • args: List The list of values to insert into the format string.

Returns:

  • String: The formatted string.

Example Usage:

name <- "Alice"
age <- 25
message <- FORMAT("My name is {} and I am {} years old.", [name, age])
DISPLAY(message)
// "My name is Alice and I am 25 years old."

DISPLAYF

Displays a formatted string to the console by replacing placeholders ({}) with values from a list.

Parameters:

  • fstring: String The format string with {} as placeholders.
  • args: List The list of values to insert into the format string.

Returns:

  • NULL

Example Usage:

name <- "Bob"
score <- 100
DISPLAYF("Player {} scored {} points!", [name, score])
// "Player Bob scored 100 points!"

Style Module Documentation

IMPORT MOD "STYLE"

The style module includes utilities for coloring and adding styles to displayed text.

Table of Contents


Functions


CLEAR_STYLE

Clears all applied styles

Parameters: None.

Returns: None.

Example Usage:

STYLE("blue")
DISPLAY("This text is blue")
CLEAR_STYLE()
DISPLAY("This text is no longer blue")

STYLE

Applies a style

Parameters:

  • style: String The style type to apply to the text
Default Colors

Style/ColorANSI CodeDescription
clear\x1b[0mResets all styles and colors
default_color\x1b[39mResets the foreground color to default
bg_default_color\x1b[49mResets the background color to default

Foreground Colors

Style/ColorANSI CodeDescription
black\x1b[30mSets the text color to black
red\x1b[31mSets the text color to red
green\x1b[32mSets the text color to green
yellow\x1b[33mSets the text color to yellow
blue\x1b[34mSets the text color to blue
magenta\x1b[35mSets the text color to magenta
cyan\x1b[36mSets the text color to cyan
white\x1b[37mSets the text color to white
bright_black\x1b[90mSets the text color to bright black (gray)
bright_red\x1b[91mSets the text color to bright red
bright_green\x1b[92mSets the text color to bright green
bright_yellow\x1b[93mSets the text color to bright yellow
bright_blue\x1b[94mSets the text color to bright blue
bright_magenta\x1b[95mSets the text color to bright magenta
bright_cyan\x1b[96mSets the text color to bright cyan
bright_white\x1b[97mSets the text color to bright white

Background Colors

Style/ColorANSI CodeDescription
bg_black\x1b[40mSets the background color to black
bg_red\x1b[41mSets the background color to red
bg_green\x1b[42mSets the background color to green
bg_yellow\x1b[43mSets the background color to yellow
bg_blue\x1b[44mSets the background color to blue
bg_magenta\x1b[45mSets the background color to magenta
bg_cyan\x1b[46mSets the background color to cyan
bg_white\x1b[47mSets the background color to white
bg_bright_black\x1b[100mSets the background color to bright black (gray)
bg_bright_red\x1b[101mSets the background color to bright red
bg_bright_green\x1b[102mSets the background color to bright green
bg_bright_yellow\x1b[103mSets the background color to bright yellow
bg_bright_blue\x1b[104mSets the background color to bright blue
bg_bright_magenta\x1b[105mSets the background color to bright magenta
bg_bright_cyan\x1b[106mSets the background color to bright cyan
bg_bright_white\x1b[107mSets the background color to bright white

Text Styles

Style/ColorANSI CodeDescription
bold\x1b[1mMakes the text bold or bright
faint\x1b[2mMakes the text faint or dim
underline\x1b[4mUnderlines the text
blink\x1b[5mMakes the text blink (less supported)

Returns:

  • Bool: TRUE if the style was applied, FALSE if it was not

Example Usage:

STYLE("red")
DISPLAY("This text is red")
CLEAR_STYLE()