-
Notifications
You must be signed in to change notification settings - Fork 152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an intrinsic implementation of type(object)
function
#2592
Conversation
The reason which causes the above 2 tests to fail is also the one I need help with. The argument |
Co-authored-by: Thirumalai Shaktivel <74826228+Thirumalai-Shaktivel@users.noreply.github.com>
Co-authored-by: Thirumalai Shaktivel <74826228+Thirumalai-Shaktivel@users.noreply.github.com>
Co-authored-by: Thirumalai Shaktivel <74826228+Thirumalai-Shaktivel@users.noreply.github.com>
Co-authored-by: Thirumalai Shaktivel <74826228+Thirumalai-Shaktivel@users.noreply.github.com>
Also, Let's add some tests. |
Co-authored-by: Thirumalai Shaktivel <74826228+Thirumalai-Shaktivel@users.noreply.github.com>
There is a small issue. The return type of |
Minimum reproducible example (MRE), please? |
l: list[i32] = [1, 2, 3, 4, 5]
t: str = type(l) Another one l: list[i32] = [1, 2, 3, 4, 5]
print(type(type(l)) In CPython, a statement like the above returns |
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 think the following code output would differ with CPython, we have to fix it before merging this PR.
Rest looks good.
print(type(type(1)))
Co-authored-by: Thirumalai Shaktivel <74826228+Thirumalai-Shaktivel@users.noreply.github.com>
Co-authored-by: Thirumalai Shaktivel <74826228+Thirumalai-Shaktivel@users.noreply.github.com>
Co-authored-by: Thirumalai Shaktivel <74826228+Thirumalai-Shaktivel@users.noreply.github.com>
Going the |
Nope, I meant the case: type(type(1)) |
But this will always be the case until we create a specific type for |
Check if the Later in the future, if we find any other different output or cases, we will modify it accordingly. |
Hmm, this seems a good idea. Let's test it out. 👍 |
I am getting this error now. I think it is because of the clean build we did for the CMake Error at CMakeLists.txt:10 (file):
file STRINGS file "/home/saurabh-kumar/Projects/System/lpython/version"
cannot be read.
.
.
.
-- Configuring incomplete, errors occurred! |
Which command did you use to build |
When this error occurred now, I followed the complete process which we do on a fresh build. As it turns out, only |
Before Or you can just run |
Thanks @Thirumalai-Shaktivel it works now. It was an issue with the tag which had previously caused |
Thanks a lot for your support and guidance @Thirumalai-Shaktivel! Without you I could not have made it this far. Thank you very much! |
@Thirumalai-Shaktivel do you think this PR is ready? |
if (ASR::is_a<ASR::IntrinsicScalarFunction_t>(*args[0])) { | ||
ASR::IntrinsicScalarFunction_t *object = ASR::down_cast<ASR::IntrinsicScalarFunction_t>(args[0]); | ||
if (static_cast<IntrinsicScalarFunctions>(object->m_intrinsic_id) == IntrinsicScalarFunctions::ObjectType) { | ||
m_value = StringConstant("<type 'type'>", character(13)); // 13 is the length of the string "<type '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.
m_value = StringConstant("<type 'type'>", character(13)); // 13 is the length of the string "<type 'type'>" | |
m_value = StringConstant("<class 'type'>", character(13)); // 13 is the length of the string "<type 'type'>" |
>>> type(type(1))
<class '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.
I had intentionally not used the word 'class' as we do not currently support it fully. Should we write it 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.
Nope, we have to make sure both CPython and LPython generates the same output.
So, I suggested the above changes and test this both in CPython and LPython(llvm).
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 really sorry for the confusion. The return type of type()
in CPython is of type - type
, whereas here we are using a string for it. They would not be similar.
I request guidance on how do we go about this @Thirumalai-Shaktivel.
tests/tests.toml
Outdated
[[test]] | ||
filename = "../integration_tests/test_builtin_type.py" | ||
asr = true | ||
|
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.
[[test]] | |
filename = "../integration_tests/test_builtin_type.py" | |
asr = true |
Tests this using integration_tests/CMakeLists
test: llvm, cpython
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.
Okay.
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.
The cpython test fails because the type()
has a different return type there.
Co-authored-by: Thirumalai Shaktivel <74826228+Thirumalai-Shaktivel@users.noreply.github.com>
Apply the following diff: diff --git a/integration_tests/test_builtin_type.py b/integration_tests/test_builtin_type.py
index dea42bc74..961ed245c 100644
--- a/integration_tests/test_builtin_type.py
+++ b/integration_tests/test_builtin_type.py
@@ -1,19 +1,27 @@
-from lpython import i32, f64, list, str, dict, Const
+from lpython import i32, f64, Const
def test_builtin_type():
i: i32 = 42
+ f: f64 = 64.
s: str = "Hello, LPython!"
l: list[i32] = [1, 2, 3, 4, 5]
d: dict[str, i32] = {"a": 1, "b": 2, "c": 3}
- CONST_LIST: Const[list[f64]] = [12.22, 14.63, 33.82, 19.18]
+ res: str = ""
- assert type(i) == "<type 'i32'>"
- assert type(s) == "<type 'str'>"
- assert type(l) == "<type 'list[i32]'>"
- assert type(d) == "<type 'dict[str, i32]'>"
- assert type(CONST_LIST) == "<type 'Const[list[f64]]'>"
-
- assert type(type(i)) == "<type 'type'>"
- assert type(type(CONST_LIST)) == "<type 'type'>"
+ res = str(type(i))
+ print(res)
+ assert res == "<class 'int'>"
+ res = str(type(f))
+ print(res)
+ assert res == "<class 'float'>"
+ res = str(type(s))
+ print(res)
+ assert res == "<class 'str'>"
+ res = str(type(l))
+ print(res)
+ assert res == "<class 'list'>"
+ res = str(type(d))
+ print(res)
+ assert res == "<class 'dict'>"
test_builtin_type()
diff --git a/src/libasr/pass/intrinsic_function_registry.h b/src/libasr/pass/intrinsic_function_registry.h
index e70524b62..19d219f53 100644
--- a/src/libasr/pass/intrinsic_function_registry.h
+++ b/src/libasr/pass/intrinsic_function_registry.h
@@ -1173,7 +1173,24 @@ namespace ObjectType {
static ASR::expr_t *eval_ObjectType(Allocator &al, const Location &loc,
ASR::ttype_t* t1, Vec<ASR::expr_t*>& /*args*/) {
- std::string object_type = "<type '" + ASRUtils::type_to_str_python(t1) + "'>";
+ std::string object_type = "<class '";
+ switch (t1->type) {
+ case ASR::ttypeType::Integer : {
+ object_type += "int"; break;
+ } case ASR::ttypeType::Real : {
+ object_type += "float"; break;
+ } case ASR::ttypeType::Character : {
+ object_type += "str"; break;
+ } case ASR::ttypeType::List : {
+ object_type += "list"; break;
+ } case ASR::ttypeType::Dict : {
+ object_type += "dict"; break;
+ } default: {
+ LCOMPILERS_ASSERT_MSG(false, "Unsupported type");
+ break;
+ }
+ }
+ object_type += "'>";
return StringConstant(object_type, character(object_type.length()));
}
@@ -1185,17 +1202,8 @@ namespace ObjectType {
}
ASR::expr_t *m_value = nullptr;
Vec<ASR::expr_t *> arg_values;
-
- if (ASR::is_a<ASR::IntrinsicScalarFunction_t>(*args[0])) {
- ASR::IntrinsicScalarFunction_t *object = ASR::down_cast<ASR::IntrinsicScalarFunction_t>(args[0]);
- if (static_cast<IntrinsicScalarFunctions>(object->m_intrinsic_id) == IntrinsicScalarFunctions::ObjectType) {
- m_value = StringConstant("<type 'type'>", character(13)); // 13 is the length of the string "<type 'type'>"
- }
- }
- else {
- m_value = eval_ObjectType(al, loc, expr_type(args[0]), arg_values);
- }
-
+ m_value = eval_ObjectType(al, loc, expr_type(args[0]), arg_values);
+
return ASR::make_IntrinsicScalarFunction_t(al, loc,
static_cast<int64_t>(IntrinsicScalarFunctions::ObjectType),
args.p, args.n, 0, ASRUtils::expr_type(m_value), m_value); |
@Shaikh-Ubaid, do you have any design suggestions 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.
I shared some comments. Overall the implementation looks in the right direction.
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.
We just need to fix #2592 (comment) and #2592 (comment). I think then this would be good to merge.
Co-authored-by: Shaikh Ubaid <shaikhubaid769@gmail.com>
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 looks good! Thanks!
Currently the logic is simple - get the type of the passed argument using
ASRUtils::type_to_str_python(*ttype_t)
and return it as a StringConstant. I request guidance to improve this PR.Get type of the object
Compare object types (requires #2591 to be merged)