Pico Engine welcoming your contributions
The node pico engine still needs work, and we invite you to participate in this open-source project (hosted on GitHub).
Extending the libraries
Besides the base language of KRL, supported by the krl-compiler
and the associated run-time system, pico-engine-core
, there are several libraries (sometimes called modules, because the functions they provide are invoked with the same syntax used for user-defined KRL modules). It is relatively easy to extend these so as to add functionality to KRL. This is done by providing JavaScript code to implement a new library function, as shown in the following example.
Motivation: round numbers
For example, while working on a pico-based project, we encountered the need for rounding a number to the nearest integer. A quick search of the documentation shows that the math library in the classic engine provided a round()
function. However, as of this writing, that function had not yet been implemented.
Looking for a place to add new code
The pico-engine consists of several packages. The one which applies in this case is pico-engine-core and more specifically the file pico-engine-core/src/modules/math.js
which contains the implementation of everything provided by the math library.
Adding code for a round()
function
We added a new function with this code, aping existing functions within the library:
round: mkKRLfn([ 'number', 'precision' ], function (ctx, args) { if (!_.has(args, 'number')) { throw new Error('math:round needs a number') } return _.round(args.number, args.precision) })
A consultation of the lodash
documentation on the Internet shows that it provides a round()
function, which we can use, since the library already requires it. In general, NodeJS is a rich ecosystem of code with almost everything one can imagine already implemented and ready for our use. Since the lodash
function we are going to use under the covers, as our JavaScript implementation of the KRL function, provides a precision
argument, we'll allow that as well. Note to adjust the documentation accordingly.
Having changed the pico-engine-core, we restart our pico-engine.
Testing the new code
We created this ruleset as a test jig for our newly-added function:
ruleset round_test { meta { shares __testing, round } global { __testing = { "queries": [ { "name": "__testing" } , { "name": "round", "args": [ "number" ] } , { "name": "round", "args": [ "number", "precision" ] } ] } round = function(number,precision){ pre = precision => precision.as("Number") | 0; num = number => number.as("Number") | null; math:round(num,pre) } } }
We then created a pico, named "math", installed in it the round_test
ruleset, and visited the Testing tab of the UI:
Using this testing jig, we were satisfied that we were getting good results, documented here:
round
round(<num>)
- convert <num>
to the nearest integer.
n = math:round(2.1); // n = 2 m = math:round(2.7); // m = 3
round
can take an optional second argument, the number of decimal places, which extends to negative values in an intuitive way.
math:round(4066.123,2) // 4066.12 math:round(4066.123,0) // 4066 math:round(4066.123,-2) // 4100
Contributing the new code
Satisfied that the code works correctly, we worked with git
in our local clone of the GitHub repository:
$ git checkout -b selected-math-functions master M packages/pico-engine-core/src/modules/math.js Switched to a new branch 'selected-math-functions' $ git add packages/pico-engine-core/src/modules/math.js $ git commit -m "initial implementation" [selected-math-functions 40f618e] initial implementation 1 file changed, 53 insertions(+) $ git push -u origin selected-math-functions
First (line 1), we create a new local branch off of master
, named selected-math-functions
. Next, we add the modified file to our local git
repository (line 4), and commit the change (line 5). Finally, we share the new branch to the GitHub repository (line 8).
The next step is to visit GitHub and turn the new branch into a pull request, by clicking on the green button, "Compare & pull request":
This launches some automatic checks, which we followed. When they failed, we clicked on one of them to see the detailed messages and found that we needed to add a space after the comma between function arguments. Matthew suggested a way to fix code-style problems:
Automated tests
It is part of our coding culture at Pico Labs to include automated tests. So, our pull request would not be accepted without them. The tests are found in pico-engine-core/test/modules/math.test.js
and we added these tests cases:
t.is( await kmath.round({}, [0.46]), 0 ) t.is( await kmath.round({}, [-0.46]), -0 ) t.is( await kmath.round({}, [-0.46, 1]), -0.5 ) t.is( await kmath.round({}, [4066, 0]), 4066 ) t.is( await kmath.round({}, [4066, -1]), 4070 ) t.is( await kmath.round({}, [4066, -2]), 4100 ) t.is( await kmath.round({}, [4066, -3]), 4000 ) t.is( await kmath.round({}, [4066, -4]), 0 ) await terr('round', {}, [], 'Error: math:round needs a number')
To run the tests, from within the pico-engine-core folder, use
$ npm run test
Requesting a review
On the GitHub web site, viewing our pull request, we select a reviewer (near the upper-right corner) and click on that person's name to request a review. Assuming everything is satisfactory, they will accept our change and merge it into the master branch.
While awaiting the review, you can return to the master branch using this command:
git checkout master
See the git cheatsheet for more information.
Cleaning up
Once your pull request has been reviewed and merged into the master branch, you need to do a little clean-up.
Delete the branch on GitHub, using the button in its UI, if this hasn't already been done by the reviewer.
You can delete your local git
branch using this command:
git branch -d selected-math-functions
Copyright Picolabs | Licensed under Creative Commons.