diff --git a/stdlib/ffi.cl b/stdlib/ffi.cl new file mode 100644 index 0000000..3766a5c --- /dev/null +++ b/stdlib/ffi.cl @@ -0,0 +1,34 @@ +//! Conlang FFI +use super::preamble::*; + +type void = (); + +#[extern("C")] +/// void free(void *_Nullable ptr); +/// +/// Frees a block of memory previously allocated with `malloc` +fn free(ptr: *void); + +#[extern("C")] +/// void *malloc(size_t size); +/// +/// Allocates a block of uninitialized memory +fn malloc(size: usize) -> *void; + +#[extern("C")] +/// void *calloc(size_t n, size_t size); +/// +/// Allocates a block of zero-initialized memory +fn calloc(n: usize, size: usize); + +#[extern("C")] +/// void *realloc(void *_Nullable ptr, size_t size); +/// +/// Reallocates a block of memory to fit `size` bytes +fn realloc(ptr: *void, size: usize) -> *void; + +#[extern("C")] +/// void *reallocarray(void *_Nullable ptr, size_t n, size_t size); +/// +/// Reallocates a block of memory to fit `n` elements of `size` bytes. +fn reallocarray(ptr: *void, n: usize, size: usize) -> *void; diff --git a/stdlib/std.cl b/stdlib/std.cl index 4596234..111c2e0 100644 --- a/stdlib/std.cl +++ b/stdlib/std.cl @@ -2,14 +2,19 @@ pub mod preamble { pub use super::{ + io::*, num::*, option::Option, range::{RangeExc, RangeInc}, result::Result, - str::str, + str::*, }; } +pub mod ffi; + +pub mod io; + pub mod num; pub mod str; @@ -20,5 +25,5 @@ pub mod result; pub mod range; -#[cfg("test")] -mod test; +// #[cfg("test")] +// mod test; diff --git a/stdlib/std/io.cl b/stdlib/std/io.cl new file mode 100644 index 0000000..3ed524e --- /dev/null +++ b/stdlib/std/io.cl @@ -0,0 +1,19 @@ +//! The IO module contains functions for interacting with +//! input and output streams +use super::str::str; + +/// Immediately causes program execution to stop +#[builtin = "panic"] +fn panic(..args) -> !; + +/// Prints whatever you give it +#[builtin = "print"] +fn print(..args); + +/// Prints whatever you give it, followed by a newline +#[builtin = "println"] +fn println(..args); + +/// Debug-prints a thing, returning it +#[builtin = "dbg"] +fn dbg(arg) -> _ arg diff --git a/stdlib/std/num.cl b/stdlib/std/num.cl index c1e9273..b9b0b6e 100644 --- a/stdlib/std/num.cl +++ b/stdlib/std/num.cl @@ -278,9 +278,9 @@ pub mod ops { } impl usize { - pub const MIN: Self = (); // __march_ptr_width_unsigned_min(); // TODO: intrinsics - pub const MAX: Self = (); // __march_ptr_width_unsigned_max(); // TODO: intrinsics - pub const BIT_WIDTH: u32 = (); // __march_ptr_width_bits(); // TODO: intrinsics + pub const MIN: Self = u64::MIN as usize; // __march_ptr_width_unsigned_min(); // TODO: intrinsics + pub const MAX: Self = u64::MAX as usize; // __march_ptr_width_unsigned_max(); // TODO: intrinsics + pub const BIT_WIDTH: u32 = u64::BIT_WIDTH; // __march_ptr_width_bits(); // TODO: intrinsics pub fn default() -> Self { 0 } @@ -512,9 +512,9 @@ pub mod ops { } impl isize { - pub const MIN: Self = (); // __march_ptr_width_signed_min(); // TODO: intrinsics - pub const MAX: Self = (); // __march_ptr_width_signed_max(); // TODO: intrinsics - pub const BIT_WIDTH: u32 = (); // __march_ptr_width_bits(); // TODO: intrinsics + pub const MIN: Self = i64::MIN as isize; // __march_ptr_width_signed_min(); // TODO: intrinsics + pub const MAX: Self = i64::MAX as isize; // __march_ptr_width_signed_max(); // TODO: intrinsics + pub const BIT_WIDTH: u32 = i64::BIT_WIDTH; // __march_ptr_width_bits(); // TODO: intrinsics pub fn default() -> Self { 0 } diff --git a/stdlib/std/option.cl b/stdlib/std/option.cl index e36458f..bb976c2 100644 --- a/stdlib/std/option.cl +++ b/stdlib/std/option.cl @@ -6,24 +6,31 @@ pub enum Option { None, } -impl Option { - pub fn is_some(self: &Self) -> bool { - match self { - Some(_) => true, - None => false, - } - } - pub fn is_none(self: &Self) -> bool { - match self { - Some(_) => false, - None => true, - } - } - /// Maps from one option space to another +impl Option { + // pub fn is_some(self) -> bool { + // match self { + // Option::Some(_) => true, + // Option::None() => false, + // } + // } + // pub fn is_none(self: &Self) -> bool { + // match self { + // Option::Some(_) => false, + // Option::None() => true, + // } + // } + // /// Maps from one option space to another // pub fn map(self: Self, f: fn(T) -> U) -> Option { // match self { - // Some(value) => Some(f(value)), - // None => None, + // Option::Some(value) => Option::Some(f(value)), + // Option::None() => Option::None(), + // } + // } + + // pub fn and_then(self: Self, f: fn(T) -> Option) -> Option { + // match self { + // Option::Some(value) => f(value), + // Option::None() => Option::None(), // } // } } diff --git a/stdlib/std/range.cl b/stdlib/std/range.cl index 90b57aa..a0a2d1a 100644 --- a/stdlib/std/range.cl +++ b/stdlib/std/range.cl @@ -1,15 +1,17 @@ //! Iterable ranges /// An Exclusive Range `a .. b` iterates from a to b, excluding b -// #[lang = "range_exc"] +#[lang = "range_exc"] pub struct RangeExc(T, T) /// An Inclusive Range `a ..= b` iterates from a to b, including b -// #[lang = "range_inc"] +#[lang = "range_inc"] pub struct RangeInc(T, T) -impl RangeExc { - fn next(this: &RangeExc) -> T { - (*this).0 - } +impl RangeExc { + // fn next(self: &Self) -> T { + // let out = (*self.0); + // (*self).0 += 1; + // out + // } } diff --git a/stdlib/std/result.cl b/stdlib/std/result.cl index 2275ff7..f5862ae 100644 --- a/stdlib/std/result.cl +++ b/stdlib/std/result.cl @@ -6,29 +6,29 @@ pub enum Result { Err(E), } -impl Result { - pub fn is_ok(&self) -> bool { - match self { - Ok(_) => true, - Err(_) => false, - } - } - pub fn is_err(&self) -> bool { - match self { - Ok(_) => false, - Err(_) => true, - } - } - /// Maps the value inside the Result::Ok, leaving errors alone. - // pub fn map(self, f: fn(T) -> U) -> Result { - // match self { +impl Result { + // pub fn is_ok(self: &Self) -> bool { + // match *self { + // Ok(_) => true, + // Err(_) => false, + // } + // } + // pub fn is_err(self: &Self) -> bool { + // match *self { + // Ok(_) => false, + // Err(_) => true, + // } + // } + // /// Maps the value inside the Result::Ok, leaving errors alone. + // pub fn map(self: &Self, f: fn(T) -> U) -> Result { + // match *self { // Ok(t) => Ok(f(t)), // Err(e) => Err(e), // } // } - /// Maps the value inside the Result::Err, leaving values alone. - // pub fn map_err(self, f: fn(E) -> F) -> Result { - // match self { + // /// Maps the value inside the Result::Err, leaving values alone. + // pub fn map_err(self: &Self, f: fn(E) -> F) -> Result { + // match *self { // Ok(t) => Ok(t), // Err(e) => Err(f(e)), // } diff --git a/stdlib/std/str.cl b/stdlib/std/str.cl index 4f42327..3dd81c7 100644 --- a/stdlib/std/str.cl +++ b/stdlib/std/str.cl @@ -1,5 +1,11 @@ //! TODO: give conland a string type -use super::num::u8; +use super::num::{char, u8}; -// #[lang = "str"] +#[lang = "str"] type str = [u8]; + +#[builtin = "chars"] +fn chars(s: &str) -> [char]; + +#[builtin = "fmt"] +fn fmt(..args) -> &str; diff --git a/stdlib/std/test.cl b/stdlib/std/test.cl index be5652f..2863e42 100644 --- a/stdlib/std/test.cl +++ b/stdlib/std/test.cl @@ -32,12 +32,13 @@ fn noop () -> bool { } else break loop if false { - } else break true; + } else break true } fn while_else() -> i32 { + let (conditional, pass, fail) = (true, 10, 100 as i32); while conditional { - pass + pass; } else { fail } @@ -66,7 +67,7 @@ fn if_else() -> i32 { mod horrible_imports { mod foo { use super::{bar::*, baz::*}; - struct Foo(&Foo, &Bar) + struct Foo(&Bar, &Baz) } mod bar { use super::{foo::*, baz::*};