Big update to prettier-extension-monkeyc

I've posted about prettier-extension-monkeyc before, but I've added a bunch of new features that developers will probably like (well, I've been missing them, so maybe you have too).

The new features it implements for VSCode include:

  • Goto Definition. Point at a symbol, Ctrl/Cmd click, and it will take you to the definition. Or F12
  • Goto References. Right click on a symbol and select "Goto References". It will show you all the references. Or Shift-F12
  • Peek Definition/Peek References. Same as above, but in a popup window so you don't lose your place in the original document.
  • Rename Symbol. Right click on a local, function, class or module name, and select "Rename Symbol". It will rename all the references. It doesn't yet work for class members/methods.
  • Goto Symbol. Type Ctrl/Cmd-Shift-O and pick a symbol from the drop down (which has a hierarchical view of all symbols in the current file). This also appears as an outline across the top of the file.
  • Open Symbol By Name. Type Ctrl/Cmd-T, then start typing letters from a symbol name. A drop down will be populated with all matching symbols from anywhere in your project.

Older features include a prettier based formatter for monkeyc, and a monkeyc optimizer that will build/run/export an optimized version of your project.

[edit: My last couple of replies seem to have just disappeared, and the whole conversation seems to be in a jumbled order, so tldr: there's a new test-release at https://github.com/markw65/prettier-extension-monkeyc/releases/tag/v2.0.9 which seems to work for me on linux. I'll do more verification tomorrow, and push a proper update to the vscode store once I'm sure everything is working]

  • Ok - can you clarify when it happens?

    Does the message only appear when you also get the out of memory error that you initially reported? Does it only happen with the post build optimizer? Does it *always* happen with the post build optimizer?

  • FIrst of all I can say now that it's not related to the out of memory error (it also happens when there's enough memory).

    Secondly if it wasn't clear, when I wrote I did "Monkey C: Build for device" I meant to say that it happens also when I don't use the optimizer. Which if I understand what "Build for device" means sounds like an SDK bug (otherwise why would anyone build the project for a device if not to side load it on the device?)

    Thirdly it looks like it does always happen with the optimizer (At least I tried now with a build I made using the tasks.json you sent)

  • I see now in 2.0.80 you added the warnings: " The inline function ... was not removed from the program". Thanks!!! This saves LOOOOT of code! Basically all of the places I didn't know until now about are caused by using a method name that already exists in the SDK somewhere else. I would even be happy to have a switch in the settings to make these ERROR instead of INFO, 'cause it's so useful!

  • There's a bug however. I'll try to create a POC, but it's somehow happening like this:

    1. I had an inlined function with 6 parameters: drawHrZoneGauge, and I had a warning about an unused class variable (this was kind of true, but not 100%). So I removed the variable from the class, because and I added it to be passed as the 7th parameter to drawHrZoneGauge however at the place I call it I forgot to add the 7th parameter. Now I got these:

    ERROR> fr255: MyField.mc:597:9: $.BaseField.drawHrZoneGauge expects 7 arguments, but got 6
    INFO> fr255: MyField.mc:597:9: While inlining drawHrZoneGauge: This function can only be inlined in statement, assignment, if or return contexts

    All this is OK, but then here's the bug:

    1. somehow drawHrZoneGauge was excluded from the optimized code and thus not called (probably the other way around)

    2. the build should've failed because I passed 6 params to a function that expects 7

  • import Toybox.Lang;
    import Toybox.Application;
    import Toybox.Graphics;
    import Toybox.WatchUi;
    
    class TestApp extends Application.AppBase {
        function initialize() {
            AppBase.initialize();
        }
    
        function getInitialView() as Array<Views or InputDelegates>? {
            return [ new MyField() ] as Array<Views or InputDelegates>;
        }
    
    }
    
    class MyField extends WatchUi.DataField {
        public function initialize() {
            DataField.initialize();
        }
    
        public function onUpdate(dc as Graphics.Dc) {
            drawHrZoneGauge(dc, 100, /* true*/);
        }
    
        (:inline)
        hidden function drawHrZoneGauge(dc as Graphics.Dc, n as Number, b as Boolean) as Void {
            System.println("n: " + n + ", b: " + b);
        }
    }
    

  • Nice test case. Looking at it now...

  • For the sake of discussion lets say I have some functions:

    function foo(r1, a1, r2, a2) {
        // do foo math
        return [r, a];
    }
    
    function bar(r, a) {
        // do bar math
        return [x, y];
    }

    I would also like to be able to do both at once:

    function foobar(r1, a1, r2, a2) {
        return bar(foo(r1, a1, r2, a2));
    }
    

    This sounds simple enough in theory, but in practice turns out to be faster to combine them instead like this:

    function foobar(r1, a1, r2, a2) {
        // do foo math
        // do bar math
        return [x, y];
    }
    

    I wouldn't care much about the speed difference except that this is in onPartialUpdate, so I need to conserve milliseconds.

    It sure would be nice if I could have faster AND smaller code, but it seems the benefit of reduced code is lost to the function calling overhead. Is there a way to achieve this?

  • Have you tried to add (:inline) annotation?

    Though it won't be ideal cause you still will create an array and you don't want that...

  • In every case there will be an array because we're dealing with coordinates, but at least I can save that until the return statement so I only have to do it once per function. I've seen inline mentioned but I can't seem to find documentation on it. Can you give some details on usage and limitations? When would I not want to use it?