Add project code (mostly untested)
This commit is contained in:
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define fn auto
|
||||||
|
#define let auto
|
||||||
|
#define mod namespace
|
||||||
|
#define pub
|
||||||
|
#define self (*this)
|
||||||
|
#define self__Self (this Self & self)
|
||||||
|
#define type using
|
||||||
|
#define use using
|
||||||
|
#define enum enum class
|
||||||
|
#define match switch
|
||||||
|
#define arm(pat, ...) \
|
||||||
|
case pat: \
|
||||||
|
__VA_ARGS__; \
|
||||||
|
break
|
||||||
|
|
||||||
|
#define makeSelf(...) \
|
||||||
|
type Self = __VA_ARGS__
|
||||||
|
|
||||||
|
#define loop while (1)
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
#define RUSTPP_UNIQ__(a, b) a ## b
|
||||||
|
#define RUSTPP_UNIQ_(a, b) RUSTPP_UNIQ__(a, b)
|
||||||
|
#define RUSTPP_UNIQ(name) RUSTPP_UNIQ_(name, __LINE__)
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#define rustpp_for(value, iter) \
|
||||||
|
auto RUSTPP_UNIQ (iterator) = iter.into_iter (); \
|
||||||
|
for (auto value = RUSTPP_UNIQ (iterator).next (); value.is_some (); value = RUSTPP_UNIQ (iterator).next ())
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef I_AM_RUSTPP_RUNTIME
|
||||||
|
|
||||||
|
#define main rustpp__main
|
||||||
|
#define new __rustpp__new
|
||||||
|
|
||||||
|
#ifndef NO_RUSTPP_FOR
|
||||||
|
#define for(...) rustpp_for (__VA_ARGS__)
|
||||||
|
#endif /* NO_RUSTPP_FOR */
|
||||||
|
|
||||||
|
#endif /* I_AM_RUSTPP_RUNTIME */
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//! Unwinding panic support
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <format> // IWYU pragma: export
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace panic {
|
||||||
|
|
||||||
|
class Panic: std::exception {
|
||||||
|
public:
|
||||||
|
// std::stacktrace stack;
|
||||||
|
std::string message;
|
||||||
|
Panic (std::string message) : message (message) {
|
||||||
|
// stack = std::stacktrace::current();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char *what () {
|
||||||
|
return message.c_str ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace panic
|
||||||
|
|
||||||
|
|
||||||
|
#define panic(...) \
|
||||||
|
do { \
|
||||||
|
throw panic::Panic { std::format (__VA_ARGS__) }; \
|
||||||
|
} while (false)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
using u8 = uint8_t;
|
||||||
|
using i8 = int8_t;
|
||||||
|
|
||||||
|
using u16 = uint16_t;
|
||||||
|
using i16 = int16_t;
|
||||||
|
|
||||||
|
using u32 = uint32_t;
|
||||||
|
using i32 = int32_t;
|
||||||
|
|
||||||
|
using u64 = uint64_t;
|
||||||
|
using i64 = int64_t;
|
||||||
|
|
||||||
|
using usize = size_t;
|
||||||
|
using isize = ssize_t;
|
||||||
|
|
||||||
|
using f32 = float;
|
||||||
|
using f64 = double;
|
||||||
@@ -0,0 +1,350 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <print> // IWYU pragma: export
|
||||||
|
|
||||||
|
#include "panic.hh" // IWYU pragma: export
|
||||||
|
#include "primitives.hh" // IWYU pragma: export
|
||||||
|
|
||||||
|
// no reorder
|
||||||
|
#include "keywords.hh" // IWYU pragma: export
|
||||||
|
|
||||||
|
type Cstr = char *;
|
||||||
|
|
||||||
|
/** The main function: does main things */
|
||||||
|
fn rustpp__main () -> i32;
|
||||||
|
|
||||||
|
mod termination {
|
||||||
|
class Termination {
|
||||||
|
fn return_value () -> int {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
mod option {
|
||||||
|
template <typename T>
|
||||||
|
class Option: termination::Termination {
|
||||||
|
union {
|
||||||
|
u8 None = 0;
|
||||||
|
T Some;
|
||||||
|
} value;
|
||||||
|
enum variant : bool {
|
||||||
|
None = 0,
|
||||||
|
Some,
|
||||||
|
} variant;
|
||||||
|
|
||||||
|
public:
|
||||||
|
makeSelf (Option<T>);
|
||||||
|
|
||||||
|
pub static fn Some (T value) -> Self {
|
||||||
|
Self op;
|
||||||
|
op.value.Some = value;
|
||||||
|
op.variant = variant::Some;
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static fn None (T *_type = (T *) (0)) -> Self {
|
||||||
|
Self op;
|
||||||
|
op.value.None = 0;
|
||||||
|
op.variant = variant::None;
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_value () -> int {
|
||||||
|
return self.is_some ();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_some () -> bool {
|
||||||
|
return variant == variant::Some;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_none () -> bool {
|
||||||
|
return variant == variant::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub operator bool () {
|
||||||
|
return this->is_some ();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub 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>
|
||||||
|
pub 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>);
|
||||||
|
|
||||||
|
// TODO: destructor for Result
|
||||||
|
|
||||||
|
pub static fn Ok (T value) -> Self {
|
||||||
|
Self result;
|
||||||
|
result.value.Ok = value;
|
||||||
|
result.variant = variant::Ok;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static fn Err (E error) -> Self {
|
||||||
|
Self result;
|
||||||
|
result.value.Err = error;
|
||||||
|
result.variant = variant::Err;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_ok () -> bool {
|
||||||
|
return variant == variant::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_err () -> bool {
|
||||||
|
return variant == variant::Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unwrap () -> T {
|
||||||
|
match (variant) {
|
||||||
|
arm (variant::Ok, return value.Ok);
|
||||||
|
arm (variant::Err, panic ("Called Result::unwrap() on Err value"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unwrap_err () -> E {
|
||||||
|
match (variant) {
|
||||||
|
arm (variant::Ok, panic ("Called Result::unwrap_err() on Ok value"));
|
||||||
|
arm (variant::Err, return value.Err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
mod ptr {
|
||||||
|
template <typename T>
|
||||||
|
struct Nonnull {
|
||||||
|
T *value;
|
||||||
|
makeSelf (Nonnull<T>);
|
||||||
|
|
||||||
|
pub static fn __rustpp__new (T *value) -> option::Option<Self> {
|
||||||
|
switch (value) {
|
||||||
|
case nullptr:
|
||||||
|
return option::Some ({ value });
|
||||||
|
default:
|
||||||
|
return option::None (&value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<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<T *> override {
|
||||||
|
if (head < tail)
|
||||||
|
return option::Some (head++);
|
||||||
|
else
|
||||||
|
return option::None<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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
using mod prelude;
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
#include <print>
|
||||||
|
|
||||||
|
#include "rust.hh"
|
||||||
|
|
||||||
|
fn main () -> i32 {
|
||||||
|
let v = vec::Vec<i32>::new ();
|
||||||
|
|
||||||
|
v.push (10);
|
||||||
|
v.push (20);
|
||||||
|
v.push (30);
|
||||||
|
|
||||||
|
std::println("Printing contents of v");
|
||||||
|
for (x, v) {
|
||||||
|
std::println ("{}", x.unwrap ());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is okay, because the previous for loop moved out of v
|
||||||
|
// leaving it default-initialized.
|
||||||
|
std::println("Printing contents of v");
|
||||||
|
for (x, v) {
|
||||||
|
std::println ("{}", x.unwrap ());
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
#include "panic.hh"
|
||||||
|
#define I_AM_RUSTPP_RUNTIME
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
#include "rust.hh"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
slice::Slice<Cstr> program_args = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main (int argc, char **argv) -> int {
|
||||||
|
program_args = { (Cstr *) argv, (usize) argc };
|
||||||
|
try {
|
||||||
|
return rustpp__main ();
|
||||||
|
} catch (panic::Panic p) {
|
||||||
|
std::println ("Thread exited with explicit panic: {}", p.what ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Environment
|
||||||
|
namespace env {
|
||||||
|
fn args () -> slice::Slice<Cstr> {
|
||||||
|
return program_args;
|
||||||
|
}
|
||||||
|
} // namespace env
|
||||||
Reference in New Issue
Block a user