#define isfloat(X) (((ast_expression*)(X))->vtype == TYPE_FLOAT)
#define isvector(X) (((ast_expression*)(X))->vtype == TYPE_VECTOR)
#define isstring(X) (((ast_expression*)(X))->vtype == TYPE_STRING)
+#define isarray(X) (((ast_expression*)(X))->vtype == TYPE_ARRAY)
#define isfloats(X,Y) (isfloat (X) && isfloat (Y))
/*
return NULL;
}
+static GMQCC_INLINE ast_expression *fold_op_length(fold_t *fold, ast_value *a) {
+ if (fold_can_1(a) && isstring(a))
+ return fold_constgen_float(fold, strlen(fold_immvalue_string(a)));
+ if (isarray(a))
+ return fold_constgen_float(fold, vec_size(a->initlist));
+ return NULL;
+}
+
ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **opexprs) {
ast_value *a = (ast_value*)opexprs[0];
ast_value *b = (ast_value*)opexprs[1];
fold_op_case(2, ('=', '='), cmp, (fold, a, b, false));
fold_op_case(2, ('~', 'P'), bnot, (fold, a));
fold_op_case(2, ('>', '<'), cross, (fold, a, b));
+ fold_op_case(3, ('l','e','n'), length, (fold, a));
}
#undef fold_op_case
compile_error(fold_ctx(fold), "internal error: attempted to constant-fold for unsupported operator");
return (lex->tok.ttype = TOKEN_OPERATOR);
}
+ /* len operator */
+ if (ch == 'l') {
+ if ((nextch = lex_getch(lex)) == 'e') {
+ if ((nextch = lex_getch(lex)) == 'n') {
+ lex_tokench(lex, 'l');
+ lex_tokench(lex, 'e');
+ lex_tokench(lex, 'n');
+ lex_endtoken(lex);
+ return (lex->tok.ttype = TOKEN_OPERATOR);
+ } else {
+ lex_ungetch(lex, nextch);
+ }
+ } else {
+ lex_ungetch(lex, nextch);
+ }
+ }
+
if (isident_start(ch))
{
const char *v;
static const oper_info c_operators[] = {
{ "(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */
+ { "len", 1, opid3('l','e','n'), ASSOC_RIGHT, 98, OP_PREFIX, true}, /* len operator */
{ "++", 1, opid3('S','+','+'), ASSOC_LEFT, 17, OP_SUFFIX, false},
{ "--", 1, opid3('S','-','-'), ASSOC_LEFT, 17, OP_SUFFIX, false},
out = (ast_expression*)asbinstore;
break;
+ case opid3('l', 'e', 'n'):
+ if (exprs[0]->vtype != TYPE_ARRAY && exprs[0]->vtype != TYPE_STRING) {
+ ast_type_to_string(exprs[0], ty1, sizeof(ty1));
+ compile_error(ast_ctx(exprs[0]), "invalid type for length operator: %s", ty1);
+ return false;
+ }
+ if (!(out = fold_op(parser->fold, op, exprs))) {
+ compile_error(ast_ctx(exprs[0]), "expected constant expression as operand to length operator");
+ return false;
+ }
+ break;
+
case opid2('~', 'P'):
if (exprs[0]->vtype != TYPE_FLOAT && exprs[0]->vtype != TYPE_VECTOR) {
ast_type_to_string(exprs[0], ty1, sizeof(ty1));