munificent / craftinginterpreters

Repository for the book "Crafting Interpreters"
http://www.craftinginterpreters.com/
Other
8.75k stars 1.03k forks source link

Not a problem ... But just want to ask about that do - while Loop #1007

Closed heinthanth closed 2 years ago

heinthanth commented 2 years ago

Is there any specific reason to use that do while loop since while(false) make the loop runs only once. I see that in both Lox and Wren VM.

in https://github.com/wren-lang/wren/blob/accfa598b3cbc54fdfb33cb568055ed6994a4966/src/vm/wren_common.h#L160-L168

#define BINARY_OP(valueType, op) \
    do { \
      if (!IS_NUMBER(peek(0)) || !IS_NUMBER(peek(1))) { \
        runtimeError("Operands must be numbers."); \
        return INTERPRET_RUNTIME_ERROR; \
      } \
      double b = AS_NUMBER(pop()); \
      double a = AS_NUMBER(pop()); \
      push(valueType(a op b)); \
    } while (false)

in https://github.com/wren-lang/wren/blob/accfa598b3cbc54fdfb33cb568055ed6994a4966/src/vm/wren_common.h#L160

do                                                                       \
      {                                                                        \
        if (!(condition))                                                      \
        {                                                                      \
          fprintf(stderr, "[%s:%d] Assert failed in %s(): %s\n",               \
              __FILE__, __LINE__, __func__, message);                          \
          abort();                                                             \
        }                                                                      \
      } while (false)

That code works. But I just want to know using do-while instead of just write the code inside without loop.

cdmh commented 2 years ago

It’s a common idiom to prevent errors using the macro in a block statement, such as if, without curly braces

if (cond)
    BINARY_OP(…);

will still work as expected, with all the usual rules of block scope and semi-colon terminations. This wouldn’t be the case if the BINARY_OP didn’t have the do … while(false);

bugwelle commented 2 years ago

Another reason is that it forces a semicolon after the macro. Without the do...while(false), i.e. with just braces ({...}), no semicolon is required after the macro.

munificent commented 2 years ago

The strange form of that macro is explained in the book here. C is weird.