From 4df56dd51a5755b93791901c193b91ee1ae2ef31 Mon Sep 17 00:00:00 2001 From: Gavrilikhin Daniil Date: Wed, 6 Mar 2024 20:10:50 +0800 Subject: [PATCH] Make String to be a wrapper above ref (#87) * Make string to be wrapper around pointer * Print present types --- src/ir/types.rs | 4 +-- src/runtime/ppl.ppl | 5 +++- src/runtime/src/integer.rs | 14 +++++++---- src/runtime/src/memory.rs | 8 +++--- src/runtime/src/rational.rs | 10 +++++--- src/runtime/src/string.rs | 42 +++++++++++++++++++++++-------- src/runtime/src/type.rs | 4 ++- src/semantics/contexts/builtin.rs | 13 +++++++++- 8 files changed, 73 insertions(+), 27 deletions(-) diff --git a/src/ir/types.rs b/src/ir/types.rs index b8ee968e..14fe60ff 100644 --- a/src/ir/types.rs +++ b/src/ir/types.rs @@ -98,8 +98,8 @@ impl<'llvm> Types<'llvm> { } /// LLVM IR for [`String`](Type::String) type - pub fn string(&self) -> PointerType<'llvm> { - self.opaque("String") + pub fn string(&self) -> StructType<'llvm> { + self.with_impl("String") } /// LLVM IR for C string type diff --git a/src/runtime/ppl.ppl b/src/runtime/ppl.ppl index 1ae702fd..c202e61f 100644 --- a/src/runtime/ppl.ppl +++ b/src/runtime/ppl.ppl @@ -167,8 +167,11 @@ fn destroy <:Rational> //================================= // String //================================= +type StringImpl + @builtin -type String +type String: + impl: Reference /// Concatenate 2 strings @mangle_as("string_plus_string") diff --git a/src/runtime/src/integer.rs b/src/runtime/src/integer.rs index 4df14a91..313f2a5d 100644 --- a/src/runtime/src/integer.rs +++ b/src/runtime/src/integer.rs @@ -1,6 +1,6 @@ use rug::{ops::Pow, Integer}; -use crate::Rational; +use crate::{Rational, String}; /// Construct [`Integer`](ppl::semantics::Type::Integer) from i32 #[no_mangle] @@ -41,11 +41,13 @@ pub extern "C" fn integer_from_c_string(str: *const i8) -> *mut Integer { /// fn <:Integer> as String -> String /// ``` #[no_mangle] -pub extern "C" fn integer_as_string(i: *const Integer) -> *mut String { +pub extern "C" fn integer_as_string(i: *const Integer) -> String { let i = unsafe { i.as_ref().unwrap() }; let str = i.to_string(); let boxed = Box::new(str); - Box::into_raw(boxed) + String { + data: Box::into_raw(boxed), + } } /// Negates integer @@ -218,9 +220,11 @@ pub extern "C" fn i32_plus_i32(x: i32, y: i32) -> i32 { /// fn <:I32> as String -> String /// ``` #[no_mangle] -pub extern "C" fn i32_as_string(x: i32) -> *mut String { +pub extern "C" fn i32_as_string(x: i32) -> String { let boxed = Box::new(x.to_string()); - Box::into_raw(boxed) + String { + data: Box::into_raw(boxed), + } } /// # PPL diff --git a/src/runtime/src/memory.rs b/src/runtime/src/memory.rs index 15e680ff..e267e163 100644 --- a/src/runtime/src/memory.rs +++ b/src/runtime/src/memory.rs @@ -1,7 +1,7 @@ use libc::{c_void, malloc}; use rug::Integer; -use crate::{integer_from_i64, integer_from_u64, Type}; +use crate::{integer_from_i64, integer_from_u64, String, Type}; #[repr(C)] pub struct MemoryAddress { @@ -13,12 +13,14 @@ pub struct MemoryAddress { /// fn as String -> String /// ``` #[no_mangle] -pub extern "C" fn memory_address_as_string(address: MemoryAddress) -> *mut String { +pub extern "C" fn memory_address_as_string(address: MemoryAddress) -> String { let value = unsafe { address.value.as_ref().unwrap() }; let hex = format!("0x{}", value.to_string_radix(16).to_uppercase()); let boxed = Box::new(hex); - Box::into_raw(boxed) + String { + data: Box::into_raw(boxed), + } } /// # PPL diff --git a/src/runtime/src/rational.rs b/src/runtime/src/rational.rs index 7ce634f7..b88d0286 100644 --- a/src/runtime/src/rational.rs +++ b/src/runtime/src/rational.rs @@ -1,5 +1,7 @@ use rug::{ops::Pow, Integer}; +use crate::String; + /// Rational number. /// Wrapper around pointer to [`rug::Rational`]. /// @@ -36,11 +38,13 @@ pub extern "C" fn rational_from_c_string(str: *const i8) -> Rational { /// fn <:Rational> as String -> String /// ``` #[no_mangle] -pub extern "C" fn rational_as_string(r: Rational) -> *mut String { +pub extern "C" fn rational_as_string(r: Rational) -> String { let value = unsafe { r.data.as_ref().unwrap() }; let boxed = Box::new(maybe_to_decimal_string(value)); - Box::into_raw(boxed) + String { + data: Box::into_raw(boxed), + } } /// Negates rational @@ -145,7 +149,7 @@ pub extern "C" fn destroy_rational(x: Rational) { let _ = unsafe { Box::from_raw(x.data) }; } -pub fn maybe_to_decimal_string(r: &rug::Rational) -> String { +pub fn maybe_to_decimal_string(r: &rug::Rational) -> std::string::String { let mut denom = r.denom().clone(); let pow2 = denom.remove_factor_mut(&Integer::from(2)); let pow5 = denom.remove_factor_mut(&Integer::from(5)); diff --git a/src/runtime/src/string.rs b/src/runtime/src/string.rs index bff76cea..ebe6b298 100644 --- a/src/runtime/src/string.rs +++ b/src/runtime/src/string.rs @@ -1,13 +1,31 @@ use std::io::Write; +/// PPL's String type. +/// Wrapper around pointer to [`std::string::String`]. +/// +/// # PPL +/// ```no_run +/// type StringImpl +/// +/// @builtin +/// type String: +/// impl: Reference +/// ``` +#[repr(C)] +pub struct String { + pub data: *mut std::string::String, +} + /// Construct [`String`](ppl::semantics::Type::String) from a C string /// and length #[no_mangle] -pub extern "C" fn string_from_c_string_and_length(str: *const i8, _len: u64) -> *mut String { +pub extern "C" fn string_from_c_string_and_length(str: *const i8, _len: u64) -> String { let c_str = unsafe { core::ffi::CStr::from_ptr(str) }; let str = c_str.to_str().unwrap(); let boxed = Box::new(str.to_string()); - Box::into_raw(boxed) + String { + data: Box::into_raw(boxed), + } } /// Concatenate 2 string @@ -17,12 +35,14 @@ pub extern "C" fn string_from_c_string_and_length(str: *const i8, _len: u64) -> /// fn <:String> + <:String> -> None /// ``` #[no_mangle] -pub extern "C" fn string_plus_string(x: *const String, y: *const String) -> *mut String { - let x = unsafe { x.as_ref().unwrap() }; - let y = unsafe { y.as_ref().unwrap() }; +pub extern "C" fn string_plus_string(x: String, y: String) -> String { + let x = unsafe { x.data.as_ref().unwrap() }; + let y = unsafe { y.data.as_ref().unwrap() }; let boxed = Box::new(format!("{x}{y}")); - Box::into_raw(boxed) + String { + data: Box::into_raw(boxed), + } } /// Prints none value @@ -32,8 +52,8 @@ pub extern "C" fn string_plus_string(x: *const String, y: *const String) -> *mut /// fn print -> None /// ``` #[no_mangle] -pub extern "C" fn print_string(str: *const String) { - let str = unsafe { str.as_ref().unwrap() }; +pub extern "C" fn print_string(str: String) { + let str = unsafe { str.data.as_ref().unwrap() }; print!("{str}"); std::io::stdout().flush().unwrap(); @@ -44,8 +64,8 @@ pub extern "C" fn print_string(str: *const String) { /// fn destroy <:String> /// ``` #[no_mangle] -pub extern "C" fn destroy_string(x: *mut String) { - debug_assert!(!x.is_null()); +pub extern "C" fn destroy_string(x: String) { + debug_assert!(!x.data.is_null()); - let _ = unsafe { Box::from_raw(x) }; + let _ = unsafe { Box::from_raw(x.data) }; } diff --git a/src/runtime/src/type.rs b/src/runtime/src/type.rs index 0139c173..8d572686 100644 --- a/src/runtime/src/type.rs +++ b/src/runtime/src/type.rs @@ -1,5 +1,7 @@ use rug::Integer; +use crate::String; + /// Runtime type information /// /// # PPL @@ -10,6 +12,6 @@ use rug::Integer; /// ``` #[repr(C)] pub struct Type { - pub name: *mut String, + pub name: String, pub size: *mut Integer, } diff --git a/src/semantics/contexts/builtin.rs b/src/semantics/contexts/builtin.rs index d0e26da7..cd997ef9 100644 --- a/src/semantics/contexts/builtin.rs +++ b/src/semantics/contexts/builtin.rs @@ -55,7 +55,18 @@ impl BuiltinTypes<'_> { self.module .types .get(name) - .expect(format!("Builtin type `{name}` should be present").as_str()) + .expect( + format!( + "Builtin type `{name}` should be present. Present types: {}", + self.module + .types + .iter() + .map(|t| t.0.clone()) + .collect::>() + .join(", ") + ) + .as_str(), + ) .clone() .into() }