From 0a812bedeba388e26371f1a36905ceafccf354a7 Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Mon, 31 Oct 2022 12:38:24 +0100 Subject: [PATCH 01/36] bigint and bigrat term getters and unifiers --- swipl-fli/build.rs | 7 +- swipl/Cargo.toml | 1 + swipl/src/context.rs | 14 ++-- swipl/src/dict.rs | 4 +- swipl/src/functor.rs | 4 +- swipl/src/term/bignum.rs | 140 +++++++++++++++++++++++++++++++++++++++ swipl/src/term/mod.rs | 2 + 7 files changed, 159 insertions(+), 13 deletions(-) create mode 100644 swipl/src/term/bignum.rs diff --git a/swipl-fli/build.rs b/swipl-fli/build.rs index 3265919a84..d687998d9d 100644 --- a/swipl-fli/build.rs +++ b/swipl-fli/build.rs @@ -10,8 +10,11 @@ fn main() { println!("cargo:rerun-if-changed=c/wrapper.h"); println!("cargo:rerun-if-env-changed=SWIPL"); - let bindings = bindgen::Builder::default() - .header("c/wrapper.h") + let mut bindings = bindgen::Builder::default(); + // TODO behind feature flag please; + bindings = bindings.header_contents("include_gmp", "#include \n"); + + let bindings = bindings.header("c/wrapper.h") .clang_arg(format!("-I{}", info.header_dir)) .parse_callbacks(Box::new(bindgen::CargoCallbacks)) .generate() diff --git a/swipl/Cargo.toml b/swipl/Cargo.toml index 1c5e03592e..8f1ad0f0c2 100644 --- a/swipl/Cargo.toml +++ b/swipl/Cargo.toml @@ -17,6 +17,7 @@ lazy_static = "1.4.0" thiserror = "1.0" serde = {version="1.0", optional=true} convert_case = "0.6" +rug = {version = "1.17", default-features = false, features=["integer","rational"]} [dev-dependencies] serde = {version="1.0", features=["derive"]} \ No newline at end of file diff --git a/swipl/src/context.rs b/swipl/src/context.rs index 583830b006..d211f6598a 100644 --- a/swipl/src/context.rs +++ b/swipl/src/context.rs @@ -455,7 +455,7 @@ enum FrameState { /// let term2 = frame.new_term_ref(); /// /// frame.close(); -/// assert_eq!(42_u64, term.get()?); +/// assert_eq!(42_u64, term.get::()?); /// // the following would result in a compile error: /// // term2.unify(42_u64)?; /// @@ -482,7 +482,7 @@ enum FrameState { /// term.unify(43_u64)?; /// /// frame.close(); -/// assert_eq!(43_u64, term.get()?); +/// assert_eq!(43_u64, term.get::()?); /// /// Ok(()) /// } @@ -1207,7 +1207,7 @@ mod tests { let next = query.next_solution()?; assert!(!next); - assert_eq!(42_u64, term1.get()?); + assert_eq!(42_u64, term1.get::()?); let next = query.next_solution(); assert!(next.is_err()); @@ -1239,7 +1239,7 @@ mod tests { let next = query.next_solution()?; assert!(!next); - assert_eq!(42_u64, term1.get().unwrap()); + assert_eq!(42_u64, term1.get::().unwrap()); } // after leaving the block, we have discarded @@ -1272,7 +1272,7 @@ mod tests { let next = query.next_solution()?; assert!(!next); - assert_eq!(42_u64, term1.get()?); + assert_eq!(42_u64, term1.get::()?); query.discard(); } @@ -1306,12 +1306,12 @@ mod tests { let next = query.next_solution()?; assert!(!next); - assert_eq!(42_u64, term1.get()?); + assert_eq!(42_u64, term1.get::()?); query.cut(); } // a cut query leaves data intact - assert_eq!(42_u64, term1.get()?); + assert_eq!(42_u64, term1.get::()?); Ok(()) } diff --git a/swipl/src/dict.rs b/swipl/src/dict.rs index 703f515bc1..0d6c9dc977 100644 --- a/swipl/src/dict.rs +++ b/swipl/src/dict.rs @@ -656,7 +656,7 @@ mod tests { dict.unify(&builder).unwrap(); dict.get_dict_tag_term(&tag2).unwrap(); - assert_eq!(42_u64, tag2.get().unwrap()); + assert_eq!(42_u64, tag2.get::().unwrap()); tag.unify(&tag2).unwrap(); } @@ -673,7 +673,7 @@ mod tests { dict.unify(&builder).unwrap(); - assert_eq!(42_u64, dict.get_dict_key("foo").unwrap()); + assert_eq!(42_u64, dict.get_dict_key::<_,u64>("foo").unwrap()); let hello_str: String = dict.get_dict_key("bar").unwrap(); assert_eq!("hello", hello_str); diff --git a/swipl/src/functor.rs b/swipl/src/functor.rs index 17ed1f8874..f6f8924d9c 100644 --- a/swipl/src/functor.rs +++ b/swipl/src/functor.rs @@ -272,12 +272,12 @@ mod tests { assert!(term.unify(f).is_ok()); assert!(term.get_arg::(1).unwrap_err().is_failure()); assert!(term.unify_arg(1, 42_u64).is_ok()); - assert_eq!(42_u64, term.get_arg(1).unwrap()); + assert_eq!(42_u64, term.get_arg::(1).unwrap()); assert!(term.unify_arg(1, 42_u64).is_ok()); assert!(!term.unify_arg(1, 43_u64).is_ok()); assert!(term.unify_arg(2, 24_u64).is_ok()); - assert_eq!(24_u64, term.get_arg(2).unwrap()); + assert_eq!(24_u64, term.get_arg::(2).unwrap()); assert!(!term.unify_arg(3, 24_u64).is_ok()); assert!(term.get_arg::(3).unwrap_err().is_failure()); diff --git a/swipl/src/term/bignum.rs b/swipl/src/term/bignum.rs new file mode 100644 index 0000000000..fe6289715e --- /dev/null +++ b/swipl/src/term/bignum.rs @@ -0,0 +1,140 @@ +//! Support for rug Integer and Rational using SWI-Prolog's GMP support. + +use crate::{term_getable, unifiable}; +use crate::term::*; +use crate::fli; +use rug::{Integer, Rational}; + +term_getable! { + (Integer, "bigint", term) => { + let mut i = Integer::new(); + let ptr = i.as_raw_mut(); + + let result = unsafe { + fli::PL_get_mpz(term.term_ptr(), std::mem::transmute(ptr)) + }; + if result != 0 { + Some(i) + } + else { + None + } + } +} + +unifiable! { + (self:&Integer, term) => { + let ptr = self.as_raw(); + + let result = unsafe { + fli::PL_unify_mpz(term.term_ptr(), std::mem::transmute(ptr)) + }; + + result != 0 + } +} + +term_getable! { + (Rational, "bigrat", term) => { + let mut r = Rational::new(); + let ptr = r.as_raw_mut(); + + let result = unsafe { + fli::PL_get_mpq(term.term_ptr(), std::mem::transmute(ptr)) + }; + if result != 0 { + Some(r) + } + else { + None + } + } +} + +unifiable! { + (self:&Rational, term) => { + let ptr = self.as_raw(); + + let result = unsafe { + fli::PL_unify_mpq(term.term_ptr(), std::mem::transmute(ptr)) + }; + + result != 0 + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use crate::context::*; + use super::*; + #[test] + fn get_bigint() { + let engine = Engine::new(); + let activation = engine.activate(); + let context: Context<_> = activation.into(); + + let big_int_str = "1234123412341234123412341234123412341234"; + let term = context.term_from_string(big_int_str).unwrap(); + + let expected = Integer::from_str(big_int_str).unwrap(); + let i: Integer = term.get().unwrap(); + assert_eq!(expected, i); + } + + #[test] + fn unify_bigint() { + let engine = Engine::new(); + let activation = engine.activate(); + let context: Context<_> = activation.into(); + + let big_int_str = "1234123412341234123412341234123412341234"; + let i = Integer::from_str(big_int_str).unwrap(); + + let term = context.new_term_ref(); + term.unify(&i).unwrap(); + + let s = context.string_from_term(&term).unwrap(); + + assert_eq!(big_int_str, s); + } + + #[test] + fn get_bigrat() { + let engine = Engine::new(); + let activation = engine.activate(); + let context: Context<_> = activation.into(); + + // we construct a big rational in swipl using the 'r' notation. + // We use a prime denominator to ensure no unexpected normalizing happens. + let big_numerator = "1234123412341234123412341234123412341234"; + let big_prime_str = "19131612631094571991039"; + let big_rat_prolog_string = format!("{big_numerator}r{big_prime_str}"); + let big_rat_div_string = format!("{big_numerator}/{big_prime_str}"); + let term = context.term_from_string(&big_rat_prolog_string).unwrap(); + + let expected = Rational::from_str(&big_rat_div_string).unwrap(); + let i: Rational = term.get().unwrap(); + assert_eq!(expected, i); + } + + #[test] + fn unify_bigrat() { + let engine = Engine::new(); + let activation = engine.activate(); + let context: Context<_> = activation.into(); + + let big_numerator = "1234123412341234123412341234123412341234"; + let big_prime_str = "19131612631094571991039"; + let big_rat_prolog_string = format!("{big_numerator}r{big_prime_str}"); + let big_rat_div_string = format!("{big_numerator}/{big_prime_str}"); + let i = Rational::from_str(&big_rat_div_string).unwrap(); + + let term = context.new_term_ref(); + term.unify(&i).unwrap(); + + let s = context.string_from_term(&term).unwrap(); + + assert_eq!(big_rat_prolog_string, s); + } +} diff --git a/swipl/src/term/mod.rs b/swipl/src/term/mod.rs index b35da9f619..5cf8d5a4d2 100644 --- a/swipl/src/term/mod.rs +++ b/swipl/src/term/mod.rs @@ -54,6 +54,8 @@ pub use de::Deserializer; #[cfg(feature = "serde")] pub use ser::{Serializer, SerializerConfiguration}; +pub mod bignum; + /// A term reference. #[derive(Clone)] pub struct Term<'a> { From cfa63ec8863133fb2fd78a931af020d5fed005fa Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Mon, 31 Oct 2022 12:43:58 +0100 Subject: [PATCH 02/36] put bignum support behind rug feature flag --- swipl-fli/Cargo.toml | 3 +++ swipl-fli/build.rs | 5 +++-- swipl/Cargo.toml | 7 +++++-- swipl/src/term/mod.rs | 3 ++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/swipl-fli/Cargo.toml b/swipl-fli/Cargo.toml index a080e483b8..df4d277f14 100644 --- a/swipl-fli/Cargo.toml +++ b/swipl-fli/Cargo.toml @@ -13,3 +13,6 @@ documentation = "https://terminusdb-labs.github.io/swipl-rs/swipl_fli/" [build-dependencies] bindgen = "0.59.0" swipl-info = {path = "../swipl-info", version = "0.3.2"} + +[features] +gmp = [] \ No newline at end of file diff --git a/swipl-fli/build.rs b/swipl-fli/build.rs index d687998d9d..5a020ad22c 100644 --- a/swipl-fli/build.rs +++ b/swipl-fli/build.rs @@ -11,8 +11,9 @@ fn main() { println!("cargo:rerun-if-env-changed=SWIPL"); let mut bindings = bindgen::Builder::default(); - // TODO behind feature flag please; - bindings = bindings.header_contents("include_gmp", "#include \n"); + if cfg!(feature = "gmp") { + bindings = bindings.header_contents("include_gmp", "#include \n"); + } let bindings = bindings.header("c/wrapper.h") .clang_arg(format!("-I{}", info.header_dir)) diff --git a/swipl/Cargo.toml b/swipl/Cargo.toml index 8f1ad0f0c2..3ad3e9307f 100644 --- a/swipl/Cargo.toml +++ b/swipl/Cargo.toml @@ -17,7 +17,10 @@ lazy_static = "1.4.0" thiserror = "1.0" serde = {version="1.0", optional=true} convert_case = "0.6" -rug = {version = "1.17", default-features = false, features=["integer","rational"]} +rug = {version = "1.17", default-features = false, optional=true, features=["integer","rational"]} [dev-dependencies] -serde = {version="1.0", features=["derive"]} \ No newline at end of file +serde = {version="1.0", features=["derive"]} + +[features] +rug = ["dep:rug", "swipl-fli/gmp"] \ No newline at end of file diff --git a/swipl/src/term/mod.rs b/swipl/src/term/mod.rs index 5cf8d5a4d2..fa9d7b234b 100644 --- a/swipl/src/term/mod.rs +++ b/swipl/src/term/mod.rs @@ -54,7 +54,8 @@ pub use de::Deserializer; #[cfg(feature = "serde")] pub use ser::{Serializer, SerializerConfiguration}; -pub mod bignum; +#[cfg(feature = "rug")] +mod bignum; /// A term reference. #[derive(Clone)] From 9f2d1abd571ffc257cc6af4e205c0120df3f24e2 Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Tue, 8 Nov 2022 14:28:14 +0100 Subject: [PATCH 03/36] use thread state to do faster atom deserialization from swipl --- swipl/src/term/de.rs | 107 ++++++++++++++++++++++++++++++++++++++++-- tests/json/src/lib.rs | 14 +++++- 2 files changed, 116 insertions(+), 5 deletions(-) diff --git a/swipl/src/term/de.rs b/swipl/src/term/de.rs index 80eb4145ee..36b56e8f1c 100644 --- a/swipl/src/term/de.rs +++ b/swipl/src/term/de.rs @@ -8,6 +8,7 @@ use crate::{atom, functor}; use serde::de::{self, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, VariantAccess, Visitor}; use serde::Deserialize; use std::fmt::{self, Display}; +use std::cell::Cell; /// Deserialize a term into a rust value using serde. pub fn from_term<'a, C: QueryableContextType, T>( @@ -458,7 +459,7 @@ impl<'de, C: QueryableContextType> de::Deserializer<'de> for Deserializer<'de, C Err(Error::ValueOutOfRange) } } - None => Err(Error::ValueNotOfExpectedType("u64")), + None => Err(Error::ValueNotOfExpectedType("u64 (x)")), } } fn deserialize_f32(self, visitor: V) -> Result @@ -580,7 +581,23 @@ impl<'de, C: QueryableContextType> de::Deserializer<'de> for Deserializer<'de, C V: Visitor<'de>, { if name == ATOM_STRUCT_NAME { - self.deserialize_string(visitor) + if DeserializingAtomState::is_deserializing_atom() { + let atom = attempt_opt(self.term.get::())?; + match atom { + Some(atom) => { + if cfg!(target_pointer_width = "32") { + visitor.visit_u32(atom.atom_ptr() as u32) + } + else { + visitor.visit_u64(atom.atom_ptr() as u64) + } + }, + None => Err(Error::ValueNotOfExpectedType("atom")) + } + } + else { + self.deserialize_string(visitor) + } } else { visitor.visit_newtype_struct(self) } @@ -944,9 +961,24 @@ impl<'de> de::Deserializer<'de> for KeyDeserializer { where V: Visitor<'de>, { + // an atom key! if name == ATOM_STRUCT_NAME { - // an atom key! - self.deserialize_string(visitor) + if DeserializingAtomState::is_deserializing_atom() { + match self.key { + Key::Atom(atom) => { + if cfg!(target_pointer_width = "32") { + visitor.visit_u32(atom.atom_ptr() as u32) + } + else { + visitor.visit_u64(atom.atom_ptr() as u64) + } + }, + _ => Err(Error::ValueNotOfExpectedType("atom")) + } + } + else { + self.deserialize_string(visitor) + } } else { Err(Error::UnexpectedType("newtype struct")) } @@ -1220,11 +1252,42 @@ impl<'de> de::Deserializer<'de> for EnumVariantDeserializer { } } +thread_local! { + static DESERIALIZING_ATOM: Cell = Cell::new(false); +} + +struct DeserializingAtomState; + +impl DeserializingAtomState { + fn start() -> Self { + DESERIALIZING_ATOM.with(|da| { + if da.get() { + panic!("atom serialization was already set. did we recurse?"); + } + da.set(true) + }); + + + Self + } + + fn is_deserializing_atom() -> bool { + DESERIALIZING_ATOM.with(|da| da.get()) + } +} + +impl Drop for DeserializingAtomState { + fn drop(&mut self) { + DESERIALIZING_ATOM.with(|da| da.set(false)); + } +} + impl<'de> Deserialize<'de> for Atom { fn deserialize(deserializer: D) -> std::result::Result where D: de::Deserializer<'de>, { + let _state = DeserializingAtomState::start(); deserializer.deserialize_newtype_struct(ATOM_STRUCT_NAME, AtomVisitor) } } @@ -1238,12 +1301,48 @@ impl<'de> Visitor<'de> for AtomVisitor { write!(formatter, "an atom") } + #[cfg(target_pointer_width = "32")] + fn visit_u32(self, v: u32) -> std::result::Result + where + E: de::Error, + { + if !DeserializingAtomState::is_deserializing_atom() { + panic!("visiting atom as pointer but not in deserializing state"); + } + let atom = unsafe { Atom::wrap((v as usize).into()) }; + atom.increment_refcount(); + Ok(atom) + } + + #[cfg(target_pointer_width = "64")] + fn visit_u64(self, v: u64) -> std::result::Result + where + E: de::Error, + { + if !DeserializingAtomState::is_deserializing_atom() { + panic!("visiting atom as pointer but not in deserializing state"); + } + let atom = unsafe { Atom::wrap((v as usize).into()) }; + atom.increment_refcount(); + Ok(atom) + } + fn visit_str(self, s: &str) -> std::result::Result where E: de::Error, { Ok(Atom::new(s)) } + + fn visit_newtype_struct(self, deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + // us being here indicates we're being deserialized from an + // unknown deserializer (not swipl). That means we have to + // interpret as string and not as a pointer. + deserializer.deserialize_str(self) + } } #[cfg(test)] diff --git a/tests/json/src/lib.rs b/tests/json/src/lib.rs index 2019cce14e..28c4905736 100644 --- a/tests/json/src/lib.rs +++ b/tests/json/src/lib.rs @@ -1,6 +1,5 @@ #[cfg(test)] mod tests { - use serde::{Deserialize, Serialize}; use serde_json::{self, json, Value}; use std::io::{BufWriter, Write}; use swipl::prelude::*; @@ -47,4 +46,17 @@ mod tests { assert_eq!(r#"{"foo":"bar","baz":{"elts":[42,{"wow":"moo"},50]}}"#, s); } + + #[test] + fn deserialize_atom_from_json() { + let engine = Engine::new(); + let activation = engine.activate(); + let _context: Context<_> = activation.into(); + + let json = json!("hello"); + + let atom: Atom = serde_json::from_value(json).unwrap(); + + assert_eq!(atom!("hello"), atom); + } } From 39a024037081054fd4c1650e139f937203896b1a Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 10:44:30 +0100 Subject: [PATCH 04/36] ci: install specific gnu target for Windows --- .github/workflows/rust.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 04f4b49473..104e1dd783 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -26,6 +26,15 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 + # This is needed because the GMP crate does not support MSVC + - name: Install MINGW version of rust for Windows + if ${{ matrix.os == 'windows-latest' }} + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: x86_64-pc-windows-gnu + override: true + default: true - name: Install SWI Prolog on Linux if: ${{ matrix.os == 'ubuntu-latest' }} run: | From 11bbee591818fefcf2f27eec015f1980fec461fa Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 10:45:03 +0100 Subject: [PATCH 05/36] Fix typo --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 104e1dd783..682fcf80cf 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -28,7 +28,7 @@ jobs: - uses: actions/checkout@v2 # This is needed because the GMP crate does not support MSVC - name: Install MINGW version of rust for Windows - if ${{ matrix.os == 'windows-latest' }} + if: ${{ matrix.os == 'windows-latest' }} uses: actions-rs/toolchain@v1 with: toolchain: stable From 87e1304d41ae764536412342441a80438416cbf2 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 10:54:50 +0100 Subject: [PATCH 06/36] Explicity target windows-gnu --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 682fcf80cf..3b857d63a4 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -73,7 +73,7 @@ jobs: env: SWIPL: C:\Program Files\swipl\bin\swipl.exe LIBCLANG_PATH: C:\Program Files\LLVM\bin\ - run: cargo swipl test --all-features + run: cargo swipl test --all-features --target=x86_64-pc-windows-gnu - name: Run tests on osx with dmg if: ${{ matrix.dmg == 'dmg' }} env: From 0d6fafc64b03aa6d445c2862f1906a9e45255215 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 11:01:55 +0100 Subject: [PATCH 07/36] use default gnu toolchain --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3b857d63a4..7ef074a254 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -31,7 +31,7 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} uses: actions-rs/toolchain@v1 with: - toolchain: stable + toolchain: stable-x86_64-pc-windows-gnu target: x86_64-pc-windows-gnu override: true default: true From 70deb1e47afb25948a97e0e00c05682ec46390f0 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 13:10:13 +0100 Subject: [PATCH 08/36] Try to set path in windows CI --- .github/workflows/rust.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7ef074a254..38082855b4 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -73,7 +73,9 @@ jobs: env: SWIPL: C:\Program Files\swipl\bin\swipl.exe LIBCLANG_PATH: C:\Program Files\LLVM\bin\ - run: cargo swipl test --all-features --target=x86_64-pc-windows-gnu + run: | + export PATH=$PATH:/c/msys64/usr/bin:/c/msys64/bin + cargo swipl test --all-features --target=x86_64-pc-windows-gnu - name: Run tests on osx with dmg if: ${{ matrix.dmg == 'dmg' }} env: From c176eac595ddfada1f5a5e63e6ec10436366c8a9 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 13:24:25 +0100 Subject: [PATCH 09/36] Add gmp and m4 --- .github/workflows/rust.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 38082855b4..3450ef48c7 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -75,6 +75,7 @@ jobs: LIBCLANG_PATH: C:\Program Files\LLVM\bin\ run: | export PATH=$PATH:/c/msys64/usr/bin:/c/msys64/bin + pacman -S gmp gmp-devel m4 cargo swipl test --all-features --target=x86_64-pc-windows-gnu - name: Run tests on osx with dmg if: ${{ matrix.dmg == 'dmg' }} From 4e404eff226fecdfff53481c124b716e5d84da64 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 13:32:35 +0100 Subject: [PATCH 10/36] use msys2 shell properly --- .github/workflows/rust.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3450ef48c7..d610f464d1 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -68,15 +68,26 @@ jobs: - name: Run tests on posix if: ${{ matrix.os != 'windows-latest' && matrix.dmg == 'no_dmg' }} run: cargo swipl test --all-features + + - name: Install msys2 + if: ${{ matrix.os == 'windows-latest' }} + uses: msys2/setup-msys2@v2 + with: + install: >- + base-devel + gmp + gmp-devel + m4 - name: Run tests on windows if: ${{ matrix.os == 'windows-latest' }} - env: + shell: msys2 {0} + env: SWIPL: C:\Program Files\swipl\bin\swipl.exe LIBCLANG_PATH: C:\Program Files\LLVM\bin\ run: | - export PATH=$PATH:/c/msys64/usr/bin:/c/msys64/bin - pacman -S gmp gmp-devel m4 cargo swipl test --all-features --target=x86_64-pc-windows-gnu + + - name: Run tests on osx with dmg if: ${{ matrix.dmg == 'dmg' }} env: From c0aaff5c408b85eada43932083d5797b3026d793 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 13:41:23 +0100 Subject: [PATCH 11/36] Add cargo to path --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d610f464d1..1a45d3b41f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -85,9 +85,9 @@ jobs: SWIPL: C:\Program Files\swipl\bin\swipl.exe LIBCLANG_PATH: C:\Program Files\LLVM\bin\ run: | + export PATH="$PATH:/c/UsersDefault/.cargo/bin" cargo swipl test --all-features --target=x86_64-pc-windows-gnu - - name: Run tests on osx with dmg if: ${{ matrix.dmg == 'dmg' }} env: From 90e2d59e118dfd6259deb8750fec1bb1a7f3d8b1 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 13:41:41 +0100 Subject: [PATCH 12/36] Add missing slash --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 1a45d3b41f..71033d4c6f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -85,7 +85,7 @@ jobs: SWIPL: C:\Program Files\swipl\bin\swipl.exe LIBCLANG_PATH: C:\Program Files\LLVM\bin\ run: | - export PATH="$PATH:/c/UsersDefault/.cargo/bin" + export PATH="$PATH:/c/Users/Default/.cargo/bin" cargo swipl test --all-features --target=x86_64-pc-windows-gnu - name: Run tests on osx with dmg From df50c71a1b1dad4bc1d532c8f3140626f1be24f8 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 13:54:40 +0100 Subject: [PATCH 13/36] Install exact packages as specified on gmp-mpfr-sys docs --- .github/workflows/rust.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 71033d4c6f..dffdd06747 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -74,10 +74,10 @@ jobs: uses: msys2/setup-msys2@v2 with: install: >- - base-devel - gmp - gmp-devel + diffutils m4 + make + mingw-w64-x86_64-gcc - name: Run tests on windows if: ${{ matrix.os == 'windows-latest' }} shell: msys2 {0} From 016cd7cbc4fed0affbc29c8ac63af5ca571cbff4 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 14:02:25 +0100 Subject: [PATCH 14/36] gmp also needed? --- .github/workflows/rust.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index dffdd06747..89e3542cc3 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -78,6 +78,8 @@ jobs: m4 make mingw-w64-x86_64-gcc + gmp + gmp-devel - name: Run tests on windows if: ${{ matrix.os == 'windows-latest' }} shell: msys2 {0} From c87f2b0e38b11373c6d8f658023ee3f6b0e8a7b5 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 14:10:48 +0100 Subject: [PATCH 15/36] Use mingw gmp --- .github/workflows/rust.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 89e3542cc3..8fdd020d03 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -78,8 +78,7 @@ jobs: m4 make mingw-w64-x86_64-gcc - gmp - gmp-devel + mingw-w64-gmp - name: Run tests on windows if: ${{ matrix.os == 'windows-latest' }} shell: msys2 {0} From 4353db0931124c48f16c09543fcfe04debbc207f Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 14:18:17 +0100 Subject: [PATCH 16/36] update: true --- .github/workflows/rust.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8fdd020d03..e9931a977a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -73,6 +73,7 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} uses: msys2/setup-msys2@v2 with: + update: true install: >- diffutils m4 From 502f63604caf2e27cc08bfe888c77a1b953a9035 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 14:28:20 +0100 Subject: [PATCH 17/36] usr include --- .github/workflows/rust.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e9931a977a..b469d279ea 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -78,8 +78,9 @@ jobs: diffutils m4 make + gmp + gmp-devel mingw-w64-x86_64-gcc - mingw-w64-gmp - name: Run tests on windows if: ${{ matrix.os == 'windows-latest' }} shell: msys2 {0} @@ -88,6 +89,7 @@ jobs: LIBCLANG_PATH: C:\Program Files\LLVM\bin\ run: | export PATH="$PATH:/c/Users/Default/.cargo/bin" + export C_INCLUDE_PATH=/usr/include/ cargo swipl test --all-features --target=x86_64-pc-windows-gnu - name: Run tests on osx with dmg From bf38a0ac2bb93d45e3eb1e71cc289cd801f1e468 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 17:38:28 +0100 Subject: [PATCH 18/36] Run msys2 by default on Windows --- .github/workflows/rust.yml | 56 ++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b469d279ea..14138aab54 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -18,8 +18,18 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + include: + - os: ubuntu-latest + shell: bash + - os: macos-latest + shell: bash + - os: windows-latest + shell: msys2 dmg: [no_dmg] + + defaults: + run: + shell: ${{ matrix.shell} {0} #include: # - os: macos-latest # dmg: dmg @@ -27,23 +37,28 @@ jobs: steps: - uses: actions/checkout@v2 # This is needed because the GMP crate does not support MSVC - - name: Install MINGW version of rust for Windows - if: ${{ matrix.os == 'windows-latest' }} - uses: actions-rs/toolchain@v1 - with: - toolchain: stable-x86_64-pc-windows-gnu - target: x86_64-pc-windows-gnu - override: true - default: true - name: Install SWI Prolog on Linux if: ${{ matrix.os == 'ubuntu-latest' }} run: | sudo apt-add-repository ppa:swi-prolog/stable sudo apt-get update sudo apt install swi-prolog-nox - - name: Install LLVM and SWI Prolog on Windows + + - name: Install msys2 for Windows if: ${{ matrix.os == 'windows-latest' }} - run: choco install llvm swi-prolog + uses: msys2/setup-msys2@v2 + with: + install: >- + diffutils + m4 + make + gmp + gmp-devel + mingw-w64-x86_64-gcc + mingw-w64-swi-prolog + mingw-w64-clang + mingw-w64-rust + - name: Install SWI Prolog on MacOS from brew if: ${{ matrix.os == 'macos-latest' && matrix.dmg == 'no_dmg' }} run: brew install swi-prolog @@ -55,8 +70,6 @@ jobs: run: cargo run --bin print_swipl_info - name: Print information with swipl-info on windows if: ${{ matrix.os == 'windows-latest' }} - env: - SWIPL: C:\Program Files\swipl\bin\swipl.exe run: cargo run --bin print_swipl_info - name: Print information with swipl-info on osx with dmg if: ${{ matrix.dmg == 'dmg' }} @@ -69,26 +82,9 @@ jobs: if: ${{ matrix.os != 'windows-latest' && matrix.dmg == 'no_dmg' }} run: cargo swipl test --all-features - - name: Install msys2 - if: ${{ matrix.os == 'windows-latest' }} - uses: msys2/setup-msys2@v2 - with: - update: true - install: >- - diffutils - m4 - make - gmp - gmp-devel - mingw-w64-x86_64-gcc - name: Run tests on windows if: ${{ matrix.os == 'windows-latest' }} - shell: msys2 {0} - env: - SWIPL: C:\Program Files\swipl\bin\swipl.exe - LIBCLANG_PATH: C:\Program Files\LLVM\bin\ run: | - export PATH="$PATH:/c/Users/Default/.cargo/bin" export C_INCLUDE_PATH=/usr/include/ cargo swipl test --all-features --target=x86_64-pc-windows-gnu From 6e464f18eec136c6b8895464cffc669c9d32ad30 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 17:39:27 +0100 Subject: [PATCH 19/36] Close expression --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 14138aab54..7e10ac1110 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -29,7 +29,7 @@ jobs: defaults: run: - shell: ${{ matrix.shell} {0} + shell: ${{ matrix.shell}} {0} #include: # - os: macos-latest # dmg: dmg From ef91fe1c695a5d518915f28429279c03ff261326 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 17:41:07 +0100 Subject: [PATCH 20/36] dmg setting --- .github/workflows/rust.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7e10ac1110..f5bb7ec388 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -21,11 +21,13 @@ jobs: include: - os: ubuntu-latest shell: bash + dmg: no_dmg - os: macos-latest shell: bash + dmg: no_dmg - os: windows-latest shell: msys2 - dmg: [no_dmg] + dmg: no_dmg defaults: run: From 1b071a769df5bbcaee26451f345f321d32776b45 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 17:43:07 +0100 Subject: [PATCH 21/36] Try without prefix --- .github/workflows/rust.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index f5bb7ec388..9a6109ba68 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -57,9 +57,9 @@ jobs: gmp gmp-devel mingw-w64-x86_64-gcc - mingw-w64-swi-prolog - mingw-w64-clang - mingw-w64-rust + swi-prolog + clang + rust - name: Install SWI Prolog on MacOS from brew if: ${{ matrix.os == 'macos-latest' && matrix.dmg == 'no_dmg' }} From d861b8422dcf721b1b6f0037c0a0f4448f7c13ad Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 17:48:34 +0100 Subject: [PATCH 22/36] Set up specific packages --- .github/workflows/rust.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9a6109ba68..44db014349 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -57,9 +57,9 @@ jobs: gmp gmp-devel mingw-w64-x86_64-gcc - swi-prolog - clang - rust + mingw-w64-x86_64-rust + mingw-w64-x86_64-swi-prolog + mingw-w64-clang-x86_64-toolchain - name: Install SWI Prolog on MacOS from brew if: ${{ matrix.os == 'macos-latest' && matrix.dmg == 'no_dmg' }} From 9443deab1d64c866898ddfe12823df3a257af266 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 18:03:42 +0100 Subject: [PATCH 23/36] Use cargo swipl for print_swipl_info --- .github/workflows/rust.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 44db014349..7681868f3f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -70,16 +70,16 @@ jobs: - name: Print information with swipl-info on posix if: ${{ matrix.os != 'windows-latest' && matrix.dmg == 'no_dmg' }} run: cargo run --bin print_swipl_info + - name: Install cargo-swipl + run: cargo install --path ./cargo-swipl - name: Print information with swipl-info on windows if: ${{ matrix.os == 'windows-latest' }} - run: cargo run --bin print_swipl_info + run: cargo swipl run --bin print_swipl_info - name: Print information with swipl-info on osx with dmg if: ${{ matrix.dmg == 'dmg' }} env: SWIPL: /Applications/SWI-Prolog.app/Contents/MacOS/swipl run: cargo run --bin print_swipl_info - - name: Install cargo-swipl - run: cargo install --path ./cargo-swipl - name: Run tests on posix if: ${{ matrix.os != 'windows-latest' && matrix.dmg == 'no_dmg' }} run: cargo swipl test --all-features From 22f3b61cdae6f31b99a3874ee21022e88c118881 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 19:38:48 +0100 Subject: [PATCH 24/36] Specify swipl using ENV variable --- .github/workflows/rust.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7681868f3f..47807f5488 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -74,6 +74,8 @@ jobs: run: cargo install --path ./cargo-swipl - name: Print information with swipl-info on windows if: ${{ matrix.os == 'windows-latest' }} + env: + SWIPL: /mingw64/bin/swipl run: cargo swipl run --bin print_swipl_info - name: Print information with swipl-info on osx with dmg if: ${{ matrix.dmg == 'dmg' }} @@ -86,6 +88,9 @@ jobs: - name: Run tests on windows if: ${{ matrix.os == 'windows-latest' }} + env: + C_INCLUDE_PATH: /usr/include + SWIPL: /mingw64/bin/swipl run: | export C_INCLUDE_PATH=/usr/include/ cargo swipl test --all-features --target=x86_64-pc-windows-gnu From 5842396d7847c494dfbd07e2964f67c8c411c700 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Wed, 9 Nov 2022 19:50:21 +0100 Subject: [PATCH 25/36] ci: use windows paths SAD --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 47807f5488..fc3b5b7ca1 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -90,7 +90,7 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} env: C_INCLUDE_PATH: /usr/include - SWIPL: /mingw64/bin/swipl + SWIPL: C:\msys64\mingw64\bin run: | export C_INCLUDE_PATH=/usr/include/ cargo swipl test --all-features --target=x86_64-pc-windows-gnu From c274160b4eaa599020013cde35cf6cceef86c756 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Thu, 10 Nov 2022 10:27:59 +0100 Subject: [PATCH 26/36] Directly use swipl --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index fc3b5b7ca1..40be7d0a41 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -90,7 +90,7 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} env: C_INCLUDE_PATH: /usr/include - SWIPL: C:\msys64\mingw64\bin + SWIPL: C:\msys64\mingw64\bin\swipl run: | export C_INCLUDE_PATH=/usr/include/ cargo swipl test --all-features --target=x86_64-pc-windows-gnu From a225b57cc3e0bfb647b3ea651b1e17f229e11b77 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Thu, 10 Nov 2022 10:36:24 +0100 Subject: [PATCH 27/36] Use different path --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 40be7d0a41..e66b42bf91 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -75,7 +75,7 @@ jobs: - name: Print information with swipl-info on windows if: ${{ matrix.os == 'windows-latest' }} env: - SWIPL: /mingw64/bin/swipl + SWIPL: C:\msys64\mingw64\bin\swipl run: cargo swipl run --bin print_swipl_info - name: Print information with swipl-info on osx with dmg if: ${{ matrix.dmg == 'dmg' }} From ca8409996f40b621b98d6d3c2f05d4ababa02ba6 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Thu, 10 Nov 2022 10:43:06 +0100 Subject: [PATCH 28/36] Use swipl.exe --- .github/workflows/rust.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e66b42bf91..619a95ae6e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -75,7 +75,7 @@ jobs: - name: Print information with swipl-info on windows if: ${{ matrix.os == 'windows-latest' }} env: - SWIPL: C:\msys64\mingw64\bin\swipl + SWIPL: C:\msys64\mingw64\lib\swipl\bin\amd64-windows\swipl.exe run: cargo swipl run --bin print_swipl_info - name: Print information with swipl-info on osx with dmg if: ${{ matrix.dmg == 'dmg' }} @@ -90,7 +90,7 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} env: C_INCLUDE_PATH: /usr/include - SWIPL: C:\msys64\mingw64\bin\swipl + SWIPL: C:\msys64\mingw64\lib\swipl\bin\amd64-windows\swipl.exe run: | export C_INCLUDE_PATH=/usr/include/ cargo swipl test --all-features --target=x86_64-pc-windows-gnu From c08800aececbf77eadc710ec9496126ce6b06743 Mon Sep 17 00:00:00 2001 From: Robin de Rooij Date: Thu, 10 Nov 2022 11:33:09 +0100 Subject: [PATCH 29/36] Try again with different path --- .github/workflows/rust.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 619a95ae6e..f5bfeeee55 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -75,7 +75,7 @@ jobs: - name: Print information with swipl-info on windows if: ${{ matrix.os == 'windows-latest' }} env: - SWIPL: C:\msys64\mingw64\lib\swipl\bin\amd64-windows\swipl.exe + SWIPL: /mingw64/lib/swipl/bin/amd64-windows/swipl.exe run: cargo swipl run --bin print_swipl_info - name: Print information with swipl-info on osx with dmg if: ${{ matrix.dmg == 'dmg' }} @@ -90,7 +90,7 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} env: C_INCLUDE_PATH: /usr/include - SWIPL: C:\msys64\mingw64\lib\swipl\bin\amd64-windows\swipl.exe + SWIPL: /mingw64/lib/swipl/bin/amd64-windows/swipl.exe run: | export C_INCLUDE_PATH=/usr/include/ cargo swipl test --all-features --target=x86_64-pc-windows-gnu From bbfb8730078d3083fa92c7abb50e32d4c182495e Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Fri, 11 Nov 2022 09:51:04 +0100 Subject: [PATCH 30/36] ensure gmp is built against the system library --- swipl/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/swipl/Cargo.toml b/swipl/Cargo.toml index cb2967c63d..fc2a523c61 100644 --- a/swipl/Cargo.toml +++ b/swipl/Cargo.toml @@ -18,9 +18,10 @@ thiserror = "1.0" serde = {version="1.0", optional=true} convert_case = "0.6" rug = {version = "1.17", default-features = false, optional=true, features=["integer","rational"]} +gmp-mpfr-sys = {version = "1.4", optional=true, features=["use-system-libs"]} [dev-dependencies] serde = {version="1.0", features=["derive"]} [features] -rug = ["dep:rug", "swipl-fli/gmp"] \ No newline at end of file +rug = ["dep:rug", "dep:gmp-mpfr-sys", "swipl-fli/gmp"] \ No newline at end of file From 820fb5c1b1053eb6cb2167262661285974ddc5c9 Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Fri, 11 Nov 2022 09:59:24 +0100 Subject: [PATCH 31/36] disable optional features for the gmp-mpfr-sys library --- swipl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swipl/Cargo.toml b/swipl/Cargo.toml index fc2a523c61..7de4ce2a99 100644 --- a/swipl/Cargo.toml +++ b/swipl/Cargo.toml @@ -18,7 +18,7 @@ thiserror = "1.0" serde = {version="1.0", optional=true} convert_case = "0.6" rug = {version = "1.17", default-features = false, optional=true, features=["integer","rational"]} -gmp-mpfr-sys = {version = "1.4", optional=true, features=["use-system-libs"]} +gmp-mpfr-sys = {version = "1.4", default-features = false, optional=true, features=["use-system-libs"]} [dev-dependencies] serde = {version="1.0", features=["derive"]} From 1ee879f0c5adb05423b2d58576dc70540d0a7b58 Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Fri, 11 Nov 2022 10:17:49 +0100 Subject: [PATCH 32/36] try install mingw version for gmp for windows --- .github/workflows/rust.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index f5bfeeee55..352558095e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -60,6 +60,7 @@ jobs: mingw-w64-x86_64-rust mingw-w64-x86_64-swi-prolog mingw-w64-clang-x86_64-toolchain + mingw-w64-x86_64-gmp - name: Install SWI Prolog on MacOS from brew if: ${{ matrix.os == 'macos-latest' && matrix.dmg == 'no_dmg' }} From 81e205238981a408a9569993980615f75c493ff1 Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Fri, 11 Nov 2022 10:38:20 +0100 Subject: [PATCH 33/36] install pkg-config --- .github/workflows/rust.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 352558095e..698338ccd6 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -61,6 +61,7 @@ jobs: mingw-w64-x86_64-swi-prolog mingw-w64-clang-x86_64-toolchain mingw-w64-x86_64-gmp + mingw-w64-x86_64-pkg-config - name: Install SWI Prolog on MacOS from brew if: ${{ matrix.os == 'macos-latest' && matrix.dmg == 'no_dmg' }} From 087bb0a81ecc88a49d1d8f0358e4c797677c003b Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Fri, 11 Nov 2022 11:57:09 +0100 Subject: [PATCH 34/36] serialize atoms using their atom_t only in special cases --- swipl/src/term/ser.rs | 41 ++++++++++++++++++++++++++++++++++++++++- tests/json/src/lib.rs | 14 ++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/swipl/src/term/ser.rs b/swipl/src/term/ser.rs index ec3196fe12..14409366bc 100644 --- a/swipl/src/term/ser.rs +++ b/swipl/src/term/ser.rs @@ -7,6 +7,8 @@ use crate::{atom, functor}; use serde::ser::Impossible; use serde::{self, ser, Serialize}; +use std::cell::Cell; + pub(crate) const ATOM_STRUCT_NAME: &'static str = "$swipl::private::atom"; impl ser::Error for Error { @@ -32,6 +34,7 @@ where T: Serialize, { let serializer = Serializer::new(context, term.clone()); + let _state = SerializingSwiplTermState::start(); obj.serialize(serializer) } @@ -47,6 +50,7 @@ where T: Serialize, { let serializer = Serializer::new_with_config(context, term.clone(), configuration); + let _state = SerializingSwiplTermState::start(); obj.serialize(serializer) } @@ -379,12 +383,47 @@ impl<'a, C: QueryableContextType> serde::Serializer for Serializer<'a, C> { } } +thread_local! { + static SERIALIZING_SWIPL_TERM: Cell = Cell::new(false); +} +struct SerializingSwiplTermState; + +impl SerializingSwiplTermState { + fn start() -> Self { + SERIALIZING_SWIPL_TERM.with(|sst| { + if sst.get() { + panic!("swipl term serialization was already set. did we recurse?"); + } + sst.set(true) + }); + + + Self + } + + fn is_serializing_swipl_term() -> bool { + SERIALIZING_SWIPL_TERM.with(|sst| sst.get()) + } +} + +impl Drop for SerializingSwiplTermState { + fn drop(&mut self) { + SERIALIZING_SWIPL_TERM.with(|sst| sst.set(false)); + } +} + + impl ser::Serialize for Atom { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { - serializer.serialize_newtype_struct(ATOM_STRUCT_NAME, &self.atom_ptr()) + if SerializingSwiplTermState::is_serializing_swipl_term() { + serializer.serialize_newtype_struct(ATOM_STRUCT_NAME, &self.atom_ptr()) + } + else { + serializer.serialize_newtype_struct(ATOM_STRUCT_NAME, &self.name()) + } } } diff --git a/tests/json/src/lib.rs b/tests/json/src/lib.rs index 28c4905736..987e8b497f 100644 --- a/tests/json/src/lib.rs +++ b/tests/json/src/lib.rs @@ -59,4 +59,18 @@ mod tests { assert_eq!(atom!("hello"), atom); } + + #[test] + fn serialize_atom_to_json() { + let engine = Engine::new(); + let activation = engine.activate(); + let _context: Context<_> = activation.into(); + + let atom = atom!("hello"); + let expected = json!("hello"); + + let json = serde_json::to_value(atom).unwrap(); + + assert_eq!(expected, json); + } } From f698cae43faf7aea1e97c1da05736d1938d35c00 Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Fri, 11 Nov 2022 12:03:04 +0100 Subject: [PATCH 35/36] change error back from debug version to normal --- swipl/src/term/de.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swipl/src/term/de.rs b/swipl/src/term/de.rs index 36b56e8f1c..b6745218e3 100644 --- a/swipl/src/term/de.rs +++ b/swipl/src/term/de.rs @@ -459,7 +459,7 @@ impl<'de, C: QueryableContextType> de::Deserializer<'de> for Deserializer<'de, C Err(Error::ValueOutOfRange) } } - None => Err(Error::ValueNotOfExpectedType("u64 (x)")), + None => Err(Error::ValueNotOfExpectedType("u64")), } } fn deserialize_f32(self, visitor: V) -> Result From b45f4c9d4becc1a2ce5fda74355a4aedb659b0a0 Mon Sep 17 00:00:00 2001 From: Matthijs van Otterdijk Date: Tue, 17 Jan 2023 17:59:32 +0100 Subject: [PATCH 36/36] work --- swipl-fli/build.rs | 3 ++- swipl/src/dict.rs | 2 +- swipl/src/result.rs | 2 +- swipl/src/term/bignum.rs | 31 +++++++++++++++++++++--- swipl/src/term/bignum/de.rs | 47 ++++++++++++++++++++++++++++++++++++ swipl/src/term/bignum/ser.rs | 18 ++++++++++++++ swipl/src/term/de.rs | 23 +++++++----------- swipl/src/term/ser.rs | 6 +---- 8 files changed, 106 insertions(+), 26 deletions(-) create mode 100644 swipl/src/term/bignum/de.rs create mode 100644 swipl/src/term/bignum/ser.rs diff --git a/swipl-fli/build.rs b/swipl-fli/build.rs index 5a020ad22c..329e871dc9 100644 --- a/swipl-fli/build.rs +++ b/swipl-fli/build.rs @@ -15,7 +15,8 @@ fn main() { bindings = bindings.header_contents("include_gmp", "#include \n"); } - let bindings = bindings.header("c/wrapper.h") + let bindings = bindings + .header("c/wrapper.h") .clang_arg(format!("-I{}", info.header_dir)) .parse_callbacks(Box::new(bindgen::CargoCallbacks)) .generate() diff --git a/swipl/src/dict.rs b/swipl/src/dict.rs index 0d6c9dc977..585adcb3c7 100644 --- a/swipl/src/dict.rs +++ b/swipl/src/dict.rs @@ -673,7 +673,7 @@ mod tests { dict.unify(&builder).unwrap(); - assert_eq!(42_u64, dict.get_dict_key::<_,u64>("foo").unwrap()); + assert_eq!(42_u64, dict.get_dict_key::<_, u64>("foo").unwrap()); let hello_str: String = dict.get_dict_key("bar").unwrap(); assert_eq!("hello", hello_str); diff --git a/swipl/src/result.rs b/swipl/src/result.rs index 8d13f0d858..411b900d61 100644 --- a/swipl/src/result.rs +++ b/swipl/src/result.rs @@ -16,7 +16,7 @@ use crate::context::{Context, QueryableContextType}; /// This is either a failure or an exception. In case of an exception, /// whowever returned the exception was also supposed to raise an /// exception on the context. -#[derive(Error, Debug)] +#[derive(Error, Debug, PartialEq, Eq)] pub enum PrologError { #[error("prolog function failed")] Failure, diff --git a/swipl/src/term/bignum.rs b/swipl/src/term/bignum.rs index fe6289715e..75969f3ae9 100644 --- a/swipl/src/term/bignum.rs +++ b/swipl/src/term/bignum.rs @@ -1,8 +1,8 @@ //! Support for rug Integer and Rational using SWI-Prolog's GMP support. -use crate::{term_getable, unifiable}; -use crate::term::*; use crate::fli; +use crate::term::*; +use crate::{term_getable, unifiable}; use rug::{Integer, Rational}; term_getable! { @@ -36,6 +36,7 @@ unifiable! { term_getable! { (Rational, "bigrat", term) => { + eprintln!("hi"); let mut r = Rational::new(); let ptr = r.as_raw_mut(); @@ -65,9 +66,9 @@ unifiable! { #[cfg(test)] mod tests { - use std::str::FromStr; - use crate::context::*; use super::*; + use crate::context::*; + use std::str::FromStr; #[test] fn get_bigint() { let engine = Engine::new(); @@ -137,4 +138,26 @@ mod tests { assert_eq!(big_rat_prolog_string, s); } + + #[test] + fn unify_unequal_bigrat_fails() { + let engine = Engine::new(); + let activation = engine.activate(); + let context: Context<_> = activation.into(); + + let big_numerator = "1234123412341234123412341234123412341234"; + let big_prime_str = "19131612631094571991039"; + let big_rat_prolog_string = format!("{big_numerator}r{big_prime_str}"); + let big_rat_div_string = format!("{big_numerator}/{big_prime_str}"); + let i = Rational::from_str(&big_rat_div_string).unwrap(); + let i2: Rational = i.clone() + 1; + + let term = context.new_term_ref(); + term.unify(&i).unwrap(); + assert!(term.unify(&i2).unwrap_err().is_failure()); + + let s = context.string_from_term(&term).unwrap(); + + assert_eq!(big_rat_prolog_string, s); + } } diff --git a/swipl/src/term/bignum/de.rs b/swipl/src/term/bignum/de.rs new file mode 100644 index 0000000000..a0219675db --- /dev/null +++ b/swipl/src/term/bignum/de.rs @@ -0,0 +1,47 @@ +impl<'de> Deserialize<'de> for BigInt { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de> { + deserializer.deserialize_str(BigIntDeserializationVisitor) + } +} + +struct BigIntDeserializationVisitor; + +impl<'de> Visitor<'de> for BigIntDeserializationVisitor { + type Value = BigInt; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "bigint") + } + + fn visit_str(self, v: &str) -> Result { + Integer::from_str(v) + .map(|i| BigInt(i)) + .map_err(|_e| E::custom(format!("{v} did not parse to a bigint"))) + } +} + +impl<'de> Deserialize<'de> for BigRat { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de> { + deserializer.deserialize_str(BigRatDeserializationVisitor) + } +} + +struct BigRatDeserializationVisitor; + +impl<'de> Visitor<'de> for BigRatDeserializationVisitor { + type Value = BigRat; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "bigrat") + } + + fn visit_str(self, v: &str) -> Result { + Rational::from_str(v) + .map(|i| BigRat(i)) + .map_err(|_e| E::custom(format!("{v} did not parse to a bigrat"))) + } +} diff --git a/swipl/src/term/bignum/ser.rs b/swipl/src/term/bignum/ser.rs new file mode 100644 index 0000000000..ab71601bf1 --- /dev/null +++ b/swipl/src/term/bignum/ser.rs @@ -0,0 +1,18 @@ +impl Serialize for BigInt { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer { + let s = self.0.to_string(); + serializer.serialize_str(&s) + } +} + +impl Serialize for BigRat { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer { + let s = self.0.to_string(); + serializer.serialize_str(&s) + } +} + diff --git a/swipl/src/term/de.rs b/swipl/src/term/de.rs index b6745218e3..651b58fd7c 100644 --- a/swipl/src/term/de.rs +++ b/swipl/src/term/de.rs @@ -7,8 +7,8 @@ use crate::text::*; use crate::{atom, functor}; use serde::de::{self, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, VariantAccess, Visitor}; use serde::Deserialize; -use std::fmt::{self, Display}; use std::cell::Cell; +use std::fmt::{self, Display}; /// Deserialize a term into a rust value using serde. pub fn from_term<'a, C: QueryableContextType, T>( @@ -587,15 +587,13 @@ impl<'de, C: QueryableContextType> de::Deserializer<'de> for Deserializer<'de, C Some(atom) => { if cfg!(target_pointer_width = "32") { visitor.visit_u32(atom.atom_ptr() as u32) - } - else { + } else { visitor.visit_u64(atom.atom_ptr() as u64) } - }, - None => Err(Error::ValueNotOfExpectedType("atom")) + } + None => Err(Error::ValueNotOfExpectedType("atom")), } - } - else { + } else { self.deserialize_string(visitor) } } else { @@ -968,15 +966,13 @@ impl<'de> de::Deserializer<'de> for KeyDeserializer { Key::Atom(atom) => { if cfg!(target_pointer_width = "32") { visitor.visit_u32(atom.atom_ptr() as u32) - } - else { + } else { visitor.visit_u64(atom.atom_ptr() as u64) } - }, - _ => Err(Error::ValueNotOfExpectedType("atom")) + } + _ => Err(Error::ValueNotOfExpectedType("atom")), } - } - else { + } else { self.deserialize_string(visitor) } } else { @@ -1267,7 +1263,6 @@ impl DeserializingAtomState { da.set(true) }); - Self } diff --git a/swipl/src/term/ser.rs b/swipl/src/term/ser.rs index 14409366bc..f85dd4fdb4 100644 --- a/swipl/src/term/ser.rs +++ b/swipl/src/term/ser.rs @@ -93,7 +93,6 @@ impl SerializerConfiguration { self.default_tag = Some(tag.as_atom()); } - /// Set the default tag to use for dictionaries. /// /// This is used when serializing maps. By default, this tag will @@ -397,7 +396,6 @@ impl SerializingSwiplTermState { sst.set(true) }); - Self } @@ -412,7 +410,6 @@ impl Drop for SerializingSwiplTermState { } } - impl ser::Serialize for Atom { fn serialize(&self, serializer: S) -> Result where @@ -420,8 +417,7 @@ impl ser::Serialize for Atom { { if SerializingSwiplTermState::is_serializing_swipl_term() { serializer.serialize_newtype_struct(ATOM_STRUCT_NAME, &self.atom_ptr()) - } - else { + } else { serializer.serialize_newtype_struct(ATOM_STRUCT_NAME, &self.name()) } }