diff --git a/src/include/keywords.hh b/src/include/keywords.hh index 41eea1a..d147b5a 100644 --- a/src/include/keywords.hh +++ b/src/include/keywords.hh @@ -26,15 +26,17 @@ #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 ()) +#define rustpp_for(value, iter) \ + if (auto RUSTPP_UNIQ (iterator) = iter.into_iter (); auto RUSTPP_UNIQ (opt) = RUSTPP_UNIQ (iterator).next ()) \ + for (auto value = RUSTPP_UNIQ (opt).unwrap_unchecked (); \ + RUSTPP_UNIQ (opt).is_some (); \ + RUSTPP_UNIQ (opt) = RUSTPP_UNIQ (iterator).next (), value = RUSTPP_UNIQ (opt).unwrap_unchecked ()) #ifndef I_AM_RUSTPP_RUNTIME #define main rustpp__main -#define new __rustpp__new +#define new rustpp__new #ifndef NO_RUSTPP_FOR #define for(...) rustpp_for (__VA_ARGS__) diff --git a/src/include/primitives.hh b/src/include/primitives.hh index 3b114ba..bacff7e 100644 --- a/src/include/primitives.hh +++ b/src/include/primitives.hh @@ -1,3 +1,5 @@ +//! Rusty primitive types + #pragma once #include #include diff --git a/src/include/rust.hh b/src/include/rust.hh index edf1aa4..c7f3fd9 100644 --- a/src/include/rust.hh +++ b/src/include/rust.hh @@ -1,12 +1,12 @@ #pragma once +// all C/++ headers must be imported first #include -#include // IWYU pragma: export #include "panic.hh" // IWYU pragma: export #include "primitives.hh" // IWYU pragma: export -// no reorder +// keywords.hh must come last; changes language semantics with macros #include "keywords.hh" // IWYU pragma: export type Cstr = char *; @@ -37,37 +37,41 @@ mod option { public: makeSelf (Option); - pub static fn Some (T value) -> Self { + 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 { + 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 { + fn return_value () -> int { return self.is_some (); } - pub fn is_some () -> bool { + fn is_some () -> bool { return variant == variant::Some; } - pub fn is_none () -> bool { + fn is_none () -> bool { return variant == variant::None; } - pub operator bool () { + operator bool () { return this->is_some (); } - pub fn unwrap () -> T { + 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")); @@ -75,7 +79,7 @@ mod option { } template - pub fn map (U (f) (T)) -> Option { + fn map (U (f) (T)) -> Option { match (variant) { arm (variant::Some, return Some (f (value.Some))); arm (variant::None, return None ()); @@ -115,42 +119,68 @@ mod result { // TODO: destructor for Result - pub static fn Ok (T value) -> Self { + 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 { + static fn Err (E error) -> Self { Self result; result.value.Err = error; result.variant = variant::Err; return result; } - pub fn is_ok () -> bool { + fn is_ok () -> bool { return variant == variant::Ok; } - pub fn is_err () -> bool { + fn is_err () -> bool { return variant == variant::Err; } - pub fn unwrap () -> T { + 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")); } } - pub fn unwrap_err () -> E { + 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 { @@ -159,12 +189,11 @@ mod ptr { T *value; makeSelf (Nonnull); - pub static fn __rustpp__new (T *value) -> option::Option { - switch (value) { - case nullptr: - return option::Some ({ value }); - default: - return option::None (&value); + static fn rustpp__new (T *value) -> option::Option { + if (value) { + return option::Some ((Self) { value }); + } else { + return option::None (); } } @@ -200,7 +229,7 @@ mod iter { mod slice { template - class Iter: public iter::Iterator { + class Iter: public iter::Iterator> { T *head; T *tail; @@ -209,15 +238,15 @@ mod slice { public: makeSelf (Iter); - static fn __rustpp__new (T *head, usize len) -> Self { + static fn rustpp__new (T *head, usize len) -> Self { return { head, head + len }; } - fn next () -> option::Option override { + fn next () -> option::Option> override { if (head < tail) - return option::Some (head++); + return ptr::Nonnull::rustpp__new (head++); else - return option::None (); + return option::None> (); } fn into_iter () -> Self & { @@ -232,7 +261,7 @@ mod slice { makeSelf (Slice); fn into_iter () -> Iter { - return Iter::__rustpp__new (self.ptr, self.len); + return Iter::rustpp__new (self.ptr, self.len); } }; } @@ -260,7 +289,7 @@ mod vec { return option::Some (*head++); } if (allocation) { - free(allocation); + free (allocation); allocation = nullptr; } return option::None (); @@ -276,7 +305,7 @@ mod vec { makeSelf (Vec); - static fn __rustpp__new () -> Self { + static fn rustpp__new () -> Self { return {}; } @@ -347,4 +376,4 @@ mod prelude { } -using mod prelude; +use mod prelude; diff --git a/src/main.cc b/src/main.cc index 8f0b079..0ab0454 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,5 +1,6 @@ #include +// rust.hh changes language semantics, so must be included last! #include "rust.hh" fn main () -> i32 { @@ -9,16 +10,15 @@ fn main () -> i32 { v.push (20); v.push (30); - std::println("Printing contents of v"); - for (x, v) { - std::println ("{}", x.unwrap ()); + std::println ("Printing contents of v by reference"); + for (x, v.iter ()) { + std::println ("{}", *x); } - // This is okay, because the previous for loop moved out of v - // leaving it default-initialized. - std::println("Printing contents of v"); + // This is okay, because the previous for loop borrowed v + std::println ("Printing contents of v by value"); for (x, v) { - std::println ("{}", x.unwrap ()); + std::println ("{}", x); } return 0;