syntax-errorwhere-clauseassertionfflanura

Combine asserting clauses with where clauses


I have noticed that when I have multiple where clauses and multiple asserting clauses, that I get often get syntax errors when I combine them together. The error will say "unexpected token after where". How should I write it to avoid this error? Here is the latest example:

Attempt 1:

def(class game_state game) ->commands [
        set(attack, cost),
        set(life, cost),
        set(abilities, []),
    ] where cost=(card.cost + (card.loyalty_cost * size(card.school)))
      where card=crypt_spells[choices[0]]
//      asserting size(choices) = 1 //FIXME: syntax error uncommented
        asserting choices != null
      where crypt_spells=filter(game.crypt.cards_of(player), value.type='spell')
      where player=game.player_obj

I also tried rewriting it a different way, that also resulted in the "unexpected token after where" syntax error.

Attempt 2:

def(class game_state game) ->commands [
        set(attack, cost),
        set(life, cost),
        set(abilities, []),
    ] where cost=(card.cost + (card.loyalty_cost * size(card.school)))
      where card=crypt_spells[choices[0]]
      asserting choices != null, size(choices)=1 | choices //FIXME: syntax error
      where crypt_spells=filter(game.crypt.cards_of(player), value.type='spell')
      where player=game.player_obj

Example 3:

Here is another example that, I think, highlights the problem:

def(class game_state game, class message.play_card info) ->commands
  if(info.choices,
    ([ /* do stuff */ ]
      where entry=game.crypt.get_entry(info.choices[0])
      asserting size(info.targets)=1 | info.targets    /* PARSE ERROR! */
    ) asserting size(info.choices)=1 | info.choices,   /* WORKS */
    [ /* else */ ]
  )

As you can see from this example, asserting a=b works fine unless it is preceded by a where clause.


Solution

  • Let me try to transform your code into generic debug console code:

    f()
    where f = def
            () -> commands [
                    debug(['something']),
                    debug(['more stuff']),
                    debug(['yet more stuff']),
            ]
            where aaa = (0 + (1 * 2))
            where bbb = 4
    //        asserting 2 + 2 = 4 // FIXME: syntax error uncommented
            asserting '000' != null
            where ccc = [0, 1, 2, 3]
            where ddd = {'0': 0, '1': 1, }
    

    The debug console can execute that:

    (debug console):0: ['something']
    (debug console):0: ['more stuff']
    (debug console):0: ['yet more stuff']
    [(Command Object: N10game_logic12_GLOBAL__N_113debug_commandE),
     (Command Object: N10game_logic12_GLOBAL__N_113debug_commandE),
     (Command Object: N10game_logic12_GLOBAL__N_113debug_commandE)]
    

    Let's check that your syntax error is still there, or at least some syntax error, when uncommenting the assertion:

    f()
    where f = def
            () -> commands [
                    debug(['something']),
                    debug(['more stuff']),
                    debug(['yet more stuff']),
            ]
            where aaa = (0 + (1 * 2))
            where bbb = 4
            asserting 2 + 2 = 4 // FIXME: syntax error uncommented
            asserting '000' != null
            where ccc = [0, 1, 2, 3]
            where ddd = {'0': 0, '1': 1, }
    

    The debug console can't execute:

    error parsing formula: formula.cpp:3942 ASSERTION FAILED: Unexpected tokens after
    where
    At (debug console) 0:
    ... where bbb = 4       asserting 2 + 2 = 4 // FIXME syntax error uncommen...
                                            ^
    

    The engine uses simple parsing, and currently where, asserting and = (and maybe even ,?) can be combined in ways intuitive but not well managed by the parser.

    Here, I think it found a secondary = for where before reaching ,, but I don't know. Right now I don't know exactly what is the criteria for finishing parsing of where. You would know by just debugging the parser.

    This is an important issue, but maybe not critical and must fix now, as can mostly be managed by including more parens exhaustiveness.

    Let's place just one parens pair, let's start by the failing assertion:

    f()
    where f = def
            () -> commands [
                    debug(['something']),
                    debug(['more stuff']),
                    debug(['yet more stuff']),
            ]
            where aaa = (0 + (1 * 2))
            where bbb = 4
            asserting (2 + 2 = 4) // FIXME: syntax error uncommented
            asserting '000' != null
            where ccc = [0, 1, 2, 3]
            where ddd = {'0': 0, '1': 1, }
    

    The debug console can execute again:

    (debug console):0: ['something']
    (debug console):0: ['more stuff']
    (debug console):0: ['yet more stuff']
    [(Command Object: N10game_logic12_GLOBAL__N_113debug_commandE),
     (Command Object: N10game_logic12_GLOBAL__N_113debug_commandE),
     (Command Object: N10game_logic12_GLOBAL__N_113debug_commandE)]
    

    2018 May 27 added the error pinpoint location.