-
Notifications
You must be signed in to change notification settings - Fork 13
Conversation
Please review and suggest changes - @ruvi-d @manuranga |
This PR addresses issue #86. |
From issue - #86
The original types are available in smart pointers. The original types - for example - int, char, any, etc is supposed to be checked before callling As discussed earlier, wrapper function is supposed to be implemented in rust. Is wrapper function suggested to be implemented in rust or llvm side? |
IMO, such decisions should be based on whether the check is at compile time or runtime. If the check needs to happen at compile time, the implementation should be on the C++/LLVM side. If it's a runtime check, then it should happen on the Rust side. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see review comments
let source_cstr: &CStr = unsafe { CStr::from_ptr(src_type) }; | ||
let dest_cstr: &CStr = unsafe { CStr::from_ptr(dest_type) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an assert!(!src_type.is_null());
before CStr::from_ptr(src_type)
. Do for dest_type
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
runtime/src/lib.rs
Outdated
Some('C') => priority = 4, | ||
Some('B') => priority = 1, | ||
Some('F') | Some('I') => priority = 8, | ||
Some('A') => priority = 16, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a comment defining the char to type mapping?
#50 suggested X
for any
type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Please check it!
runtime/src/lib.rs
Outdated
return false; | ||
} | ||
} | ||
_ => println!("Unsupported data structure"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unsupported should fail check. return false;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Done.
runtime/src/lib.rs
Outdated
Some('B') => priority = 1, | ||
Some('F') | Some('I') => priority = 8, | ||
Some('A') => priority = 16, | ||
_ => println!("Unsupported type"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return error Result for unsupported types
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this?
_ => panic!("Unsupported type in mangled string"),
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd return a std::result::Result from the function. The lib.rs side can check the return and panic if required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
runtime/src/lib.rs
Outdated
} | ||
let mut src_priority = 0; | ||
let mut dest_priority = 0; | ||
match source.chars().nth(0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define these magic numbers for bit positions as constants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate a bit more in this suggestion?
Do you mean to use below snippet instead -
let constant = source.chars().nth(0);
match constant {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no.. I mean define the string indexes as constants like:
const BASE_TYPE_INDX: u32 = 0;
const ARRAY_MEMBER_TYPE_INDX: u32 = 1;
const ARRAY_SIZE_LSB_INDX: u32 = 2;
const ARRAY_SIZE_MSB_INDX: u32 = 3;
...
// Then use these constants when accessing the chars
match source.chars().nth(BASE_TYPE_INDX)
Hope that makes sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Makes sense. I have used usize
instead of u32
as match expects a usize
-
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;
I will push this snippet along with other changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It took some time, but I was able to come up with following code. Please do the research on rust language best practices in the future.
extern crate num;
extern crate num_derive;
use num::FromPrimitive;
use num_derive::FromPrimitive;
const ARRAY_MEMBER_TYPE_INDEX: usize = 2;
#[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,
}
pub fn type_size(type_string: &str) -> i32 {
let type_char = type_string.chars().nth(ARRAY_MEMBER_TYPE_INDEX)
.unwrap_or_else(|| panic!("illegle type discripor '{}', wrong length", type_string));
let bal_type = FromPrimitive::from_u32(type_char as u32)
.unwrap_or_else(|| panic!("illegle type tag '{}' in type discripor '{}'", 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) }
}
}
Cargo.toml
[dependencies]
num = "0.3"
num-traits = "0.2"
num-derive = "0.3"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the snippet! Sure. I will follow it in next tasks!
Let me modify other functions to follow above points!
runtime/src/lib.rs
Outdated
//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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to handle unbounded Array sizes?
@shubhamnarlawar other general review comments:
|
Got it. Thanks for the clarification. |
|
Let us know if there is a good reason to use Rust logic for compile time checks and then maybe we can take it case by case. |
I think it should be |
Sure. At this point, there is no need to write wrapper function for calling 'is_same_type()'. |
For point 3, we have not planned handling unbounded size arrays in this sprint. We need to discuss it in Monday's meeting - Some quick thoughts to discuss - |
runtime/src/lib.rs
Outdated
pub fn calculate_type_priority(type_string: &str) -> Result<i32, &'static str> { | ||
let priority: i32; | ||
match type_string.chars().nth(ARRAY_MEMBER_TYPE_INDX) { | ||
Some('C') | Some('B') => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be descriptive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added comment at top of this function-
/*
* Computes size of the type
* Type Notations -
* C represents character
* B represents boolean
* F represents float
* I represents integer
* S represents string
* X represents any*/
Is using a macro suggested here ? Like -
macro_rules! Char { () => {'C'}; }
and In the match case, it will be - Some(Char!())
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@manuranga - In yesterday's call, you suggested to use enum. But here at some places, two entities require same value -
for example - Some('C') | Some('B')
- here both characer and boolean requires a value of 1
.
Can you share example to make it more descriptive? You mentioned that you have known in other languages in C++ to make this match case more descriptive. Can you please share here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi looks like rust doesn't support this out of the box yet rust-lang/rfcs#3040
But it seems like there is a common way to do this : https://stackoverflow.com/a/28029279
Please try to use this approach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From above link - I can write enum as below -
enum TYPE_SIZE {
CHAR = 1,
INT = 8,
STRING = 12,
ANY = 16,
}
and so on
but for boolean data type with size 1 byte
, it also need 1
similarly, float needs 8
. Here we have repetitive values. How would enum works in this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I am suggesting not to have unnamed constants like C
and X
. This is the same reason we use constants instead inlined numbers https://stackoverflow.com/a/47902.
I was not suggesting to have priorities be encoded into to enum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. I misinterpreted it.
How about using below constants instead of just C
and X
? -
pub const CHARACTER: char = 'C';
pub const BOOLEAN: char = 'B';
pub const INTEGER: char = 'I';
pub const FLOAT: char = 'F';
pub const STRING: char = 'S';
pub const ANY: char = 'X';
pub const ARRAY: char = 'A';
4dba208
to
e12de36
Compare
f853bd6
to
07bed03
Compare
runtime/src/lib.rs
Outdated
Some('A') => { | ||
if source.chars().nth(ARRAY_MEMBER_TYPE_INDX) | ||
!= destination.chars().nth(ARRAY_MEMBER_TYPE_INDX) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this line formatted using rustfmt
? brace seems to be on the wrong line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am using cargo-fmt
. I tried with rustfmt
but getting same result. Let me reformat it once again!
runtime/src/lib.rs
Outdated
return false; | ||
} | ||
let mut src_type_size: Result<i32, &'static str> = Ok(0); | ||
let mut dest_type_size: Result<i32, &'static str> = Ok(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Rust, it's a best practice to use mut
minimally. If you can avoid it, it's better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it! Sure
runtime/src/lib.rs
Outdated
* F represents float | ||
* I represents integer | ||
* S represents string | ||
* X represents any*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shubhamnarlawar Please read https://ballerina.io/spec/lang/draft/v2020-12-17/#section_5.1.4
these are the type we need to support. We can start by selected subset, but there is no type called character.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. From the above enum you wrote, we can treat it as a subset!
@shubhamnarlawar remember to create a separate |
I have moved all functions except |
Is this PR ready to merge now? |
You will have to fix the conflicts with master. When the PR is ready to review, you can mark my request for change complete and request for review again. |
I have resolved the conflict with master. No merge conflict now! |
@ruvi-d - Please give suggestions if any on latest changes pushed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better now with the Rust unit tests.
Just one more suggestion. Move the is_same_type function to the type_checker module. Change it's input args to take Rust strings. On the lib.rs, only do the String construction and directly pass it to type_checker module. Similar to how the Map implementation has been done.
The idea here is to keep lib.rs as thin as possible, doing only the data type conversions. The actual logic will be kept on a separate, reusable(independent) Rust module.
0a66764
to
c8588fd
Compare
Done. Please check it. I have moved logic of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am OK to merge. Best if @manuranga can double check the Rust lang specific stuff.
Still little bit unsure about the algo, but we'll catch if there is any issues with lit tests later. Looks good to merge. |
Sounds good. Can you mark it as review complete and approve? |
Purpose
Checks whether array typecast is possible from source type to destination type.
Related discussion - ballerina-platform/nballerina#50
Fixes #86