Skip to main content

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;
}

Issues with This Approach

This implementation assumes that:

  • The script always loads correctly.
  • There are no syntax errors.
  • Execution never fails.

However, in real-world scenarios, scripts might contain syntax errors, runtime exceptions, or other issues. The above implementation does not handle these cases, leading to undefined behavior or crashes.

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;
}

Key Improvements

  • Error Handling: Checks for errors at each step and prevents execution if issues occur.
  • Informative Error Messages: Prints relevant messages to help diagnose problems.
  • State Safety: Ensures the state is correctly initialized before use.

Additional Notes

  • Consider using VSL (string literals) and VarjusString (std::(u16)string) when working with 8/16 byte characters.
  • Always validate return values to prevent undefined behavior.
  • By following these best practices, you ensure your Varjus script execution is both reliable and maintainable.