pg表达式引擎里面各个表达式的串联是使用goto动态label实现的。
// 定义部分
#if defined(EEO_USE_COMPUTED_GOTO)
static const void *const dispatch_table[] = {
&&CASE_EEOP_DONE,
&&CASE_EEOP_INNER_FETCHSOME,
&&CASE_EEOP_OUTER_FETCHSOME,
&&CASE_EEOP_SCAN_FETCHSOME,
&&CASE_EEOP_INNER_VAR,
&&CASE_EEOP_OUTER_VAR,
&&CASE_EEOP_SCAN_VAR,
...
// 跳转
EEO_CASE(EEOP_OUTER_FETCHSOME)
{
CheckOpSlotCompatibility(op, outerslot);
slot_getsomeattrs(outerslot, op->d.fetch.last_var);
EEO_NEXT();
}
// 宏定义
#define EEO_SWITCH() starteval: switch ((ExprEvalOp) op->opcode)
#define EEO_CASE(name) case name:
#define EEO_DISPATCH() goto starteval
#define EEO_OPCODE(opcode) (opcode)
#endif /* EEO_USE_COMPUTED_GOTO */
#define EEO_NEXT() \
do { \
op++; \
EEO_DISPATCH(); \
} while (0)
#define EEO_JUMP(stepno) \
do { \
op = &state->steps[stepno]; \
EEO_DISPATCH(); \
} while (0)
也就是日常用的比较少的&&操作符。如下:
#include <stdio.h>
#include <string.h>
enum {
ADD,
SUB,
MUL,
DIV,
END
};
int main(int argc,char *argv[])
{
static const void *const disptab[] = {
&&L_ADD,
&&L_SUB,
&&L_MUL,
&&L_DIV,
&&L_END
};
int code[] = {ADD,ADD,MUL,MUL,END};
int i = 0;
int sum = 0;
goto *disptab[code[i++]];
L_ADD:
sum += 2;
goto *disptab[code[i++]];
L_SUB:
sum -= 2;
goto *disptab[code[i++]];
L_MUL:
sum *= 2;
goto *disptab[code[i++]];
L_DIV:
sum /= 2;
goto *disptab[code[i++]];
L_END:
printf("sum = %d\n",sum);
return 0;
}
其等价于switch case,如下:
for()
{
switch()
{
case ADD:
sum += 2;
break;
case SUB:
sum -= 2;
break;
case MUL:
sum *= 2;
break;
case DIV:
sum /= 2;
break;
case END:
}
}
相比来看,速度会更快。