Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
Pass by ref for integer (#174)
Browse files Browse the repository at this point in the history
* Initial work for integer

* Remove destructor

* Make integer to use arc
  • Loading branch information
gavrilikhin-d authored May 18, 2024
1 parent 60ed168 commit 584df80
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 139 deletions.
6 changes: 3 additions & 3 deletions ppl/src/core.ppl
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ fn <x: Integer> % <y: Integer> -> Integer
@mangle_as("integer_as_string")
fn String from <:Integer> -> String

@mangle_as("destroy_integer")
fn destroy <:&mut Integer>

@mangle_as("clone_integer")
fn clone <:&Integer> -> Integer

@mangle_as("destroy_integer")
fn destroy <:&mut Integer>
//---------------------------------

//=================================
Expand Down
167 changes: 77 additions & 90 deletions src/runtime/src/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,67 @@ use std::ffi::c_char;

use rug::ops::Pow;

use crate::{Rational, String};
use crate::{decrement_strong_count, increment_strong_count, Rational, String};

use std::sync::Arc;

/// Big integer number.
/// Wrapper around pointer to [`rug::Integer`].
///
/// # PPL
/// ```no_run
/// type IntegerImpl
///
/// @builtin
/// type Integer:
/// impl: Reference<IntegerImpl>
/// type Integer
/// ```
#[repr(C)]
pub struct Integer {
pub data: *mut rug::Integer,
pub struct Integer(pub *const rug::Integer);

impl Clone for Integer {
fn clone(&self) -> Self {
increment_strong_count(self.0 as *const _);
Self(self.0)
}
}

/// Construct [`Integer`](ppl::semantics::Type::Integer) from i32
impl Drop for Integer {
fn drop(&mut self) {
decrement_strong_count(self.0 as *const _);
}
}

impl Integer {
/// Get the inner value
pub fn as_ref(&self) -> &rug::Integer {
unsafe { &*self.0 }
}
}

impl<T> From<T> for Integer
where
rug::Integer: From<T>,
{
fn from(x: T) -> Self {
let this = Arc::new(rug::Integer::from(x));
Self(Arc::into_raw(this))
}
}

/// Construct [`Integer`] from [`i32`]
#[no_mangle]
pub extern "C" fn integer_from_i32(value: i32) -> Integer {
let boxed = Box::new(value.into());
Integer {
data: Box::into_raw(boxed),
}
integer_from_i64(value as i64)
}

/// Construct [`Integer`](ppl::semantics::Type::Integer) from i64
/// Construct [`Integer`] from [`i64`]
#[no_mangle]
pub extern "C" fn integer_from_i64(value: i64) -> Integer {
let boxed = Box::new(value.into());
Integer {
data: Box::into_raw(boxed),
}
rug::Integer::from(value).into()
}

/// Construct [`Integer`](ppl::semantics::Type::Integer) from u64
/// Construct [`Integer`] from [`u64`]
#[no_mangle]
pub extern "C" fn integer_from_u64(value: u64) -> Integer {
let boxed = Box::new(value.into());
Integer {
data: Box::into_raw(boxed),
}
rug::Integer::from(value).into()
}

/// Construct [`Integer`](ppl::semantics::Type::Integer) from a C string
Expand All @@ -54,22 +72,18 @@ pub extern "C" fn integer_from_c_string(str: *const c_char) -> Integer {

let c_str = unsafe { core::ffi::CStr::from_ptr(str) };
let str = c_str.to_str().unwrap();
let boxed = Box::new(str.parse::<rug::Integer>().unwrap());
Integer {
data: Box::into_raw(boxed),
}
str.parse::<rug::Integer>().unwrap().into()
}

/// Converts `Integer` to `String`
/// Converts [`Integer`] to [`String`]
///
/// # PPL
/// ```no_run
/// fn String from <:Integer> -> String
/// ```
#[no_mangle]
pub extern "C" fn integer_as_string(i: Integer) -> String {
let i = unsafe { i.data.as_ref().unwrap() };
let str = i.to_string();
let str = i.as_ref().to_string();
let boxed = Box::new(str);
String {
data: Box::into_raw(boxed),
Expand All @@ -78,51 +92,41 @@ pub extern "C" fn integer_as_string(i: Integer) -> String {

/// Negates integer
///
/// Runtime for builtin ppl's function:
/// ```ppl
/// # PPL
/// ```no_run
/// fn - <:Integer> -> Integer
/// ```
#[no_mangle]
pub extern "C" fn minus_integer(i: Integer) -> Integer {
let i = unsafe { i.data.as_ref().unwrap() };
let boxed = Box::new(rug::Integer::from(-i));
Integer {
data: Box::into_raw(boxed),
}
(-i.as_ref()).into()
}

/// Add 2 integers
///
/// Runtime for builtin ppl's function:
/// ```ppl
/// # PPL
/// ```no_run
/// fn <:Integer> + <:Integer> -> Integer
/// ```
#[no_mangle]
pub extern "C" fn integer_plus_integer(x: Integer, y: Integer) -> Integer {
let x = unsafe { x.data.as_ref().unwrap() };
let y = unsafe { y.data.as_ref().unwrap() };
let x = x.as_ref();
let y = y.as_ref();

let boxed = Box::new(rug::Integer::from(x + y));
Integer {
data: Box::into_raw(boxed),
}
(x + y).into()
}

/// Multiply 2 integers
///
/// Runtime for builtin ppl's function:
/// ```ppl
/// # PPL
/// ```no_run
/// fn <:Integer> * <:Integer> -> Integer
/// ```
#[no_mangle]
pub extern "C" fn integer_star_integer(x: Integer, y: Integer) -> Integer {
let x = unsafe { x.data.as_ref().unwrap() };
let y = unsafe { y.data.as_ref().unwrap() };
let x = x.as_ref();
let y = y.as_ref();

let boxed = Box::new(rug::Integer::from(x * y));
Integer {
data: Box::into_raw(boxed),
}
(x * y).into()
}

/// Divide 2 integers
Expand All @@ -133,8 +137,8 @@ pub extern "C" fn integer_star_integer(x: Integer, y: Integer) -> Integer {
/// ```
#[no_mangle]
pub extern "C" fn integer_slash_integer(x: Integer, y: Integer) -> Rational {
let x = unsafe { x.data.as_ref().unwrap() };
let y = unsafe { y.data.as_ref().unwrap() };
let x = x.as_ref();
let y = y.as_ref();

let boxed = Box::new(rug::Rational::from(x) / y);
Rational {
Expand All @@ -144,28 +148,28 @@ pub extern "C" fn integer_slash_integer(x: Integer, y: Integer) -> Rational {

/// Compare 2 integers for equality
///
/// Runtime for builtin ppl's function:
/// ```ppl
/// # PPL
/// ```no_run
/// fn <:Integer> == <:Integer> -> Bool
/// ```
#[no_mangle]
pub extern "C" fn integer_eq_integer(x: Integer, y: Integer) -> bool {
let x = unsafe { x.data.as_ref().unwrap() };
let y = unsafe { y.data.as_ref().unwrap() };
let x = x.as_ref();
let y = y.as_ref();

x == y
}

/// Is one integer less than another?
///
/// Runtime for builtin ppl's function:
/// ```ppl
/// # PPL
/// ```no_run
/// fn <:Integer> < <:Integer> -> Bool
/// ```
#[no_mangle]
pub extern "C" fn integer_less_integer(x: Integer, y: Integer) -> bool {
let x = unsafe { x.data.as_ref().unwrap() };
let y = unsafe { y.data.as_ref().unwrap() };
let x = x.as_ref();
let y = y.as_ref();

x < y
}
Expand All @@ -178,12 +182,7 @@ pub extern "C" fn integer_less_integer(x: Integer, y: Integer) -> bool {
/// ```
#[no_mangle]
pub extern "C" fn sqrt_integer(i: Integer) -> Integer {
let i = unsafe { i.data.as_ref().unwrap() };

let boxed = Box::new(i.clone().root(2));
Integer {
data: Box::into_raw(boxed),
}
i.as_ref().clone().root(2).into()
}

/// Calculate `x` in `n`th power
Expand All @@ -194,16 +193,13 @@ pub extern "C" fn sqrt_integer(i: Integer) -> Integer {
/// ```
#[no_mangle]
pub extern "C" fn integer_power_integer(x: Integer, n: Integer) -> Integer {
let x = unsafe { x.data.as_ref().unwrap() };
let n = unsafe { n.data.as_ref().unwrap() };
let x = x.as_ref();
let n = n.as_ref();

// TODO: support other powers
let res: rug::Integer = x.pow(n.to_u32().unwrap()).into();

let boxed = Box::new(res);
Integer {
data: Box::into_raw(boxed),
}
res.into()
}

/// # PPL
Expand All @@ -212,24 +208,20 @@ pub extern "C" fn integer_power_integer(x: Integer, n: Integer) -> Integer {
/// ```
#[no_mangle]
pub extern "C" fn integer_mod_integer(x: Integer, y: Integer) -> Integer {
let x = unsafe { x.data.as_ref().unwrap() };
let y = unsafe { y.data.as_ref().unwrap() };
let x = x.as_ref();
let y = y.as_ref();

let res = x.clone().modulo(y);

let boxed = Box::new(res);
Integer {
data: Box::into_raw(boxed),
}
res.into()
}

/// # PPL
/// ```no_run
/// fn destroy <:&mut Integer>
/// ```
#[no_mangle]
pub extern "C" fn destroy_integer(x: *mut Integer) {
let _ = unsafe { Box::from_raw(x.as_ref().unwrap().data) };
pub extern "C" fn destroy_integer(x: &mut Integer) {
decrement_strong_count(x.0 as *const _);
}

/// # PPL
Expand All @@ -239,10 +231,7 @@ pub extern "C" fn destroy_integer(x: *mut Integer) {
/// ```
#[no_mangle]
pub extern "C" fn clone_integer(x: &Integer) -> Integer {
let value = unsafe { x.data.as_ref() }.unwrap().clone();
Integer {
data: Box::into_raw(Box::new(value)),
}
x.clone()
}

/// # PPL
Expand Down Expand Up @@ -284,9 +273,7 @@ pub extern "C" fn i32_as_string(x: i32) -> String {
/// ```
#[no_mangle]
pub extern "C" fn integer_as_i32(x: Integer) -> i32 {
debug_assert!(!x.data.is_null());

let integer = unsafe { Box::from_raw(x.data) };
let integer = x.as_ref();
integer
.to_i32()
.expect(&format!("Integer `{integer}` is too big to fit into i32"))
Expand Down
22 changes: 17 additions & 5 deletions src/runtime/src/memory.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::sync::Arc;

use libc::{c_void, malloc, memcpy, size_t};

use crate::{integer_from_i64, integer_from_u64, Integer, String, Type};
Expand All @@ -13,7 +15,7 @@ pub struct MemoryAddress {
/// ```
#[no_mangle]
pub extern "C" fn memory_address_as_string(address: MemoryAddress) -> String {
let value = unsafe { address.value.data.as_ref().unwrap() };
let value = address.value.as_ref();

let hex = format!("0x{}", value.to_string_radix(16).to_uppercase());
let boxed = Box::new(hex);
Expand All @@ -28,7 +30,7 @@ pub extern "C" fn memory_address_as_string(address: MemoryAddress) -> String {
/// ```
#[no_mangle]
pub extern "C" fn allocate_n_bytes(n: Integer) -> MemoryAddress {
let n = unsafe { n.data.as_ref().unwrap() };
let n = n.as_ref();

let n = n.to_usize();
if n.is_none() {
Expand All @@ -51,7 +53,7 @@ pub extern "C" fn allocate_n_bytes(n: Integer) -> MemoryAddress {
/// ```
#[no_mangle]
pub extern "C" fn free_memory(address: &MemoryAddress) {
let address = unsafe { address.value.data.as_ref().unwrap() };
let address = address.value.as_ref();

let address = address.to_u64();
if address.is_none() {
Expand All @@ -74,7 +76,7 @@ pub extern "C" fn read_memory(_ty: Type, address: &MemoryAddress) -> *mut c_void
}

fn read_memory_impl(address: &MemoryAddress) -> *mut c_void {
let address = unsafe { address.value.data.as_ref().unwrap() };
let address = address.value.as_ref();

let address = address.to_u64().unwrap();

Expand Down Expand Up @@ -106,6 +108,16 @@ pub extern "C" fn address_of(ptr: *const c_void) -> MemoryAddress {
pub extern "C" fn copy_bytes(n: &Integer, src: &MemoryAddress, dst: &MemoryAddress) {
let dest = read_memory_impl(dst);
let src = read_memory_impl(src);
let n = unsafe { n.data.as_ref().unwrap() }.to_usize().unwrap() as size_t;
let n = n.as_ref().to_usize().unwrap() as size_t;
unsafe { memcpy(dest, src, n) };
}

#[no_mangle]
pub extern "C" fn increment_strong_count(ptr: *const c_void) {
unsafe { Arc::increment_strong_count(ptr) }
}

#[no_mangle]
pub extern "C" fn decrement_strong_count(ptr: *const c_void) {
unsafe { Arc::decrement_strong_count(ptr) }
}
2 changes: 1 addition & 1 deletion src/runtime/src/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::Integer;
/// ```
#[no_mangle]
pub extern "C" fn sleep_ms(ms: Integer) {
let ms = unsafe { ms.data.as_ref().unwrap() };
let ms = ms.as_ref();
let ms = ms.to_u64();
if ms.is_none() {
return;
Expand Down
Loading

0 comments on commit 584df80

Please sign in to comment.