#![feature(pointer_methods)]
extern crate emojicode_sys;
pub use emojicode_sys::*;
use std::ffi::{CStr, CString};
use std::ptr;
#[macro_export]
macro_rules! package_version {
($maj:expr, $min:expr) => {
#[no_mangle]
#[allow(non_upper_case_globals)]
pub static version: Emojicode_PackageVersion = Emojicode_PackageVersion { major: $maj, minor: $min };
};
}
#[macro_export]
macro_rules! emoji_functions {
(
$($name:ident ($t:ident) $b:block),+
) => {
$(
unsafe extern "C" fn $name($t : *mut Emojicode_Thread) $b
)+
linking_table!($($name),+);
}
}
#[macro_export]
macro_rules! prepare_class {
(($arg1:ident, $arg2:ident) $b:block) => {
#[no_mangle]
#[allow(unused_variables)]
pub unsafe extern "C" fn prepareClass($arg1: *mut Emojicode_Class, $arg2: EmojicodeChar) $b
}
}
#[macro_export]
macro_rules! linking_table {
($($idents:ident),+) => {
#[no_mangle]
#[allow(non_upper_case_globals)]
pub static linkingTable: [Emojicode_FunctionFunctionPointer; count_args_space!($($idents)*) +1] = [None, $(Some($idents)),+];
}
}
#[macro_export]
macro_rules! count_args_space {
($name:ident) => { 1 };
($first:ident $($rest:ident) *) => {
1 + count_args_space!($($rest) *)
}
}
pub trait ToValue {
fn to_value(self) -> Option<Emojicode_Value>;
}
pub trait FromValue<T> {
fn from_value(self) -> T;
}
impl FromValue<String> for Emojicode_Value {
fn from_value(self) -> String {
unsafe {
let obj_ptr = &emojicode_sys::Emojicode_stringToCString(
self.object
);
CStr::from_ptr(*obj_ptr).to_string_lossy().into_owned()
}
}
}
impl ToValue for String {
fn to_value(self) -> Option<Emojicode_Value> {
let the_string = CString::new(self);
match the_string {
Ok(c) => unsafe {
Some(Emojicode_Value {
object: Emojicode_stringFromChar(c.as_ptr()),
})
},
Err(_) => None,
}
}
}
impl ToValue for *mut Emojicode_Object {
fn to_value(self) -> Option<Emojicode_Value> {
Some(Emojicode_Value { object: self })
}
}
pub trait EmojicodeThreadImpl {
unsafe fn return_from_function(self);
unsafe fn return_from_function_with_value(self, value: Emojicode_Value);
unsafe fn variable(self, index: usize) -> Emojicode_Value;
unsafe fn this_object(self) -> *mut Emojicode_Object;
}
impl EmojicodeThreadImpl for *mut Emojicode_Thread {
unsafe fn return_from_function(self) {
let p: *mut u32 = ptr::null_mut();
(*(*self).stack_).executionPointer = p;
}
unsafe fn return_from_function_with_value(self, value: Emojicode_Value) {
*(*(*self).stack_).destination = value;
self.return_from_function();
}
unsafe fn variable(self, index: usize) -> Emojicode_Value {
let pt: *const Emojicode_Value = &(*(*self).stack_).thisContext;
*pt.add(index + 1) as Emojicode_Value
}
unsafe fn this_object(self) -> *mut Emojicode_Object {
(*(*self).stack_).thisContext.object
}
}
pub trait EmojicodeObjectImpl {
unsafe fn value<T>(self) -> *mut T;
}
impl EmojicodeObjectImpl for *mut Emojicode_Object {
unsafe fn value<T>(self) -> *mut T {
self.add(1) as *mut T
}
}