Files
RustPP/src/include/rust.hh
T
2025-07-11 16:59:44 -04:00

387 lines
9.0 KiB
C++

#pragma once
// all C/++ headers must be imported first
#include <cstdlib>
#include "panic.hh" // IWYU pragma: export
#include "primitives.hh" // IWYU pragma: export
// keywords.hh must come last; changes language semantics with macros
#include "keywords.hh" // IWYU pragma: export
type Cstr = char *;
mod termination {
struct ExitCode {
int code;
fn return_value () -> int {
return code;
}
};
}
/** The main function: does main things */
fn rustpp__main () -> termination::ExitCode;
mod option {
template <typename T>
class Option {
union {
u8 None = 0;
T Some;
} value;
enum variant : bool {
None = 0,
Some,
} variant;
public:
makeSelf (Option<T>);
operator termination::ExitCode () {
return { (int) variant };
}
static fn Some (T value) -> Self {
Self op;
op.value.Some = value;
op.variant = variant::Some;
return op;
}
static fn None (T *_type = (T *) (0)) -> Self {
Self op;
op.value.None = 0;
op.variant = variant::None;
return op;
}
fn is_some () -> bool {
return variant == variant::Some;
}
fn is_none () -> bool {
return variant == variant::None;
}
operator bool () {
return this->is_some ();
}
fn unwrap_unchecked () -> T {
return value.Some;
}
fn unwrap () -> T {
match (variant) {
arm (variant::Some, return value.Some);
arm (variant::None, panic ("Called Option::unwrap() on a None value"));
}
}
template <typename U>
fn map (U (f) (T)) -> Option<U> {
match (variant) {
arm (variant::Some, return Some (f (value.Some)));
arm (variant::None, return None<U> ());
}
}
};
/// Constructs an Option with `variant` None
///
/// Takes an optional (never-dereferenced) pointer argument, for type inference.
template <typename T>
fn None (T *_type = (T *) (0)) -> Option<T> {
return Option<T>::None ();
}
/// Constructs an option with `variant` Some
template <typename T>
fn Some (T value) -> Option<T> {
return Option<T>::Some (value);
}
}
mod result {
template <typename T, typename E>
class Result {
union {
T Ok;
E Err;
} value;
enum variant {
Ok,
Err,
} variant;
public:
makeSelf (Result<T, E>);
operator termination::ExitCode () {
return { (int) variant };
}
// TODO: destructor for Result
static fn Ok (T value) -> Self {
Self result;
result.value.Ok = value;
result.variant = variant::Ok;
return result;
}
static fn Err (E error) -> Self {
Self result;
result.value.Err = error;
result.variant = variant::Err;
return result;
}
fn is_ok () -> bool {
return variant == variant::Ok;
}
fn is_err () -> bool {
return variant == variant::Err;
}
fn ok () -> option::Option<T> {
match (variant) {
arm (variant::Ok, return option::Some (value.Ok));
arm (variant::Err, return option::None<T> ());
}
}
fn err () -> option::Option<E> {
match (variant) {
arm (variant::Err, return option::Some (value.Err));
arm (variant::Ok, return option::None<T> ());
}
}
fn unwrap () -> T {
match (variant) {
arm (variant::Ok, return value.Ok);
arm (variant::Err, panic ("Called Result::unwrap() on Err value"));
}
}
fn unwrap_err () -> E {
match (variant) {
arm (variant::Ok, panic ("Called Result::unwrap_err() on Ok value"));
arm (variant::Err, return value.Err);
}
}
};
/// Constructs a Result with variant Err and value `Err(value)`
template <typename T, typename E>
fn Err (E error) -> Result<T, E> {
return Result<T, E>::Err (error);
}
/// Constructs a Result with variant Ok and value `Ok(value)`
template <typename T, typename E>
fn Ok (T value) -> Result<T, E> {
return Result<T, E>::Ok (value);
}
}
mod ptr {
template <typename T>
struct Nonnull {
T *value;
makeSelf (Nonnull<T>);
static fn rustpp__new (T *value) -> option::Option<Self> {
if (value) {
return option::Some ((Self) { value });
} else {
return option::None<Self> ();
}
}
fn operator* ()->T & {
return *value;
}
};
template <typename T>
fn nonnull (T * value) -> option::Option<Nonnull<T>> {
switch (value) {
case nullptr:
return option::Some (value);
default:
return option::None (&value);
}
}
template <typename T>
fn nonnull_unchecked (T * value) -> Nonnull<T> {
return { value };
}
}
mod iter {
template <typename T>
class Iterator {
public:
virtual fn next () -> option::Option<T> = 0;
// TODO: default methods for Iterator
};
}
mod slice {
template <typename T>
class Iter: public iter::Iterator<ptr::Nonnull<T>> {
T *head;
T *tail;
Iter (T *head, T *tail) : head (head), tail (tail) {}
public:
makeSelf (Iter<T>);
static fn rustpp__new (T *head, usize len) -> Self {
return { head, head + len };
}
fn next () -> option::Option<ptr::Nonnull<T>> override {
if (head < tail)
return ptr::Nonnull<T>::rustpp__new (head++);
else
return option::None<ptr::Nonnull<T>> ();
}
fn into_iter () -> Self & {
return self;
}
};
template <typename T>
struct Slice {
T *ptr;
usize len;
makeSelf (Slice<T>);
fn into_iter () -> Iter<T> {
return Iter<T>::rustpp__new (self.ptr, self.len);
}
};
}
mod vec {
/// Drains a heap allocated array, returning elements by copy
template <typename T>
class Drain: public iter::Iterator<T> {
T *allocation;
T *head;
T *tail;
public:
Drain () : allocation (nullptr), head (nullptr), tail (nullptr) {}
Drain (T *allocation, usize len) : allocation (allocation),
head (allocation),
tail (allocation + len) {}
~Drain () {
free (allocation);
}
fn next () -> option::Option<T> override {
if (head < tail) {
return option::Some (*head++);
}
if (allocation) {
free (allocation);
allocation = nullptr;
}
return option::None<T> ();
}
};
template <typename T>
struct Vec {
T *ptr;
usize len;
usize cap;
makeSelf (Vec<T>);
static fn rustpp__new () -> Self {
return {};
}
fn resize (usize cap) -> usize {
ptr = (T *) realloc ((void *) ptr, cap);
if (!ptr) {
panic ("Failed to resize Vec from {} to {}.", self.cap, cap);
}
self.cap = cap;
return self.cap;
}
fn _grow () -> usize {
switch (len) {
case 0:
return self.resize (8);
default:
return self.resize ((cap << 1) - cap);
}
}
fn drop () {
free (ptr);
self = {};
}
fn push (T value) {
self._grow ();
ptr[len++] = value;
}
fn pop () -> option::Option<T> {
use option::Some, option::None;
if (len == 0) {
return None (ptr);
}
let value = ptr[--len];
return Some (value);
}
fn as_slice () -> slice::Slice<T> {
return slice::Slice { ptr, len };
}
fn iter () -> slice::Iter<T> {
return self.as_slice ().into_iter ();
}
fn into_iter () -> Drain<T> {
let drain = Drain<T> (self.ptr, self.len);
self = {};
return drain;
}
};
}
mod env {
/// Gets the environment variables
fn args () -> slice::Slice<Cstr>;
}
mod prelude {
use slice::Slice;
use option::Option, option::Some, option::None;
use result::Result, result::Err, result::Ok;
use termination::ExitCode;
}
use mod prelude;