Carpet

Carpet

2M Downloads

[Bug] Scarpet parser throws Unexpected error in some situations

altrisi opened this issue ยท 6 comments

commented

Rare cases, but anyway cases.

Not sure (yet) what is wrong here (made it quickly, I'll be fixing it now), but basically this causes somewhere in the parser to throw without helpful message (An unexpected error occurred trying to execute that command, hover: Function 'null' is not defined yet)

Edit: See third comment for what does actually cause the issue in all of this
Edit: Also see another situation with Unexpected error in fourth comment

Excerpt of the code that causes the error (may be because of trying to run for outside of any function):

base_commands_map = {
        ''->_()->[_help(1), false],
        'help' -> [_()->_help(1), false],
        'help <page>' -> ['_help', [[0], 'help', 'l Shows this help menu, or a specified page', null, null]],
        'lang <lang>' -> [_(lang)->(global_lang=lang), [[], 'lang ', 'l Changes current app\'s language to <lang>', 'g Available languages are '+global_lang_ids, null]],
        'fill <block>' -> [['fill',null], false],
        'fill <block> <replaces>' -> ['fill', [[1], 'fill ', 'l Fills the selection, filterable', 'g You can use a tag in the replaces argument', null]],
        'undo' -> [['undo', 1], false],
        'undo <moves>' -> ['undo', [[0], 'undo', 'l Undoes last n moves, one by default', null, null]],
        'undo all' -> [['undo', 0], [[], 'undo all', 'l Undoes the entire action history', null, null]],
        'undo history' -> ['print_history', [[], 'undo history', 'l Shows the history of undone actions', null, null]],
        'redo' -> [['redo', 1], false],
        'redo <moves>' -> ['redo', [[0], 'redo', 'l Redoes last n undoes, one by default', 'g Also shows up in undo history', null]],
        'redo all' -> [['redo', 0], [[0], 'redo all', 'l Redoes the entire undo history', null, null]],
        'wand' -> ['_set_or_give_wand', [[], 'wand', 'l Sets held item as wand or gives it if hand is empty', null, null]],
        'wand <wand>' -> [_(wand)->(global_wand=wand:0), [[], 'wand ', 'l Changes the current wand item', null, null]],
        'rotate <pos> <degrees> <axis>' -> ['rotate', [[], 'rotate ', 'l Rotates [deg] about [pos]', 'g Axis must be x, y or z', null]],//will replace old stuff if need be
        'stack' -> [['stack',1,null], false],
        'stack <count>' -> [['stack',null], false],
        'stack <count> <direction>' -> ['stack', [[0,1], 'stack ', 'l Stacks selection n times in dir', 'g If not provided, direction is player\s view direction by default', null]],
        'expand <pos> <magnitude>' -> ['expand', [[], 'expand ', 'l Expands sel magnitude from pos', 'g "Expands the selection [magnitude] from [pos]', null]],
        'clone <pos>' -> [['clone',false], [[], 'clone ', 'l Clones selection to <pos>', null, null]],
        'move <pos>' -> [['clone',true], [[], 'move ', 'l Moves selection to <pos>', null, null]],
        'selection clear' -> ['clear_selection', false], //TODO help for this and below
        'selection expand' -> [_()->selection_expand(1), false],
        'selection expand <amount>' -> ['selection_expand', false],
        'selection move' -> [_() -> selection_move(1, null), false],
        'selection move <amount>' -> [_(n)->selection_move(n, null), false],
        'selection move <amount> <direction>' -> ['selection_move',false],
};

global_commands_map = {};

for(base_commands_map,
    global_commands_map:_ = base_commands_map:_:0;
);

__config()->{
    'commands'-> global_commands_map,
    'arguments'->{
        'replaces'->{'type'->'blockpredicate'},
        'moves'->{'type'->'int','min'->1,'suggest'->[]},
        'degrees'->{'type'->'int','suggest'->[]},
        'axis'->{'type'->'term','options'->['x','y','z']},
        'wand'->{'type'->'item','suggest'->['wooden_sword','wooden_axe']},
        'direction'->{'type'->'term','options'->['north','south','east','west','up','down']},
        'count'->{'type'->'int','min'->1,'suggest'->[]},
        'flags'->{'type'->'text'},
        'amount'->{'type'->'int'},
        'magnitude'->{'type'->'float','suggest'->[1,2,0.5]},
        'lang'->{'type'->'term','options'->global_lang_ids},
        'page'->{'type'->'int','min'->1,'suggest'->[1,2,3]},
    }
};

Edit: This is not about the issue in this code, but the issue in the parser that prevents from throwing a helpful message.

commented

Wait no, this is actually failing only when running:

global_commands_map:_ = base_commands_map:_:0;

even when added inside of a function.

Changing that line allows the script to load.

Also removing the config also makes it work.

So there may be something in the config not recognizing whatever that produces.

commented

Ok, found where does the issue reside (because solving this solved it):

base_commands_map = {
        ''->_()->[_help(1), false], //# <-- HERE
...
}

That line is incorrect, [ should be before starting lambda (_). The result from applying global_commands_map:_ = base_commands_map:_:0; to that makes the parser/compiler go crazy when trying to add it to a config.

commented

Another Unexpected error situation, this one also quite cryptic, but I think can be more common:

Make a command with a custom argument (e.g. a blockpredicate) and load the app. Then rename that custom argument in the arg definition so it no longer matches. Load the app again (without /reload) and try to run the command.

An unexpected error occurred trying to execute that command:

imagen

If running that with other arguments, it can (sometimes) get a lot more cryptic (happened once with an int, can't reproduce anymore), where you get a multi-paragraph error with multiple class names and/or stack's methods, below the first one without any visible relation to arguments.

This part I know, commands aren't properly reloaded until /reload, but I think they may deserve a more descriptive error, since there is a lot of people who may not know that holding the message gives you more details.

commented

so in the first example from the msg1 the error was that global_lang_ids is not defined so assumed 0, and 0 is not a list. It makes sense to add to the message which custom argument it applies to so I will add that.

if you could provide an example for the last one, would be great. Could not replicate

commented

so far:
ba25867

commented

Hm... I can still reproduce both in ba25867...

Anyway, in order to reproduce the second one, take an app using the new command system (latest WE, for example), load it, change L82 'replacement' -> 'replaces', load the app again (without /reload) and run /world-edit set acacia_planks air.

It's not really a parser error, but Brigadier finding the old argument due to it not being reloaded, and Carpet not catching the exception (since Carpet now asks for it to be a String instead).