From 21ce7943e79c3e83b7fbed1ef7068f9813726d96 Mon Sep 17 00:00:00 2001 From: shubhamnarlawar Date: Wed, 17 Feb 2021 23:50:34 +0530 Subject: [PATCH 1/7] Add support for Array TypeChecker --- runtime/src/lib.rs | 129 +++++++++++++++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 35 deletions(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 79a64e2cd..eb1b22656 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -19,84 +19,143 @@ // Rust Library +use std::ffi::CStr; use std::mem; use std::os::raw::c_char; -// String comparision +pub fn compute_size(type_string: &str) -> i32 { + let mut bits = String::new(); + //Index 2 and 3 represent the size + bits.push(type_string.chars().nth(2).unwrap()); + bits.push(type_string.chars().nth(3).unwrap()); + let total_bits: i32 = bits.parse().unwrap(); + let mut length_bits = String::new(); + let index = 4; + for i in 0..total_bits { + let iterator = i as usize; + length_bits.push(type_string.chars().nth(iterator + index).unwrap()); + } + //Convert size to i32 for integer comparision + let size: i32 = length_bits.parse().unwrap(); + return size; +} + +pub fn calculate_type_priority(type_string: &str) -> i32 { + let mut priority = 0; + match type_string.chars().nth(1) { + Some('C') => priority = 4, + Some('B') => priority = 1, + Some('F') | Some('I') => priority = 8, + Some('A') => priority = 16, + _ => println!("Unsupported type"), + } + return priority; +} + +/* + * Algorithm for checking whether typecast is possible from source to destination + * Index 0 - represents data structure + * Index 1 - represents type + * Index 2 and 3 - represents bits followed by its size + * */ #[no_mangle] -pub extern "C" fn is_same_type(src_type : *const c_char, dest_type : *const c_char) -> bool -{ - return src_type == dest_type; +pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char) -> bool { + //Conversion to CStr + let source_cstr: &CStr = unsafe { CStr::from_ptr(src_type) }; + let dest_cstr: &CStr = unsafe { CStr::from_ptr(dest_type) }; + //Conversion to rust strings + let source: String = source_cstr.to_str().unwrap().to_owned(); + let destination: String = dest_cstr.to_str().unwrap().to_owned(); + //If type strings are same + if source == destination { + return true; + } + //Index 0 represents type of data structure + if source.chars().nth(0) != destination.chars().nth(0) { + return false; + } + let mut src_priority = 0; + let mut dest_priority = 0; + match source.chars().nth(0) { + Some('A') => { + if source.chars().nth(1) != destination.chars().nth(1) { + src_priority = calculate_type_priority(&source); + dest_priority = calculate_type_priority(&destination); + } + // If source type is bigger than destination, type cast is not possible + if src_priority > dest_priority { + return false; + } + let src_size: i32 = compute_size(&source); + let dest_size: i32 = compute_size(&destination); + if src_size > dest_size { + return false; + } + } + _ => println!("Unsupported data structure"), + } + //If all the checks are passed, type cast from source to destination is valid + return true; } // Prints 64 bit signed integer #[no_mangle] -pub extern "C" fn print64(num64 : i64) -{ - println!("{}", num64); +pub extern "C" fn print64(num64: i64) { + println!("{}", num64); } // Prints 32 bit signed integer #[no_mangle] -pub extern "C" fn print32(num32 : i32) -{ - println!("{}", num32); +pub extern "C" fn print32(num32: i32) { + println!("{}", num32); } // Prints 16 bit signed integer #[no_mangle] -pub extern "C" fn print16(num16 : i16) -{ - println!("{}", num16); +pub extern "C" fn print16(num16: i16) { + println!("{}", num16); } // Prints 8 bit signed integer #[no_mangle] -pub extern "C" fn print8(num8 : i8) -{ - println!("{}", num8); +pub extern "C" fn print8(num8: i8) { + println!("{}", num8); } // Prints 64 bit unsigned integer #[no_mangle] -pub extern "C" fn printu64(num64 : u64) -{ - println!("{}", num64); +pub extern "C" fn printu64(num64: u64) { + println!("{}", num64); } // Prints 32 bit unsigned integer #[no_mangle] -pub extern "C" fn printu32(num32 : u32) -{ - println!("{}", num32); +pub extern "C" fn printu32(num32: u32) { + println!("{}", num32); } // Prints 16 bit unsigned integer #[no_mangle] -pub extern "C" fn printu16(num16 : u16) -{ - println!("{}", num16); +pub extern "C" fn printu16(num16: u16) { + println!("{}", num16); } // Prints 8 bit unsigned integer #[no_mangle] -pub extern "C" fn printu8(num8 : u8) -{ - println!("{}", num8); +pub extern "C" fn printu8(num8: u8) { + println!("{}", num8); } // Prints 64 bit float #[no_mangle] -pub extern "C" fn printf64(num64 : f64) -{ - println!("{}", num64); +pub extern "C" fn printf64(num64: f64) { + println!("{}", num64); } // Prints 32 bit float #[no_mangle] -pub extern "C" fn printf32(num32 : f32) -{ - println!("{}", num32); +pub extern "C" fn printf32(num32: f32) { + println!("{}", num32); } #[no_mangle] @@ -125,7 +184,7 @@ pub extern "C" fn int_array_store(arr_ptr: *mut Vec<*mut i32>, n: i32, ref_ptr: #[no_mangle] pub extern "C" fn int_array_load(arr_ptr: *mut Vec<*mut i32>, n: i32) -> *mut i32 { - let arr = unsafe { Box::from_raw(arr_ptr)}; + let arr = unsafe { Box::from_raw(arr_ptr) }; let n_size = n as usize; let return_val = arr[n_size]; mem::forget(arr); From e12de3693e984a179500f4eb7a9380ba58a8394a Mon Sep 17 00:00:00 2001 From: shubhamnarlawar Date: Sun, 21 Feb 2021 20:18:59 +0530 Subject: [PATCH 2/7] Update lib.rs --- runtime/src/lib.rs | 73 +++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index eb1b22656..d8606bdc0 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -23,12 +23,19 @@ use std::ffi::CStr; use std::mem; use std::os::raw::c_char; +pub const BASE_TYPE_INDX: usize = 0; +pub const ARRAY_MEMBER_TYPE_INDX: usize = 1; +pub const ARRAY_SIZE_LSB_INDX: usize = 2; +pub const ARRAY_SIZE_MSB_INDX: usize = 3; + pub fn compute_size(type_string: &str) -> i32 { - let mut bits = String::new(); + let mut hex_bits = String::new(); //Index 2 and 3 represent the size - bits.push(type_string.chars().nth(2).unwrap()); - bits.push(type_string.chars().nth(3).unwrap()); - let total_bits: i32 = bits.parse().unwrap(); + hex_bits.push(type_string.chars().nth(ARRAY_SIZE_LSB_INDX).unwrap()); + hex_bits.push(type_string.chars().nth(ARRAY_SIZE_MSB_INDX).unwrap()); + let bits: std::result::Result = + i32::from_str_radix(&hex_bits, 32); + let total_bits: i32 = bits.unwrap(); let mut length_bits = String::new(); let index = 4; for i in 0..total_bits { @@ -40,16 +47,35 @@ pub fn compute_size(type_string: &str) -> i32 { return size; } -pub fn calculate_type_priority(type_string: &str) -> i32 { - let mut priority = 0; - match type_string.chars().nth(1) { - Some('C') => priority = 4, - Some('B') => priority = 1, - Some('F') | Some('I') => priority = 8, - Some('A') => priority = 16, - _ => println!("Unsupported type"), +/* + * Type Notations - + * C represents character + * B represents boolean + * F represents float + * I represents integer + * S represents string + * X represents any*/ +pub fn calculate_type_priority(type_string: &str) -> Result { + let priority: i32; + match type_string.chars().nth(ARRAY_MEMBER_TYPE_INDX) { + Some('C') | Some('B') => { + priority = 1; + Ok(priority) + } + Some('F') | Some('I') => { + priority = 8; + Ok(priority) + } + Some('S') => { + priority = 12; + Ok(priority) + } + Some('X') => { + priority = 16; + Ok(priority) + } + _ => Err("Unsupported type"), } - return priority; } /* @@ -60,6 +86,8 @@ pub fn calculate_type_priority(type_string: &str) -> i32 { * */ #[no_mangle] pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char) -> bool { + assert!(!src_type.is_null()); + assert!(!dest_type.is_null()); //Conversion to CStr let source_cstr: &CStr = unsafe { CStr::from_ptr(src_type) }; let dest_cstr: &CStr = unsafe { CStr::from_ptr(dest_type) }; @@ -71,19 +99,24 @@ pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char return true; } //Index 0 represents type of data structure - if source.chars().nth(0) != destination.chars().nth(0) { + if source.chars().nth(BASE_TYPE_INDX) != destination.chars().nth(BASE_TYPE_INDX) { return false; } - let mut src_priority = 0; - let mut dest_priority = 0; - match source.chars().nth(0) { + let mut src_priority: Result = Ok(0); + let mut dest_priority: Result = Ok(0); + match source.chars().nth(BASE_TYPE_INDX) { Some('A') => { - if source.chars().nth(1) != destination.chars().nth(1) { + if source.chars().nth(ARRAY_MEMBER_TYPE_INDX) + != destination.chars().nth(ARRAY_MEMBER_TYPE_INDX) + { src_priority = calculate_type_priority(&source); dest_priority = calculate_type_priority(&destination); + if src_priority.is_err() || dest_priority.is_err() { + panic!("Unsupported type"); + } } // If source type is bigger than destination, type cast is not possible - if src_priority > dest_priority { + if src_priority.unwrap() > dest_priority.unwrap() { return false; } let src_size: i32 = compute_size(&source); @@ -92,7 +125,7 @@ pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char return false; } } - _ => println!("Unsupported data structure"), + _ => return false, } //If all the checks are passed, type cast from source to destination is valid return true; From 04db3f133f6a742f925e3ccc3d67f68b68e7dcd2 Mon Sep 17 00:00:00 2001 From: shubhamnarlawar Date: Tue, 23 Feb 2021 00:12:42 +0530 Subject: [PATCH 3/7] Document lib.rs --- runtime/src/lib.rs | 52 ++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index d8606bdc0..04bdb4677 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -28,6 +28,7 @@ pub const ARRAY_MEMBER_TYPE_INDX: usize = 1; pub const ARRAY_SIZE_LSB_INDX: usize = 2; pub const ARRAY_SIZE_MSB_INDX: usize = 3; +// Compute total elements present in the data structure pub fn compute_size(type_string: &str) -> i32 { let mut hex_bits = String::new(); //Index 2 and 3 represent the size @@ -48,6 +49,7 @@ pub fn compute_size(type_string: &str) -> i32 { } /* + * Computes size of the type * Type Notations - * C represents character * B represents boolean @@ -55,34 +57,47 @@ pub fn compute_size(type_string: &str) -> i32 { * I represents integer * S represents string * X represents any*/ -pub fn calculate_type_priority(type_string: &str) -> Result { - let priority: i32; +pub fn type_size(type_string: &str) -> Result { + let size: i32; match type_string.chars().nth(ARRAY_MEMBER_TYPE_INDX) { Some('C') | Some('B') => { - priority = 1; - Ok(priority) + size = 1; + Ok(size) } Some('F') | Some('I') => { - priority = 8; - Ok(priority) + size = 8; + Ok(size) } Some('S') => { - priority = 12; - Ok(priority) + size = 12; + Ok(size) } Some('X') => { - priority = 16; - Ok(priority) + size = 16; + Ok(size) } _ => Err("Unsupported type"), } } /* - * Algorithm for checking whether typecast is possible from source to destination + * To checking whether typecast is possible from source to destination + * Example of a type string - "AI041024" * Index 0 - represents data structure * Index 1 - represents type - * Index 2 and 3 - represents bits followed by its size + * Index 2 and 3 - represents bits in hex followed by its size in decimal + * + * Algorithm - + * a. Convert null terminated string to rust string. + * b. Return true if type strings are same. + * c. Return false if data structure is different. + * d. Compute type size - type_size() + * e. Return false if source type size > destination type size + * g. Compute data structure length - compute_length() + * + * Data Structure Notations - + * A - Array + * M - Map * */ #[no_mangle] pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char) -> bool { @@ -102,23 +117,24 @@ pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char if source.chars().nth(BASE_TYPE_INDX) != destination.chars().nth(BASE_TYPE_INDX) { return false; } - let mut src_priority: Result = Ok(0); - let mut dest_priority: Result = Ok(0); + let mut src_type_size: Result = Ok(0); + let mut dest_type_size: Result = Ok(0); match source.chars().nth(BASE_TYPE_INDX) { Some('A') => { if source.chars().nth(ARRAY_MEMBER_TYPE_INDX) != destination.chars().nth(ARRAY_MEMBER_TYPE_INDX) { - src_priority = calculate_type_priority(&source); - dest_priority = calculate_type_priority(&destination); - if src_priority.is_err() || dest_priority.is_err() { + src_type_size = type_size(&source); + dest_type_size = type_size(&destination); + if src_type_size.is_err() || dest_type_size.is_err() { panic!("Unsupported type"); } } // If source type is bigger than destination, type cast is not possible - if src_priority.unwrap() > dest_priority.unwrap() { + if src_type_size.unwrap() > dest_type_size.unwrap() { return false; } + // Compute total number of elements present in the data structure let src_size: i32 = compute_size(&source); let dest_size: i32 = compute_size(&destination); if src_size > dest_size { From 07bed0381a52126b9119f00e47dff281df09297f Mon Sep 17 00:00:00 2001 From: shubhamnarlawar Date: Wed, 24 Feb 2021 21:42:46 +0530 Subject: [PATCH 4/7] Add tests to check is_same_type() --- runtime/src/lib.rs | 81 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 04bdb4677..4fb6d002c 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -20,6 +20,7 @@ // Rust Library use std::ffi::CStr; +use std::ffi::CString; use std::mem; use std::os::raw::c_char; @@ -49,7 +50,7 @@ pub fn compute_size(type_string: &str) -> i32 { } /* - * Computes size of the type + * Returns size of the type * Type Notations - * C represents character * B represents boolean @@ -239,3 +240,81 @@ pub extern "C" fn int_array_load(arr_ptr: *mut Vec<*mut i32>, n: i32) -> *mut i3 mem::forget(arr); return return_val; } + +#[test] +fn src_type_size_less_than_dest() { + let src = CString::new("AF03122").unwrap(); + let dest = CString::new("AX03122").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + true + ); +} + +#[test] +fn src_type_size_greater_than_dest() { + let src = CString::new("AS03122").unwrap(); + let dest = CString::new("AB03122").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + false + ); +} + +#[test] +fn src_elements_less_than_dest() { + let src = CString::new("AB041023").unwrap(); + let dest = CString::new("AX041024").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + true + ); +} + +#[test] +fn src_elements_greater_than_dest() { + let src = CString::new("AC0519999").unwrap(); + let dest = CString::new("AX03199").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + false + ); +} + +#[test] +fn src_type_string_equal_to_dest() { + let src = CString::new("AF0599999").unwrap(); + let dest = CString::new("AF0599999").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + true + ); +} + +#[test] +fn map_test() { + let src = CString::new("MX0599999").unwrap(); + let dest = CString::new("MF0599999").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + false + ); +} From a90e7b6eaba01b62815cef6a64720334edbd5cce Mon Sep 17 00:00:00 2001 From: shubhamnarlawar Date: Mon, 1 Mar 2021 20:13:57 +0530 Subject: [PATCH 5/7] Update type_size() --- runtime/Cargo.toml | 3 ++ runtime/src/lib.rs | 100 +++++++++++++++++++++++---------------------- 2 files changed, 54 insertions(+), 49 deletions(-) diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index d1355dd76..03ad32e5e 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -11,3 +11,6 @@ name = "nballerinart" crate-type = ["cdylib"] [dependencies] +num = "0.3" +num-traits = "0.2" +num-derive = "0.3" diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 4fb6d002c..c34d91b1d 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -19,22 +19,40 @@ // Rust Library +extern crate num; +extern crate num_derive; + +use num::FromPrimitive; +use num_derive::FromPrimitive; use std::ffi::CStr; use std::ffi::CString; use std::mem; use std::os::raw::c_char; -pub const BASE_TYPE_INDX: usize = 0; -pub const ARRAY_MEMBER_TYPE_INDX: usize = 1; -pub const ARRAY_SIZE_LSB_INDX: usize = 2; -pub const ARRAY_SIZE_MSB_INDX: usize = 3; +const BASE_TYPE_INDEX: usize = 0; +const ARRAY_MEMBER_TYPE_INDEX: usize = 1; +const ARRAY_SIZE_LSB_INDEX: usize = 2; +const ARRAY_SIZE_MSB_INDEX: usize = 3; + +#[derive(Debug, PartialEq, FromPrimitive)] +#[repr(u32)] +enum BalType { + Nil = 'N' as u32, + Boolean = 'B' as u32, + Int = 'I' as u32, + Float = 'F' as u32, + Decimal = 'D' as u32, + String = 'S' as u32, + Array = 'A' as u32, + Any = 'X' as u32, +} // Compute total elements present in the data structure pub fn compute_size(type_string: &str) -> i32 { let mut hex_bits = String::new(); //Index 2 and 3 represent the size - hex_bits.push(type_string.chars().nth(ARRAY_SIZE_LSB_INDX).unwrap()); - hex_bits.push(type_string.chars().nth(ARRAY_SIZE_MSB_INDX).unwrap()); + hex_bits.push(type_string.chars().nth(ARRAY_SIZE_LSB_INDEX).unwrap()); + hex_bits.push(type_string.chars().nth(ARRAY_SIZE_MSB_INDEX).unwrap()); let bits: std::result::Result = i32::from_str_radix(&hex_bits, 32); let total_bits: i32 = bits.unwrap(); @@ -49,35 +67,25 @@ pub fn compute_size(type_string: &str) -> i32 { return size; } -/* - * Returns size of the type - * Type Notations - - * C represents character - * B represents boolean - * F represents float - * I represents integer - * S represents string - * X represents any*/ -pub fn type_size(type_string: &str) -> Result { - let size: i32; - match type_string.chars().nth(ARRAY_MEMBER_TYPE_INDX) { - Some('C') | Some('B') => { - size = 1; - Ok(size) - } - Some('F') | Some('I') => { - size = 8; - Ok(size) +pub fn type_size(type_string: &str) -> i32 { + let type_char = type_string + .chars() + .nth(ARRAY_MEMBER_TYPE_INDEX) + .unwrap_or_else(|| panic!("Illegal type descriptor '{}', wrong length", type_string)); + let bal_type = FromPrimitive::from_u32(type_char as u32).unwrap_or_else(|| { + panic!( + "Illegal type tag '{}' in type descriptor '{}'", + type_char, type_string + ) + }); + match bal_type { + BalType::Boolean => 1, + BalType::Int | BalType::Float => 8, + BalType::String => 12, + BalType::Any => 16, + _ => { + unimplemented!("type_size for '{:?}'", bal_type) } - Some('S') => { - size = 12; - Ok(size) - } - Some('X') => { - size = 16; - Ok(size) - } - _ => Err("Unsupported type"), } } @@ -115,26 +123,20 @@ pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char return true; } //Index 0 represents type of data structure - if source.chars().nth(BASE_TYPE_INDX) != destination.chars().nth(BASE_TYPE_INDX) { + if source.chars().nth(BASE_TYPE_INDEX) != destination.chars().nth(BASE_TYPE_INDEX) { return false; } - let mut src_type_size: Result = Ok(0); - let mut dest_type_size: Result = Ok(0); - match source.chars().nth(BASE_TYPE_INDX) { + match source.chars().nth(BASE_TYPE_INDEX) { Some('A') => { - if source.chars().nth(ARRAY_MEMBER_TYPE_INDX) - != destination.chars().nth(ARRAY_MEMBER_TYPE_INDX) + if source.chars().nth(ARRAY_MEMBER_TYPE_INDEX) + != destination.chars().nth(ARRAY_MEMBER_TYPE_INDEX) { - src_type_size = type_size(&source); - dest_type_size = type_size(&destination); - if src_type_size.is_err() || dest_type_size.is_err() { - panic!("Unsupported type"); + let src_type_size: i32 = type_size(&source); + let dest_type_size: i32 = type_size(&destination); + if src_type_size > dest_type_size { + return false; } } - // If source type is bigger than destination, type cast is not possible - if src_type_size.unwrap() > dest_type_size.unwrap() { - return false; - } // Compute total number of elements present in the data structure let src_size: i32 = compute_size(&source); let dest_size: i32 = compute_size(&destination); @@ -282,7 +284,7 @@ fn src_elements_less_than_dest() { #[test] fn src_elements_greater_than_dest() { - let src = CString::new("AC0519999").unwrap(); + let src = CString::new("AB0519999").unwrap(); let dest = CString::new("AX03199").unwrap(); assert_eq!( is_same_type( From 4fff6b4929c032476ae5110773d9eea4a9ec8eea Mon Sep 17 00:00:00 2001 From: shubhamnarlawar Date: Wed, 3 Mar 2021 14:00:01 +0530 Subject: [PATCH 6/7] Add new module type_checker.rs --- runtime/src/lib.rs | 163 +++------------------------------- runtime/src/type_checker.rs | 168 ++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 149 deletions(-) create mode 100644 runtime/src/type_checker.rs diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index c34d91b1d..3dad1d8e8 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -22,73 +22,12 @@ extern crate num; extern crate num_derive; -use num::FromPrimitive; -use num_derive::FromPrimitive; +mod type_checker; + use std::ffi::CStr; -use std::ffi::CString; use std::mem; use std::os::raw::c_char; -const BASE_TYPE_INDEX: usize = 0; -const ARRAY_MEMBER_TYPE_INDEX: usize = 1; -const ARRAY_SIZE_LSB_INDEX: usize = 2; -const ARRAY_SIZE_MSB_INDEX: usize = 3; - -#[derive(Debug, PartialEq, FromPrimitive)] -#[repr(u32)] -enum BalType { - Nil = 'N' as u32, - Boolean = 'B' as u32, - Int = 'I' as u32, - Float = 'F' as u32, - Decimal = 'D' as u32, - String = 'S' as u32, - Array = 'A' as u32, - Any = 'X' as u32, -} - -// Compute total elements present in the data structure -pub fn compute_size(type_string: &str) -> i32 { - let mut hex_bits = String::new(); - //Index 2 and 3 represent the size - hex_bits.push(type_string.chars().nth(ARRAY_SIZE_LSB_INDEX).unwrap()); - hex_bits.push(type_string.chars().nth(ARRAY_SIZE_MSB_INDEX).unwrap()); - let bits: std::result::Result = - i32::from_str_radix(&hex_bits, 32); - let total_bits: i32 = bits.unwrap(); - let mut length_bits = String::new(); - let index = 4; - for i in 0..total_bits { - let iterator = i as usize; - length_bits.push(type_string.chars().nth(iterator + index).unwrap()); - } - //Convert size to i32 for integer comparision - let size: i32 = length_bits.parse().unwrap(); - return size; -} - -pub fn type_size(type_string: &str) -> i32 { - let type_char = type_string - .chars() - .nth(ARRAY_MEMBER_TYPE_INDEX) - .unwrap_or_else(|| panic!("Illegal type descriptor '{}', wrong length", type_string)); - let bal_type = FromPrimitive::from_u32(type_char as u32).unwrap_or_else(|| { - panic!( - "Illegal type tag '{}' in type descriptor '{}'", - type_char, type_string - ) - }); - match bal_type { - BalType::Boolean => 1, - BalType::Int | BalType::Float => 8, - BalType::String => 12, - BalType::Any => 16, - _ => { - unimplemented!("type_size for '{:?}'", bal_type) - } - } -} - /* * To checking whether typecast is possible from source to destination * Example of a type string - "AI041024" @@ -123,23 +62,27 @@ pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char return true; } //Index 0 represents type of data structure - if source.chars().nth(BASE_TYPE_INDEX) != destination.chars().nth(BASE_TYPE_INDEX) { + if source.chars().nth(type_checker::BASE_TYPE_INDEX) + != destination.chars().nth(type_checker::BASE_TYPE_INDEX) + { return false; } - match source.chars().nth(BASE_TYPE_INDEX) { + match source.chars().nth(type_checker::BASE_TYPE_INDEX) { Some('A') => { - if source.chars().nth(ARRAY_MEMBER_TYPE_INDEX) - != destination.chars().nth(ARRAY_MEMBER_TYPE_INDEX) + if source.chars().nth(type_checker::ARRAY_MEMBER_TYPE_INDEX) + != destination + .chars() + .nth(type_checker::ARRAY_MEMBER_TYPE_INDEX) { - let src_type_size: i32 = type_size(&source); - let dest_type_size: i32 = type_size(&destination); + let src_type_size: i32 = type_checker::type_size(&source); + let dest_type_size: i32 = type_checker::type_size(&destination); if src_type_size > dest_type_size { return false; } } // Compute total number of elements present in the data structure - let src_size: i32 = compute_size(&source); - let dest_size: i32 = compute_size(&destination); + let src_size: i32 = type_checker::compute_size(&source); + let dest_size: i32 = type_checker::compute_size(&destination); if src_size > dest_size { return false; } @@ -242,81 +185,3 @@ pub extern "C" fn int_array_load(arr_ptr: *mut Vec<*mut i32>, n: i32) -> *mut i3 mem::forget(arr); return return_val; } - -#[test] -fn src_type_size_less_than_dest() { - let src = CString::new("AF03122").unwrap(); - let dest = CString::new("AX03122").unwrap(); - assert_eq!( - is_same_type( - src.as_ptr() as *const c_char, - dest.as_ptr() as *const c_char - ), - true - ); -} - -#[test] -fn src_type_size_greater_than_dest() { - let src = CString::new("AS03122").unwrap(); - let dest = CString::new("AB03122").unwrap(); - assert_eq!( - is_same_type( - src.as_ptr() as *const c_char, - dest.as_ptr() as *const c_char - ), - false - ); -} - -#[test] -fn src_elements_less_than_dest() { - let src = CString::new("AB041023").unwrap(); - let dest = CString::new("AX041024").unwrap(); - assert_eq!( - is_same_type( - src.as_ptr() as *const c_char, - dest.as_ptr() as *const c_char - ), - true - ); -} - -#[test] -fn src_elements_greater_than_dest() { - let src = CString::new("AB0519999").unwrap(); - let dest = CString::new("AX03199").unwrap(); - assert_eq!( - is_same_type( - src.as_ptr() as *const c_char, - dest.as_ptr() as *const c_char - ), - false - ); -} - -#[test] -fn src_type_string_equal_to_dest() { - let src = CString::new("AF0599999").unwrap(); - let dest = CString::new("AF0599999").unwrap(); - assert_eq!( - is_same_type( - src.as_ptr() as *const c_char, - dest.as_ptr() as *const c_char - ), - true - ); -} - -#[test] -fn map_test() { - let src = CString::new("MX0599999").unwrap(); - let dest = CString::new("MF0599999").unwrap(); - assert_eq!( - is_same_type( - src.as_ptr() as *const c_char, - dest.as_ptr() as *const c_char - ), - false - ); -} diff --git a/runtime/src/type_checker.rs b/runtime/src/type_checker.rs new file mode 100644 index 000000000..c2cde9860 --- /dev/null +++ b/runtime/src/type_checker.rs @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +// Rust Library + +extern crate num; +extern crate num_derive; + +use crate::is_same_type; + +use num::FromPrimitive; +use num_derive::FromPrimitive; +use std::ffi::CString; +use std::os::raw::c_char; + +pub const BASE_TYPE_INDEX: usize = 0; +pub const ARRAY_MEMBER_TYPE_INDEX: usize = 1; +pub const ARRAY_SIZE_LSB_INDEX: usize = 2; +pub const ARRAY_SIZE_MSB_INDEX: usize = 3; + +#[derive(Debug, PartialEq, FromPrimitive)] +#[repr(u32)] +enum BalType { + Nil = 'N' as u32, + Boolean = 'B' as u32, + Int = 'I' as u32, + Float = 'F' as u32, + Decimal = 'D' as u32, + String = 'S' as u32, + Array = 'A' as u32, + Any = 'X' as u32, +} + +// Compute total elements present in the data structure +pub fn compute_size(type_string: &str) -> i32 { + let mut hex_bits = String::new(); + //Index 2 and 3 represent the size + hex_bits.push(type_string.chars().nth(ARRAY_SIZE_LSB_INDEX).unwrap()); + hex_bits.push(type_string.chars().nth(ARRAY_SIZE_MSB_INDEX).unwrap()); + let bits: std::result::Result = + i32::from_str_radix(&hex_bits, 32); + let total_bits: i32 = bits.unwrap(); + let mut length_bits = String::new(); + let index = 4; + for i in 0..total_bits { + let iterator = i as usize; + length_bits.push(type_string.chars().nth(iterator + index).unwrap()); + } + //Convert size to i32 for integer comparision + let size: i32 = length_bits.parse().unwrap(); + return size; +} + +pub fn type_size(type_string: &str) -> i32 { + let type_char = type_string + .chars() + .nth(ARRAY_MEMBER_TYPE_INDEX) + .unwrap_or_else(|| panic!("Illegal type descriptor '{}', wrong length", type_string)); + let bal_type = FromPrimitive::from_u32(type_char as u32).unwrap_or_else(|| { + panic!( + "Illegal type tag '{}' in type descriptor '{}'", + type_char, type_string + ) + }); + match bal_type { + BalType::Boolean => 1, + BalType::Int | BalType::Float => 8, + BalType::String => 12, + BalType::Any => 16, + _ => { + unimplemented!("type_size for '{:?}'", bal_type) + } + } +} + +#[test] +fn src_type_size_less_than_dest() { + let src = CString::new("AF03122").unwrap(); + let dest = CString::new("AX03122").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + true + ); +} + +#[test] +fn src_type_size_greater_than_dest() { + let src = CString::new("AS03122").unwrap(); + let dest = CString::new("AB03122").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + false + ); +} + +#[test] +fn src_elements_less_than_dest() { + let src = CString::new("AB041023").unwrap(); + let dest = CString::new("AX041024").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + true + ); +} + +#[test] +fn src_elements_greater_than_dest() { + let src = CString::new("AB0519999").unwrap(); + let dest = CString::new("AX03199").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + false + ); +} + +#[test] +fn src_type_string_equal_to_dest() { + let src = CString::new("AF0599999").unwrap(); + let dest = CString::new("AF0599999").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + true + ); +} + +#[test] +fn map_test() { + let src = CString::new("MX0599999").unwrap(); + let dest = CString::new("MF0599999").unwrap(); + assert_eq!( + is_same_type( + src.as_ptr() as *const c_char, + dest.as_ptr() as *const c_char + ), + false + ); +} From c8588fd429befe948add7dd6761c03409fe7c953 Mon Sep 17 00:00:00 2001 From: shubhamnarlawar Date: Thu, 4 Mar 2021 15:05:18 +0530 Subject: [PATCH 7/7] Make is_same_type() as wrapper function of same_type() in type_checker.rs --- runtime/src/lib.rs | 58 ++----------------------------------- runtime/src/type_checker.rs | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 3dad1d8e8..815a286a0 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -19,34 +19,13 @@ // Rust Library -extern crate num; -extern crate num_derive; - mod type_checker; use std::ffi::CStr; use std::mem; use std::os::raw::c_char; -/* - * To checking whether typecast is possible from source to destination - * Example of a type string - "AI041024" - * Index 0 - represents data structure - * Index 1 - represents type - * Index 2 and 3 - represents bits in hex followed by its size in decimal - * - * Algorithm - - * a. Convert null terminated string to rust string. - * b. Return true if type strings are same. - * c. Return false if data structure is different. - * d. Compute type size - type_size() - * e. Return false if source type size > destination type size - * g. Compute data structure length - compute_length() - * - * Data Structure Notations - - * A - Array - * M - Map - * */ +// To check whether typecast is possible from source to destination #[no_mangle] pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char) -> bool { assert!(!src_type.is_null()); @@ -57,40 +36,7 @@ pub extern "C" fn is_same_type(src_type: *const c_char, dest_type: *const c_char //Conversion to rust strings let source: String = source_cstr.to_str().unwrap().to_owned(); let destination: String = dest_cstr.to_str().unwrap().to_owned(); - //If type strings are same - if source == destination { - return true; - } - //Index 0 represents type of data structure - if source.chars().nth(type_checker::BASE_TYPE_INDEX) - != destination.chars().nth(type_checker::BASE_TYPE_INDEX) - { - return false; - } - match source.chars().nth(type_checker::BASE_TYPE_INDEX) { - Some('A') => { - if source.chars().nth(type_checker::ARRAY_MEMBER_TYPE_INDEX) - != destination - .chars() - .nth(type_checker::ARRAY_MEMBER_TYPE_INDEX) - { - let src_type_size: i32 = type_checker::type_size(&source); - let dest_type_size: i32 = type_checker::type_size(&destination); - if src_type_size > dest_type_size { - return false; - } - } - // Compute total number of elements present in the data structure - let src_size: i32 = type_checker::compute_size(&source); - let dest_size: i32 = type_checker::compute_size(&destination); - if src_size > dest_size { - return false; - } - } - _ => return false, - } - //If all the checks are passed, type cast from source to destination is valid - return true; + return type_checker::same_type(source, destination); } // Prints 64 bit signed integer diff --git a/runtime/src/type_checker.rs b/runtime/src/type_checker.rs index c2cde9860..b94995d30 100644 --- a/runtime/src/type_checker.rs +++ b/runtime/src/type_checker.rs @@ -89,6 +89,59 @@ pub fn type_size(type_string: &str) -> i32 { } } +/* + * To checking whether typecast is possible from source to destination + * Example of a type string - "AI041024" + * Index 0 - represents data structure + * Index 1 - represents type + * Index 2 and 3 - represents bits in hex followed by its size in decimal + * + * Algorithm - + * a. Convert null terminated string to rust string. + * b. Return true if type strings are same. + * c. Return false if data structure is different. + * d. Compute type size - type_size() + * e. Return false if source type size > destination type size + * g. Compute data structure length - compute_length() + * + * Data Structure Notations - + * A - Array + * M - Map + * */ +#[no_mangle] +pub extern "C" fn same_type(source: String, destination: String) -> bool { + //If type strings are same + if source == destination { + return true; + } + //Index 0 represents type of data structure + if source.chars().nth(BASE_TYPE_INDEX) != destination.chars().nth(BASE_TYPE_INDEX) { + return false; + } + match source.chars().nth(BASE_TYPE_INDEX) { + Some('A') => { + if source.chars().nth(ARRAY_MEMBER_TYPE_INDEX) + != destination.chars().nth(ARRAY_MEMBER_TYPE_INDEX) + { + let src_type_size: i32 = type_size(&source); + let dest_type_size: i32 = type_size(&destination); + if src_type_size > dest_type_size { + return false; + } + } + // Compute total number of elements present in the data structure + let src_size: i32 = compute_size(&source); + let dest_size: i32 = compute_size(&destination); + if src_size > dest_size { + return false; + } + } + _ => return false, + } + //If all the checks are passed, type cast from source to destination is valid + return true; +} + #[test] fn src_type_size_less_than_dest() { let src = CString::new("AF03122").unwrap();