Hello, World!
This guide demonstrates how to execute a simple Varjus script and handle errors properly. We will start with an idealized implementation and then refine it to handle potential issues gracefully.
Input Script
Consider the following Varjus script:
fn main()
{
return 'Hello, World!';
}
The Ideal Implementation
In an ideal scenario where we assume the user writes perfect scripts, the implementation would look like this:
#include "varjus_api/varjus_api.hpp"
#include <iostream>
#include <format>
int main()
{
// Create a new state
Varjus::State state;
// Initialize the standard library (if required)
state.UseStdLibrary();
// Load the script from a file
state.LoadScriptFromFile("path/to/your/script.var");
// Alternatively, load it directly from a string
// state.LoadScript("fn main() { return 'Hello, World!'; }");
// Execute the script
const auto returnValue = state.ExecuteScript();
std::cout << std::format("The program returned: {}\n", returnValue->ToPrintableString());
return 0;
}
This code assumes the script loads without issues, has no syntax errors, and executes successfully. While simple, this version doesn’t account for the kinds of problems that can arise in real-world usage—like malformed scripts or unexpected runtime behavior—which may lead to crashes or undefined results.
The safe Implementation
To ensure robustness, we need to handle errors properly. Here’s an improved version that includes error handling:
#include "varjus_api/varjus_api.hpp"
#include <iostream>
#include <format>
int main()
{
// Create a new state
Varjus::State state;
// Utility lambda to retrieve error messages
const auto GetError = [](const std::optional<std::string>& errorMsg) {
return errorMsg.value_or("Unknown error!");
};
// Initialize the standard library
if (!state.UseStdLibrary()) {
// This is rare but indicates that the state was reused
std::cerr << std::format("State error: {}\n", GetError(state.GetErrorMessage()));
return 1;
}
// Load the script
if (!state.LoadScriptFromFile("path/to/your/script.var")) {
// This likely occurs due to syntax errors in the script
std::cerr << std::format("Syntax error: {}\n", GetError(state.GetErrorMessage()));
return 1;
}
// Execute the script
if (const auto returnValue = state.ExecuteScript()) {
// Successfully retrieved return value from main()
std::cout << std::format("The program returned: {}\n", returnValue->ToPrintableString());
} else {
// A runtime exception occurred, likely due to user error
std::cerr << std::format("Runtime error: {}\n", GetError(state.GetErrorMessage()));
return 1;
}
return 0;
}
This version introduces checks after each major step—initialization, loading, and execution—to catch problems early. It also prints detailed messages that can help pinpoint what went wrong. By handling errors explicitly, this approach avoids crashes and gives the user useful feedback.
Additional Notes
When dealing with 8- or 16-byte character strings, it’s useful to use VSL
macro for string literals and VarjusString
for strings to maintain compatibility between the two.