diff --git a/ppl/src/core.ppl b/ppl/src/core.ppl index 59808420..9966c638 100644 --- a/ppl/src/core.ppl +++ b/ppl/src/core.ppl @@ -112,11 +112,11 @@ fn % -> Integer @mangle_as("integer_as_string") fn String from <:Integer> -> String -@mangle_as("clone_integer") -fn clone <:&Integer> -> Integer - @mangle_as("destroy_integer") fn destroy <:&mut Integer> + +@mangle_as("clone_integer") +fn clone <:&Integer> -> Integer //--------------------------------- //================================= diff --git a/src/runtime/src/integer.rs b/src/runtime/src/integer.rs index d6914379..0e4e60af 100644 --- a/src/runtime/src/integer.rs +++ b/src/runtime/src/integer.rs @@ -2,67 +2,49 @@ use std::ffi::c_char; use rug::ops::Pow; -use crate::{decrement_strong_count, increment_strong_count, Rational, String}; - -use std::sync::Arc; +use crate::{Rational, String}; /// Big integer number. /// Wrapper around pointer to [`rug::Integer`]. /// /// # PPL /// ```no_run +/// type IntegerImpl +/// /// @builtin -/// type Integer +/// type Integer: +/// impl: Reference /// ``` #[repr(C)] -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) - } +pub struct Integer { + pub data: *mut rug::Integer, } -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 From for Integer -where - rug::Integer: From, -{ - fn from(x: T) -> Self { - let this = Arc::new(rug::Integer::from(x)); - Self(Arc::into_raw(this)) - } -} - -/// Construct [`Integer`] from [`i32`] +/// Construct [`Integer`](ppl::semantics::Type::Integer) from i32 #[no_mangle] pub extern "C" fn integer_from_i32(value: i32) -> Integer { - integer_from_i64(value as i64) + let boxed = Box::new(value.into()); + Integer { + data: Box::into_raw(boxed), + } } -/// Construct [`Integer`] from [`i64`] +/// Construct [`Integer`](ppl::semantics::Type::Integer) from i64 #[no_mangle] pub extern "C" fn integer_from_i64(value: i64) -> Integer { - rug::Integer::from(value).into() + let boxed = Box::new(value.into()); + Integer { + data: Box::into_raw(boxed), + } } -/// Construct [`Integer`] from [`u64`] +/// Construct [`Integer`](ppl::semantics::Type::Integer) from u64 #[no_mangle] pub extern "C" fn integer_from_u64(value: u64) -> Integer { - rug::Integer::from(value).into() + let boxed = Box::new(value.into()); + Integer { + data: Box::into_raw(boxed), + } } /// Construct [`Integer`](ppl::semantics::Type::Integer) from a C string @@ -72,10 +54,13 @@ 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(); - str.parse::().unwrap().into() + let boxed = Box::new(str.parse::().unwrap()); + Integer { + data: Box::into_raw(boxed), + } } -/// Converts [`Integer`] to [`String`] +/// Converts `Integer` to `String` /// /// # PPL /// ```no_run @@ -83,7 +68,8 @@ pub extern "C" fn integer_from_c_string(str: *const c_char) -> Integer { /// ``` #[no_mangle] pub extern "C" fn integer_as_string(i: Integer) -> String { - let str = i.as_ref().to_string(); + let i = unsafe { i.data.as_ref().unwrap() }; + let str = i.to_string(); let boxed = Box::new(str); String { data: Box::into_raw(boxed), @@ -92,41 +78,51 @@ pub extern "C" fn integer_as_string(i: Integer) -> String { /// Negates integer /// -/// # PPL -/// ```no_run +/// Runtime for builtin ppl's function: +/// ```ppl /// fn - <:Integer> -> Integer /// ``` #[no_mangle] pub extern "C" fn minus_integer(i: Integer) -> Integer { - (-i.as_ref()).into() + let i = unsafe { i.data.as_ref().unwrap() }; + let boxed = Box::new(rug::Integer::from(-i)); + Integer { + data: Box::into_raw(boxed), + } } /// Add 2 integers /// -/// # PPL -/// ```no_run +/// Runtime for builtin ppl's function: +/// ```ppl /// fn <:Integer> + <:Integer> -> Integer /// ``` #[no_mangle] pub extern "C" fn integer_plus_integer(x: Integer, y: Integer) -> Integer { - let x = x.as_ref(); - let y = y.as_ref(); + let x = unsafe { x.data.as_ref().unwrap() }; + let y = unsafe { y.data.as_ref().unwrap() }; - (x + y).into() + let boxed = Box::new(rug::Integer::from(x + y)); + Integer { + data: Box::into_raw(boxed), + } } /// Multiply 2 integers /// -/// # PPL -/// ```no_run +/// Runtime for builtin ppl's function: +/// ```ppl /// fn <:Integer> * <:Integer> -> Integer /// ``` #[no_mangle] pub extern "C" fn integer_star_integer(x: Integer, y: Integer) -> Integer { - let x = x.as_ref(); - let y = y.as_ref(); + let x = unsafe { x.data.as_ref().unwrap() }; + let y = unsafe { y.data.as_ref().unwrap() }; - (x * y).into() + let boxed = Box::new(rug::Integer::from(x * y)); + Integer { + data: Box::into_raw(boxed), + } } /// Divide 2 integers @@ -137,8 +133,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 = x.as_ref(); - let y = y.as_ref(); + let x = unsafe { x.data.as_ref().unwrap() }; + let y = unsafe { y.data.as_ref().unwrap() }; let boxed = Box::new(rug::Rational::from(x) / y); Rational { @@ -148,28 +144,28 @@ pub extern "C" fn integer_slash_integer(x: Integer, y: Integer) -> Rational { /// Compare 2 integers for equality /// -/// # PPL -/// ```no_run +/// Runtime for builtin ppl's function: +/// ```ppl /// fn <:Integer> == <:Integer> -> Bool /// ``` #[no_mangle] pub extern "C" fn integer_eq_integer(x: Integer, y: Integer) -> bool { - let x = x.as_ref(); - let y = y.as_ref(); + let x = unsafe { x.data.as_ref().unwrap() }; + let y = unsafe { y.data.as_ref().unwrap() }; x == y } /// Is one integer less than another? /// -/// # PPL -/// ```no_run +/// Runtime for builtin ppl's function: +/// ```ppl /// fn <:Integer> < <:Integer> -> Bool /// ``` #[no_mangle] pub extern "C" fn integer_less_integer(x: Integer, y: Integer) -> bool { - let x = x.as_ref(); - let y = y.as_ref(); + let x = unsafe { x.data.as_ref().unwrap() }; + let y = unsafe { y.data.as_ref().unwrap() }; x < y } @@ -182,7 +178,12 @@ pub extern "C" fn integer_less_integer(x: Integer, y: Integer) -> bool { /// ``` #[no_mangle] pub extern "C" fn sqrt_integer(i: Integer) -> Integer { - i.as_ref().clone().root(2).into() + let i = unsafe { i.data.as_ref().unwrap() }; + + let boxed = Box::new(i.clone().root(2)); + Integer { + data: Box::into_raw(boxed), + } } /// Calculate `x` in `n`th power @@ -193,13 +194,16 @@ 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 = x.as_ref(); - let n = n.as_ref(); + let x = unsafe { x.data.as_ref().unwrap() }; + let n = unsafe { n.data.as_ref().unwrap() }; // TODO: support other powers let res: rug::Integer = x.pow(n.to_u32().unwrap()).into(); - res.into() + let boxed = Box::new(res); + Integer { + data: Box::into_raw(boxed), + } } /// # PPL @@ -208,11 +212,15 @@ 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 = x.as_ref(); - let y = y.as_ref(); + let x = unsafe { x.data.as_ref().unwrap() }; + let y = unsafe { y.data.as_ref().unwrap() }; let res = x.clone().modulo(y); - res.into() + + let boxed = Box::new(res); + Integer { + data: Box::into_raw(boxed), + } } /// # PPL @@ -220,8 +228,8 @@ pub extern "C" fn integer_mod_integer(x: Integer, y: Integer) -> Integer { /// fn destroy <:&mut Integer> /// ``` #[no_mangle] -pub extern "C" fn destroy_integer(x: &mut Integer) { - decrement_strong_count(x.0 as *const _); +pub extern "C" fn destroy_integer(x: *mut Integer) { + let _ = unsafe { Box::from_raw(x.as_ref().unwrap().data) }; } /// # PPL @@ -231,7 +239,10 @@ pub extern "C" fn destroy_integer(x: &mut Integer) { /// ``` #[no_mangle] pub extern "C" fn clone_integer(x: &Integer) -> Integer { - x.clone() + let value = unsafe { x.data.as_ref() }.unwrap().clone(); + Integer { + data: Box::into_raw(Box::new(value)), + } } /// # PPL @@ -273,7 +284,9 @@ pub extern "C" fn i32_as_string(x: i32) -> String { /// ``` #[no_mangle] pub extern "C" fn integer_as_i32(x: Integer) -> i32 { - let integer = x.as_ref(); + debug_assert!(!x.data.is_null()); + + let integer = unsafe { Box::from_raw(x.data) }; integer .to_i32() .expect(&format!("Integer `{integer}` is too big to fit into i32")) diff --git a/src/runtime/src/memory.rs b/src/runtime/src/memory.rs index 5708f434..6a6f1a6e 100644 --- a/src/runtime/src/memory.rs +++ b/src/runtime/src/memory.rs @@ -1,5 +1,3 @@ -use std::sync::Arc; - use libc::{c_void, malloc, memcpy, size_t}; use crate::{integer_from_i64, integer_from_u64, Integer, String, Type}; @@ -15,7 +13,7 @@ pub struct MemoryAddress { /// ``` #[no_mangle] pub extern "C" fn memory_address_as_string(address: MemoryAddress) -> String { - let value = address.value.as_ref(); + let value = unsafe { address.value.data.as_ref().unwrap() }; let hex = format!("0x{}", value.to_string_radix(16).to_uppercase()); let boxed = Box::new(hex); @@ -30,7 +28,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 = n.as_ref(); + let n = unsafe { n.data.as_ref().unwrap() }; let n = n.to_usize(); if n.is_none() { @@ -53,7 +51,7 @@ pub extern "C" fn allocate_n_bytes(n: Integer) -> MemoryAddress { /// ``` #[no_mangle] pub extern "C" fn free_memory(address: &MemoryAddress) { - let address = address.value.as_ref(); + let address = unsafe { address.value.data.as_ref().unwrap() }; let address = address.to_u64(); if address.is_none() { @@ -76,7 +74,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 = address.value.as_ref(); + let address = unsafe { address.value.data.as_ref().unwrap() }; let address = address.to_u64().unwrap(); @@ -108,16 +106,6 @@ 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 = n.as_ref().to_usize().unwrap() as size_t; + let n = unsafe { n.data.as_ref().unwrap() }.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) } -} diff --git a/src/runtime/src/thread.rs b/src/runtime/src/thread.rs index f122c1be..3129eda0 100644 --- a/src/runtime/src/thread.rs +++ b/src/runtime/src/thread.rs @@ -8,7 +8,7 @@ use crate::Integer; /// ``` #[no_mangle] pub extern "C" fn sleep_ms(ms: Integer) { - let ms = ms.as_ref(); + let ms = unsafe { ms.data.as_ref().unwrap() }; let ms = ms.to_u64(); if ms.is_none() { return; diff --git a/src/tests/clone/src/main.ppl b/src/tests/clone/src/main.ppl index 2ed4c6e3..8a1e7f77 100644 --- a/src/tests/clone/src/main.ppl +++ b/src/tests/clone/src/main.ppl @@ -1,10 +1,7 @@ -let x = 1 +let mut x = 1 let mut y = x println x println y - -println "" - y = 2 println x println y diff --git a/src/tests/snapshots/ppl__tests__clone.hir.snap b/src/tests/snapshots/ppl__tests__clone.hir.snap index 48787285..19ccd336 100644 --- a/src/tests/snapshots/ppl__tests__clone.hir.snap +++ b/src/tests/snapshots/ppl__tests__clone.hir.snap @@ -2,11 +2,10 @@ source: src/tests/mod.rs expression: hir --- -let x: Integer = 1 +let mut x: Integer = 1 let mut y: Integer = `clone <:Reference>`((x:Integer)) `println <:Integer>`(`clone <:Reference>`((x:Integer))) `println <:Integer>`(`clone <:Reference>`((y:Integer))) -`println <:String>`("") `destroy <:ReferenceMut>`((y:Integer)) (y:Integer) = 2 `println <:Integer>`(`clone <:Reference>`((x:Integer))) diff --git a/src/tests/snapshots/ppl__tests__clone.ir.snap b/src/tests/snapshots/ppl__tests__clone.ir.snap index bf286613..5d4dc1ba 100644 --- a/src/tests/snapshots/ppl__tests__clone.ir.snap +++ b/src/tests/snapshots/ppl__tests__clone.ir.snap @@ -13,7 +13,6 @@ source_filename = "src/main.ppl" @0 = private unnamed_addr constant [7 x i8] c"String\00", align 1 @x = global %Integer zeroinitializer @y = global %Integer zeroinitializer -@1 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 define private void @initialize() !dbg !3 { %1 = alloca %"Type", align 8, !dbg !7 @@ -43,36 +42,34 @@ define void @main.execute() !dbg !9 { call void @"println <:Integer>"(%Integer %1), !dbg !13 %2 = call %Integer @clone_integer(ptr @y), !dbg !14 call void @"println <:Integer>"(%Integer %2), !dbg !14 - %3 = call %String @string_from_c_string_and_length(ptr @1, i64 0), !dbg !15 - call void @"println <:String>"(%String %3), !dbg !15 - call void @destroy_integer(ptr @y), !dbg !16 - %4 = call %Integer @integer_from_i64(i64 2), !dbg !17 - store %Integer %4, ptr @y, align 8, !dbg !17 - %5 = call %Integer @clone_integer(ptr @x), !dbg !18 + call void @destroy_integer(ptr @y), !dbg !15 + %3 = call %Integer @integer_from_i64(i64 2), !dbg !16 + store %Integer %3, ptr @y, align 8, !dbg !16 + %4 = call %Integer @clone_integer(ptr @x), !dbg !17 + call void @"println <:Integer>"(%Integer %4), !dbg !17 + %5 = call %Integer @clone_integer(ptr @y), !dbg !18 call void @"println <:Integer>"(%Integer %5), !dbg !18 - %6 = call %Integer @clone_integer(ptr @y), !dbg !19 - call void @"println <:Integer>"(%Integer %6), !dbg !19 - call void @destroy_integer(ptr @x), !dbg !20 - call void @destroy_integer(ptr @y), !dbg !21 - br label %return, !dbg !21 + call void @destroy_integer(ptr @x), !dbg !19 + call void @destroy_integer(ptr @y), !dbg !20 + br label %return, !dbg !20 return: ; preds = %0 ret void } -define private void @initialize.1() !dbg !22 { - %1 = call %Integer @integer_from_i64(i64 1), !dbg !23 - store %Integer %1, ptr @x, align 8, !dbg !23 - br label %return, !dbg !23 +define private void @initialize.1() !dbg !21 { + %1 = call %Integer @integer_from_i64(i64 1), !dbg !22 + store %Integer %1, ptr @x, align 8, !dbg !22 + br label %return, !dbg !22 return: ; preds = %0 ret void } -define private void @initialize.2() !dbg !24 { - %1 = call %Integer @clone_integer(ptr @x), !dbg !25 - store %Integer %1, ptr @y, align 8, !dbg !25 - br label %return, !dbg !25 +define private void @initialize.2() !dbg !23 { + %1 = call %Integer @clone_integer(ptr @x), !dbg !24 + store %Integer %1, ptr @y, align 8, !dbg !24 + br label %return, !dbg !24 return: ; preds = %0 ret void @@ -80,13 +77,13 @@ return: ; preds = %0 declare %Integer @clone_integer(ptr) -define private void @"println <:Integer>"(%Integer %0) !dbg !26 { +define private void @"println <:Integer>"(%Integer %0) !dbg !25 { %x = alloca %Integer, align 8 store %Integer %0, ptr %x, align 8 - %2 = load %Integer, ptr %x, align 8, !dbg !27 - %3 = call %String @integer_as_string(%Integer %2), !dbg !27 - call void @"println <:String>"(%String %3), !dbg !27 - br label %return, !dbg !27 + %2 = load %Integer, ptr %x, align 8, !dbg !26 + %3 = call %String @integer_as_string(%Integer %2), !dbg !26 + call void @"println <:String>"(%String %3), !dbg !26 + br label %return, !dbg !26 return: ; preds = %1 ret void @@ -104,28 +101,27 @@ declare void @destroy_integer(ptr) !0 = !{i32 2, !"Debug Info Version", i32 3} !1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2, producer: "ppl", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, sysroot: "/") !2 = !DIFile(filename: "src/main.ppl", directory: ".") -!3 = distinct !DISubprogram(name: "initialize", linkageName: "initialize", scope: !2, file: !2, line: 10, type: !4, spFlags: DISPFlagDefinition, unit: !1) +!3 = distinct !DISubprogram(name: "initialize", linkageName: "initialize", scope: !2, file: !2, line: 7, type: !4, spFlags: DISPFlagDefinition, unit: !1) !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) -!7 = !DILocation(line: 10, scope: !3) +!7 = !DILocation(line: 7, scope: !3) !8 = !DILocation(line: 0, scope: !3) !9 = distinct !DISubprogram(name: "main.execute", linkageName: "main.execute", scope: !2, file: !2, type: !4, spFlags: DISPFlagDefinition, unit: !1) -!10 = !DILocation(line: 10, scope: !9) -!11 = !DILocation(line: 0, column: 8, scope: !9) +!10 = !DILocation(line: 7, scope: !9) +!11 = !DILocation(line: 0, column: 12, scope: !9) !12 = !DILocation(line: 1, column: 12, scope: !9) !13 = !DILocation(line: 2, column: 8, scope: !9) !14 = !DILocation(line: 3, column: 8, scope: !9) -!15 = !DILocation(line: 5, column: 8, scope: !9) -!16 = !DILocation(line: 7, scope: !9) -!17 = !DILocation(line: 7, column: 4, scope: !9) -!18 = !DILocation(line: 8, column: 8, scope: !9) -!19 = !DILocation(line: 9, column: 8, scope: !9) -!20 = !DILocation(line: 0, scope: !9) -!21 = !DILocation(line: 1, scope: !9) -!22 = distinct !DISubprogram(name: "initialize.1", linkageName: "initialize.1", scope: !9, file: !2, type: !4, spFlags: DISPFlagDefinition, unit: !1) -!23 = !DILocation(line: 0, column: 8, scope: !22) -!24 = distinct !DISubprogram(name: "initialize.2", linkageName: "initialize.2", scope: !9, file: !2, line: 1, type: !4, spFlags: DISPFlagDefinition, unit: !1) -!25 = !DILocation(line: 1, column: 12, scope: !24) -!26 = distinct !DISubprogram(name: "println <:Integer>", linkageName: "println <:Integer>", scope: !9, file: !2, line: 10, type: !4, spFlags: DISPFlagDefinition, unit: !1) -!27 = !DILocation(line: 10, scope: !26) +!15 = !DILocation(line: 4, scope: !9) +!16 = !DILocation(line: 4, column: 4, scope: !9) +!17 = !DILocation(line: 5, column: 8, scope: !9) +!18 = !DILocation(line: 6, column: 8, scope: !9) +!19 = !DILocation(line: 0, scope: !9) +!20 = !DILocation(line: 1, scope: !9) +!21 = distinct !DISubprogram(name: "initialize.1", linkageName: "initialize.1", scope: !9, file: !2, type: !4, spFlags: DISPFlagDefinition, unit: !1) +!22 = !DILocation(line: 0, column: 12, scope: !21) +!23 = distinct !DISubprogram(name: "initialize.2", linkageName: "initialize.2", scope: !9, file: !2, line: 1, type: !4, spFlags: DISPFlagDefinition, unit: !1) +!24 = !DILocation(line: 1, column: 12, scope: !23) +!25 = distinct !DISubprogram(name: "println <:Integer>", linkageName: "println <:Integer>", scope: !9, file: !2, line: 7, type: !4, spFlags: DISPFlagDefinition, unit: !1) +!26 = !DILocation(line: 7, scope: !25) diff --git a/src/tests/snapshots/ppl__tests__clone.run.snap b/src/tests/snapshots/ppl__tests__clone.run.snap index 32667a8f..0d09e579 100644 --- a/src/tests/snapshots/ppl__tests__clone.run.snap +++ b/src/tests/snapshots/ppl__tests__clone.run.snap @@ -4,6 +4,5 @@ expression: run_log --- 1 1 - 1 2