Introduction
In this tutorial, we'll build a simple command-line calculator that can perform basic arithmetic operations. This project will demonstrate:
- Reading user input
- String manipulation and parsing
- Basic error handling with the
result type
- Control flow with
match expressions
- Basic arithmetic operations
By the end of this tutorial, you'll have a fully functional calculator program that can add, subtract, multiply, and divide numbers.
Setup
First, make sure you have ShitRust installed on your system. If not, follow the installation instructions.
Create a new file called calculator.sr. We'll start by importing the standard I/O library to handle user input and output:
// Import standard input/output library
import { stdin, stdout } from "std/io";
Basic Structure
Let's start by defining a function to display welcome messages and instructions to the user:
// Function to display welcome message and instructions
fn show_welcome() -> void {
println("===== ShitRust Calculator =====");
println("Enter an expression with two numbers and an operator.");
println("Example: 5 + 3");
println("Supported operators: +, -, *, /");
println("Type 'exit' to quit.");
println("==============================");
}
This function uses the println function to display text to the console. The -> void return type indicates that this function doesn't return a value.
Calculation Logic
Now we'll implement the function that performs the actual calculation:
// Function to perform the calculation
fn calculate(a: float, op: string, b: float) -> result {
match op {
"+" => return ok(a + b),
"-" => return ok(a - b),
"*" => return ok(a * b),
"/" => {
if b == 0.0 {
return err("Division by zero is not allowed");
}
return ok(a / b);
},
_ => return err("Unsupported operator")
}
}
This function uses pattern matching with a match expression to handle different operators. It also returns a result type, allowing us to handle errors like division by zero.
Main Program Loop
Finally, let's implement the main function that ties everything together:
// Main function
fn main() -> void {
show_welcome();
// Main program loop
let mut running = true;
while (running) {
// Prompt for input
print("> ");
let input = stdin.read_line();
// Check for exit command
if input.trim().to_lowercase() == "exit" {
println("Goodbye!");
running = false;
continue;
}
// Parse input and calculate
let parse_result = parse_input(input);
match parse_result {
ok((a, op, b)) => {
let calc_result = calculate(a, op, b);
match calc_result {
ok(result) => {
println("Result: " + result.to_string());
},
err(error_msg) => {
println("Error: " + error_msg);
}
}
},
err(error_msg) => {
println("Error: " + error_msg);
}
}
println(""); // Empty line for better readability
}
}
The main function:
- Displays the welcome message
- Enters a loop that continues until the user types "exit"
- Reads user input, parses it, and performs the calculation
- Handles errors at each step and displays appropriate messages
Complete Code
Here's the complete code for our calculator program:
// ShitRust Command-Line Calculator
// This program demonstrates basic input/output and arithmetic operations
// Import standard input/output library
import { stdin, stdout } from "std/io";
// Function to display welcome message and instructions
fn show_welcome() -> void {
println("===== ShitRust Calculator =====");
println("Enter an expression with two numbers and an operator.");
println("Example: 5 + 3");
println("Supported operators: +, -, *, /");
println("Type 'exit' to quit.");
println("==============================");
}
// Function to parse user input and extract operation components
fn parse_input(input: string) -> result<(float, string, float), string> {
// Trim input and split by spaces
let trimmed = input.trim();
let parts = trimmed.split(" ");
if parts.length() != 3 {
return err("Invalid input format. Please use: number operator number");
}
// Parse the first number
let first_num = parts[0].parse_float();
if first_num.is_err() {
return err("Invalid first number");
}
// Get the operator
let operator = parts[1];
if operator != "+" && operator != "-" && operator != "*" && operator != "/" {
return err("Invalid operator. Use +, -, *, or /");
}
// Parse the second number
let second_num = parts[2].parse_float();
if second_num.is_err() {
return err("Invalid second number");
}
return ok((first_num.unwrap(), operator, second_num.unwrap()));
}
// Function to perform the calculation
fn calculate(a: float, op: string, b: float) -> result {
match op {
"+" => return ok(a + b),
"-" => return ok(a - b),
"*" => return ok(a * b),
"/" => {
if b == 0.0 {
return err("Division by zero is not allowed");
}
return ok(a / b);
},
_ => return err("Unsupported operator")
}
}
// Main function
fn main() -> void {
show_welcome();
// Main program loop
let mut running = true;
while (running) {
// Prompt for input
print("> ");
let input = stdin.read_line();
// Check for exit command
if input.trim().to_lowercase() == "exit" {
println("Goodbye!");
running = false;
continue;
}
// Parse input and calculate
let parse_result = parse_input(input);
match parse_result {
ok((a, op, b)) => {
let calc_result = calculate(a, op, b);
match calc_result {
ok(result) => {
println("Result: " + result.to_string());
},
err(error_msg) => {
println("Error: " + error_msg);
}
}
},
err(error_msg) => {
println("Error: " + error_msg);
}
}
println(""); // Empty line for better readability
}
}
Running the Program
To run the calculator program:
- Save the code in a file named
calculator.sr
- Open a terminal and navigate to the directory containing your file
- Compile and run the program with the following command:
shitrust run calculator.sr
You should see the welcome message, and you can start entering calculations. For example:
> 5 + 3
Result: 8
> 10 / 2
Result: 5
> 7 * 6
Result: 42
> 10 / 0
Error: Division by zero is not allowed
> exit
Goodbye!
Extensions and Challenges
Now that you've built a basic calculator, here are some ideas to extend and improve it:
- Add support for more operations (modulo, exponentiation, etc.)
- Implement memory functions (store values, recall them later)
- Support more complex expressions with multiple operations
- Add a history feature to recall previous calculations
- Implement unit conversions (temperature, length, etc.)
These extensions will give you more practice with ShitRust and help you build a more powerful calculator application.
Next Steps
Congratulations on completing your first ShitRust tutorial! You've built a functional calculator application and learned about several key features of the language.
Check out our other tutorials to continue your ShitRust journey:
Or explore the Language Reference to learn more about ShitRust's features.