Merge branch 'cooking' of github.com:graphitemaster/gmqcc into cooking

This commit is contained in:
Dale Weiler 2013-10-19 02:53:46 -04:00
commit 0695ad1659
3 changed files with 55 additions and 15 deletions

View file

@ -44,7 +44,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels); static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels);
static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname); static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname);
static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname); 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_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef, bool *is_vararg);
static void parseerror(parser_t *parser, const char *fmt, ...) static void parseerror(parser_t *parser, const char *fmt, ...)
{ {
@ -1422,7 +1422,7 @@ static ast_expression* parse_vararg_do(parser_t *parser)
return NULL; return NULL;
} }
typevar = parse_typename(parser, NULL, NULL); typevar = parse_typename(parser, NULL, NULL, NULL);
if (!typevar) { if (!typevar) {
ast_unref(idx); ast_unref(idx);
return NULL; return NULL;
@ -4505,7 +4505,6 @@ static bool parser_create_array_getter(parser_t *parser, ast_value *array, const
return parser_create_array_getter_impl(parser, array); return parser_create_array_getter_impl(parser, array);
} }
static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef);
static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
{ {
lex_ctx_t ctx; lex_ctx_t ctx;
@ -4531,6 +4530,8 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
/* parse variables until we hit a closing paren */ /* parse variables until we hit a closing paren */
while (parser->tok != ')') { while (parser->tok != ')') {
bool is_varargs = false;
if (!first) { if (!first) {
/* there must be commas between them */ /* there must be commas between them */
if (parser->tok != ',') { if (parser->tok != ',') {
@ -4544,10 +4545,13 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
} }
first = false; first = false;
if (parser->tok == TOKEN_DOTS) { param = parse_typename(parser, NULL, NULL, &is_varargs);
if (!param && !is_varargs)
goto on_error;
if (is_varargs) {
/* '...' indicates a varargs function */ /* '...' indicates a varargs function */
variadic = true; variadic = true;
if (!parser_next(parser) || (parser->tok != ')' && parser->tok != TOKEN_IDENT)) { if (parser->tok != ')' && parser->tok != TOKEN_IDENT) {
parseerror(parser, "`...` must be the last parameter of a variadic function declaration"); parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
goto on_error; goto on_error;
} }
@ -4558,13 +4562,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
goto on_error; goto on_error;
} }
} }
} } else {
else
{
/* for anything else just parse a typename */
param = parse_typename(parser, NULL, NULL);
if (!param)
goto on_error;
vec_push(params, param); vec_push(params, param);
if (param->expression.vtype >= TYPE_VARIANT) { if (param->expression.vtype >= TYPE_VARIANT) {
char tname[1024]; /* typename is reserved in C++ */ char tname[1024]; /* typename is reserved in C++ */
@ -4716,7 +4714,7 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var)
* void() foo(), bar * void() foo(), bar
* then the type-information 'void()' can be stored in 'storebase' * then the type-information 'void()' can be stored in 'storebase'
*/ */
static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef) static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef, bool *is_vararg)
{ {
ast_value *var, *tmp; ast_value *var, *tmp;
lex_ctx_t ctx; lex_ctx_t ctx;
@ -4726,6 +4724,8 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
bool wasarray = false; bool wasarray = false;
size_t morefields = 0; size_t morefields = 0;
bool vararg = (parser->tok == TOKEN_DOTS);
ctx = parser_ctx(parser); ctx = parser_ctx(parser);
/* types may start with a dot */ /* types may start with a dot */
@ -4749,6 +4749,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
morefields += 3; morefields += 3;
else else
break; break;
vararg = false;
if (!parser_next(parser)) { if (!parser_next(parser)) {
parseerror(parser, "expected typename for field definition"); parseerror(parser, "expected typename for field definition");
return NULL; return NULL;
@ -4758,6 +4759,10 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
if (parser->tok == TOKEN_IDENT) if (parser->tok == TOKEN_IDENT)
cached_typedef = parser_find_typedef(parser, parser_tokval(parser), 0); cached_typedef = parser_find_typedef(parser, parser_tokval(parser), 0);
if (!cached_typedef && parser->tok != TOKEN_TYPENAME) { if (!cached_typedef && parser->tok != TOKEN_TYPENAME) {
if (vararg && is_vararg) {
*is_vararg = true;
return NULL;
}
parseerror(parser, "expected typename"); parseerror(parser, "expected typename");
return NULL; return NULL;
} }
@ -4878,7 +4883,7 @@ static bool parse_typedef(parser_t *parser)
ast_value *typevar, *oldtype; ast_value *typevar, *oldtype;
ast_expression *old; ast_expression *old;
typevar = parse_typename(parser, NULL, NULL); typevar = parse_typename(parser, NULL, NULL, NULL);
if (!typevar) if (!typevar)
return false; return false;
@ -5048,7 +5053,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
parseerror(parser, "`static` qualifier is not supported in global scope"); parseerror(parser, "`static` qualifier is not supported in global scope");
/* get the first complete variable */ /* get the first complete variable */
var = parse_typename(parser, &basetype, cached_typedef); var = parse_typename(parser, &basetype, cached_typedef, NULL);
if (!var) { if (!var) {
if (basetype) if (basetype)
ast_delete(basetype); ast_delete(basetype);

27
tests/dots.qc Normal file
View file

@ -0,0 +1,27 @@
entity self;
.float f;
..float fp;
...float fpp;
void try(entity e, ...float pp) {
print("and: ", ftos( e.(e.(e.pp)) ), "\n");
}
typedef float Float;
void try2(entity e, ...Float pp) {
print("and: ", ftos( e.(e.(e.pp)) ), "\n");
}
// whereas the varargs are tested in vararg tests
void main() {
self = spawn();
self.f = 123;
self.fp = f;
self.fpp = fp;
print(ftos( self.(self.fp) ), "\n");
print(ftos( self.(self.(self.fpp)) ), "\n");
try(self, fpp);
try2(self, fpp);
}

8
tests/dots.tmpl Normal file
View file

@ -0,0 +1,8 @@
I: dots.qc
D: TOKEN_DOTS disambiguation
T: -execute
C: -std=fteqcc
M: 123
M: 123
M: and: 123
M: and: 123