X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=parser.c;h=bd4f1c14b75936394f238fc9d91547c57955a30b;hb=b971ddec3a7bb56ac6c9bc094916828283838adf;hp=b97d92c3896ee0d26fb9c3a240afc7da2e02bf9b;hpb=d3c7b6fb3997256722ec0ea66bad733f0729ebba;p=xonotic%2Fgmqcc.git diff --git a/parser.c b/parser.c index b97d92c..bd4f1c1 100644 --- a/parser.c +++ b/parser.c @@ -121,6 +121,7 @@ static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value * static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname); static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef); static ast_expression *parser_builtin_pow(parser_t *); +static ast_expression *parser_builtin_exp(parser_t *); static void parseerror(parser_t *parser, const char *fmt, ...) { @@ -1086,7 +1087,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (CanConstFold(exprs[0], exprs[1])) { out = (ast_expression*)parser_const_float(parser, powf(ConstF(0), ConstF(1))); } else { - out = parser_builtin_pow(parser); + ast_call *gencall = ast_call_new(parser_ctx(parser), parser_builtin_pow(parser)); + vec_push(gencall->params, exprs[0]); + vec_push(gencall->params, exprs[1]); + out = (ast_expression*)gencall; } break; @@ -1435,7 +1439,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if(CanConstFold1(exprs[0])) out = (ast_expression*)parser_const_float(parser, ~(qcint)ConstF(0)); else - out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser_const_float_neg1(parser), exprs[0]); + out = (ast_expression*) + ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser_const_float_neg1(parser), exprs[0]); break; } #undef NotSameType @@ -1851,6 +1856,8 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) } if (!strcmp(parser_tokval(parser), "__builtin_pow")) var = parser_builtin_pow(parser); + if (!strcmp(parser_tokval(parser), "__builtin_exp")) + var = parser_builtin_exp(parser); if (!var) { char *correct = NULL; @@ -3321,11 +3328,11 @@ ast_expression *parser_builtin_pow(parser_t *parser) { * float value = 1.0f; * while (y > 0) { * while (!(y&1)) { - * y *= 2; + * y *= 0.25f; * x *= x; * } - * y = y - 1; - * value = x * value; + * y--; + * value *= x; * } * return value; * } @@ -3454,6 +3461,46 @@ ast_expression *parser_builtin_pow(parser_t *parser) { return (ast_expression*)pow_func_val; } +#ifndef M_E +#define M_E 2.71828182845905 +#endif +static ast_expression *parser_builtin_exp(parser_t *parser) { + /* + * float __builtin_exp(float x) { + * return __builtin_exp(E, x); + * } + */ + static ast_value *exp_func_val = NULL; + + if (!exp_func_val) { + ast_function *exp_func = NULL; + ast_value *arg = ast_value_new (parser_ctx(parser), "x", TYPE_FLOAT); + ast_block *exp_body = ast_block_new (parser_ctx(parser)); + ast_call *exp_call = ast_call_new (parser_ctx(parser), parser_builtin_pow(parser)); + exp_func_val = ast_value_new (parser_ctx(parser), "__builtin_exp", TYPE_FUNCTION); + exp_func_val->expression.next = (ast_expression*)ast_value_new(parser_ctx(parser), "", TYPE_FLOAT); + exp_func = ast_function_new(parser_ctx(parser), "__builtin_exp", exp_func_val); + + vec_push(exp_call->params, (ast_expression*)parser_const_float(parser, M_E)); + vec_push(exp_call->params, (ast_expression*)arg); + + vec_push(exp_body->exprs, + (ast_expression*)ast_return_new( + parser_ctx(parser), + (ast_expression*)exp_call + ) + ); + + vec_push(exp_func_val->expression.params, arg); + vec_push(exp_func->blocks, exp_body); + + vec_push(parser->functions, exp_func); + vec_push(parser->globals, (ast_expression*)exp_func_val); + } + + return (ast_expression*)exp_func_val; +} + /* parse computed goto sides */ static ast_expression *parse_goto_computed(parser_t *parser, ast_expression **side) { ast_expression *on_true; @@ -3814,6 +3861,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * static bool parse_enum(parser_t *parser) { + bool flag = false; qcfloat num = 0; ast_value **values = NULL; ast_value *var = NULL; @@ -3821,11 +3869,28 @@ static bool parse_enum(parser_t *parser) ast_expression *old; - if (!parser_next(parser) || parser->tok != '{') { - parseerror(parser, "expected `{` after `enum` keyword"); + if (!parser_next(parser) || (parser->tok != '{' && parser->tok != ':')) { + parseerror(parser, "expected `{` or `:` after `enum` keyword"); return false; } + /* enumeration attributes (can add more later) */ + if (parser->tok == ':') { + if (!parser_next(parser) || parser->tok != TOKEN_IDENT || strcmp(parser_tokval(parser), "flag")) { + parseerror(parser, "expected `flag` after enumeration attribute ':'"); + return false; + } + + if (!parser_next(parser) || parser->tok != '{') { + parseerror(parser, "expected `{` after enum attribute `flag`"); + return false; + } + + /* flagged enumeration start from 1 */ + num = 1; + flag = true; + } + while (true) { if (!parser_next(parser) || parser->tok != TOKEN_IDENT) { if (parser->tok == '}') { @@ -3849,7 +3914,9 @@ static bool parse_enum(parser_t *parser) vec_push(values, var); var->cvq = CV_CONST; var->hasvalue = true; - var->constval.vfloat = num++; + + /* for flagged enumerations increment in POTs of TWO */ + var->constval.vfloat = (flag) ? (num *= 2) : (num ++); parser_addglobal(parser, var->name, (ast_expression*)var);