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
Adding basic namespace handling #290
Conversation
…HANDLING comments. C++: register_namespace(): registers a namespace with an instance of ChaiScript (supports delayed namespace generation) import(): imports a namespace as a global Dynamic_Object ChaiScript: import(): imports a namespace namespace(): generates and registers a new namespace
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 add
{ }
in the if statements where you've left them off, and add mutex protects (notes have been made on both of these) - Please add a unit test showing the expected behavior of these functions in the unit_tests folder https://github.com/ChaiScript/ChaiScript/tree/develop/unittests
/// Helper function to add a namespace to the engine. | ||
void add_namespace(const std::string& t_namespace_name) { | ||
if (m_namespaces.count(t_namespace_name)) { | ||
if (!m_engine.get_scripting_objects().count(t_namespace_name)) // Add namespace if it hasn't already been added. |
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.
All if()
statements should have { }
for safety and code clarity
/// \brief Imports a namespace object into the global scope of this ChaiScript instance. | ||
void import(const std::string& t_namespace_name) | ||
{ | ||
if (m_namespaces.count(t_namespace_name)) |
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 code particularly makes my point about { }
being always required - mixed if
/else if
/if
without { }
can add to confusion during later edits
// NAMESPACE HANDLING | ||
/// \brief Imports a namespace object into the global scope of this ChaiScript instance. | ||
void import(const std::string& t_namespace_name) | ||
{ |
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.
All of these functions will need mutex protection, similar to this (note that it only needs m_mutex
, not m_use_mutex
): https://github.com/stephenberry/ChaiScript/blob/a01687d7ad836c24621d8af26c08d760bae7eb0d/include/chaiscript/language/chaiscript_engine.hpp#L467
Added more comments to namespace handling functions. Added mutex protection to import.
I've started to implement your requested changes, but I ran into an issue when adding the mutex to all the register_namespace functions. I haven't looked into why yet. |
Is it a compile time or run time error you are getting? |
It's a run time error: |
You're hitting a recursive mutex lock probably, don't worry about that part now, instead focus on the tests/examples. |
OK, I'll work on tests/examples. |
These demonstrate the global scope of namespaces, defining functions and variables within namespaces, and namespace nesting by copy or reference.
I added three unit tests for namespaces as well as documentation to the cheatsheet. In the cheatsheet I addressed namespaces both in the section for adding things to the engine and immediately after the section on Dynamic Objects. |
Just let me know if there is anything else you'd like me to consider or add for namespaces. My aim was to add as little code as possible while providing a framework for namespaces. |
Sorry, I'm a little behind on ChaiScript stuff right now, I'll probably get back to this in another week. |
There's a lot I like about this. I will have to address the threading concerns, but I can do that. I was wondering what you thought about changing the signature of the delayed namespace registration from:
To something like:
So there's less ambiguity about what needs to be done? -Jason |
I'm for this change, and not just because it is more straightforward. I think it allows for more flexibility in the future. By passing in a reference we could use this lambda function to expand a namespace rather than merely initialize one, I'm not sure if this is a direction to take namespace handling, but it leaves the possibility open. Note: With this change the namespace will need to be instantiated in the |
@stephenberry I have not forgotten about this branch, but I haven't had the time I want to devote to it yet. This is the kind of feature that once I commit it people will rely on it, so I want to make sure we are moving forward with something that makes sense for the long term. |
I understand. I'm looking forward to it, but there's no rush. |
I am one of those users that would love to see this in. 👍 Any progress? |
I feel like now that I've gotten past the hurdle of getting 6.0 out, I can start looking at stuff like this again. |
@stephenberry it has been 189 days since this pull request was last updated. |
@lefticus I'll update this pull request soon and look once more into possible improvements to the namespacing code. |
Removed namespaces_nested_ref.chai
…ration to allow for delayed generation. This simplifies generating namespaces by the user and leads to more efficient code.
Codecov Report
@@ Coverage Diff @@
## develop #290 +/- ##
===========================================
+ Coverage 67.79% 67.79% +<.01%
===========================================
Files 59 59
Lines 10229 10245 +16
Branches 1284 1286 +2
===========================================
+ Hits 6935 6946 +11
- Misses 2416 2419 +3
- Partials 878 880 +2
Continue to review full report at Codecov.
|
@lefticus I've updated the namespacing code and I believe it is in a good state now. I've simplified the code and the user interface. I'm requiring the user to pass in a function in order to always delay the namespace instantiation. This way the namespace will only be populated if it is imported, which can have significant memory and computation savings. I also implemented your suggested change on passing a Namespace reference into the register_namespace method. Here's a simple example: chai->register_namespace([](chaiscript::Namespace& math) {
math["pi"] = const_var(3.14159);
math["sin"] = var(fun([](const double x) { return sin(x); })); },
"math"); Some ChaiScript example code: import("math")
print(math.pi) // math namespace defined in C++
print(math.sin(math.pi / 2.0))
namespace("trig") // define a new trig namespace
trig.pi = math.pi
print(2.0*trig.pi)
trig.sin = fun(x) { math.sin(x) } // create a new function that uses the math.sin function
print(trig.sin(math.pi / 2.0)) Let me know if you would like me to consider anything else concerning namespacing. If we can get this into the main ChaiScript repo then I'll be able to implement it into more of my work and test it in broader applications. |
@stephenberry I went for it. Sorry for the supremely long delay and thank you for the hard work. |
@lefticus Excellent, thanks! I'm glad I could contribute. I'll certainly be using this. |
Nice work on this, you two! Will check it out soon. |
Issue this pull request references: #113
The new code is wrapped in NAMESPACE HANDLING comments.
C++:
register_namespace(): registers a namespace with an instance of ChaiScript (supports delayed namespace generation)
import(): imports a namespace as a global Dynamic_Object
ChaiScript:
import(): imports a namespace
namespace(): generates and registers a new namespace