#pragma once // all C/++ headers must be imported first #include #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 class Option { union { u8 None = 0; T Some; } value; enum variant : bool { None = 0, Some, } variant; public: makeSelf (Option); 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 fn map (U (f) (T)) -> Option { match (variant) { arm (variant::Some, return Some (f (value.Some))); arm (variant::None, return None ()); } } }; /// Constructs an Option with `variant` None /// /// Takes an optional (never-dereferenced) pointer argument, for type inference. template fn None (T *_type = (T *) (0)) -> Option { return Option::None (); } /// Constructs an option with `variant` Some template fn Some (T value) -> Option { return Option::Some (value); } } mod result { template class Result { union { T Ok; E Err; } value; enum variant { Ok, Err, } variant; public: makeSelf (Result); 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 { match (variant) { arm (variant::Ok, return option::Some (value.Ok)); arm (variant::Err, return option::None ()); } } fn err () -> option::Option { match (variant) { arm (variant::Err, return option::Some (value.Err)); arm (variant::Ok, return option::None ()); } } 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 fn Err (E error) -> Result { return Result::Err (error); } /// Constructs a Result with variant Ok and value `Ok(value)` template fn Ok (T value) -> Result { return Result::Ok (value); } } mod ptr { template struct Nonnull { T *value; makeSelf (Nonnull); static fn rustpp__new (T *value) -> option::Option { if (value) { return option::Some ((Self) { value }); } else { return option::None (); } } fn operator* ()->T & { return *value; } }; template fn nonnull (T * value) -> option::Option> { switch (value) { case nullptr: return option::Some (value); default: return option::None (&value); } } template fn nonnull_unchecked (T * value) -> Nonnull { return { value }; } } mod iter { template class Iterator { public: virtual fn next () -> option::Option = 0; // TODO: default methods for Iterator }; } mod slice { template class Iter: public iter::Iterator> { T *head; T *tail; Iter (T *head, T *tail) : head (head), tail (tail) {} public: makeSelf (Iter); static fn rustpp__new (T *head, usize len) -> Self { return { head, head + len }; } fn next () -> option::Option> override { if (head < tail) return ptr::Nonnull::rustpp__new (head++); else return option::None> (); } fn into_iter () -> Self & { return self; } }; template struct Slice { T *ptr; usize len; makeSelf (Slice); fn into_iter () -> Iter { return Iter::rustpp__new (self.ptr, self.len); } }; } mod vec { /// Drains a heap allocated array, returning elements by copy template class Drain: public iter::Iterator { 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 override { if (head < tail) { return option::Some (*head++); } if (allocation) { free (allocation); allocation = nullptr; } return option::None (); } }; template struct Vec { T *ptr; usize len; usize cap; makeSelf (Vec); 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 { use option::Some, option::None; if (len == 0) { return None (ptr); } let value = ptr[--len]; return Some (value); } fn as_slice () -> slice::Slice { return slice::Slice { ptr, len }; } fn iter () -> slice::Iter { return self.as_slice ().into_iter (); } fn into_iter () -> Drain { let drain = Drain (self.ptr, self.len); self = {}; return drain; } }; } mod env { /// Gets the environment variables fn args () -> slice::Slice; } 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;