-
- if (parser->tok == '[') {
- /* got a frame definition: [ framenum, nextthink ]
- * this translates to:
- * self.frame = framenum;
- * self.nextthink = time + 0.1;
- * self.think = nextthink;
- */
- nextthink = NULL;
-
- fld_think = parser_find_field(parser, "think");
- fld_nextthink = parser_find_field(parser, "nextthink");
- fld_frame = parser_find_field(parser, "frame");
- if (!fld_think || !fld_nextthink || !fld_frame) {
- parseerror(parser, "cannot use [frame,think] notation without the required fields");
- parseerror(parser, "please declare the following entityfields: `frame`, `think`, `nextthink`");
- return false;
- }
- gbl_time = parser_find_global(parser, "time");
- gbl_self = parser_find_global(parser, "self");
- if (!gbl_time || !gbl_self) {
- parseerror(parser, "cannot use [frame,think] notation without the required globals");
- parseerror(parser, "please declare the following globals: `time`, `self`");
- return false;
- }
-
- if (!parser_next(parser)) {
- return false;
- }
-
- framenum = parser_expression_leave(parser, true);
- if (!framenum) {
- parseerror(parser, "expected a framenumber constant in[frame,think] notation");
- return false;
- }
- if (!ast_istype(framenum, ast_value) || !( (ast_value*)framenum )->isconst) {
- ast_unref(framenum);
- parseerror(parser, "framenumber in [frame,think] notation must be a constant");
- }
-
- if (parser->tok != ',') {
- ast_unref(framenum);
- parseerror(parser, "expected comma after frame number in [frame,think] notation");
- parseerror(parser, "Got a %i\n", parser->tok);
- return false;
- }
-
- if (!parser_next(parser)) {
- ast_unref(framenum);
- return false;
- }
-
- if (parser->tok == TOKEN_IDENT && !parser_find_var(parser, parser_tokval(parser)))
- {
- /* qc allows the use of not-yet-declared functions here
- * - this automatically creates a prototype */
- varentry_t varent;
- ast_value *thinkfunc;
- ast_expression *functype = fld_think->expression.next;
-
- thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->expression.vtype);
- if (!thinkfunc || !ast_type_adopt(thinkfunc, functype)) {
- ast_unref(framenum);
- parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
- return false;
- }
-
- if (!parser_next(parser)) {
- ast_unref(framenum);
- return false;
- }
-
- varent.var = (ast_expression*)thinkfunc;
- varent.name = util_strdup(thinkfunc->name);
- if (thinkfunc->expression.vtype == TYPE_FUNCTION)
- {
- ast_function *func;
-
- func = ast_function_new(parser_ctx(parser), thinkfunc->name, thinkfunc);
- if (!func) {
- ast_delete(thinkfunc);
- ast_unref(framenum);
- parseerror(parser, "failed to create function for implicit prototype for `%s`",
- thinkfunc->name);
- return false;
- }
- (void)!parser_t_functions_add(parser, func);
- (void)!parser_t_globals_add(parser, varent);
- }
- else
- (void)!parser_t_globals_add(parser, varent);
- nextthink = (ast_expression*)thinkfunc;
-
- } else {
- nextthink = parser_expression_leave(parser, true);
- if (!nextthink) {
- ast_unref(framenum);
- parseerror(parser, "expected a think-function in [frame,think] notation");
- return false;
- }
- }
-
- if (!ast_istype(nextthink, ast_value) || !( (ast_value*)nextthink )->isconst) {
- ast_unref(nextthink);
- ast_unref(framenum);
- parseerror(parser, "think-function in [frame,think] notation must be a constant");
- }
-
- if (parser->tok != ']') {
- parseerror(parser, "expected closing `]` for [frame,think] notation");
- ast_unref(nextthink);
- ast_unref(framenum);
- return false;
- }
-
- if (!parser_next(parser)) {
- ast_unref(nextthink);
- ast_unref(framenum);
- return false;
- }
-
- if (parser->tok != '{') {
- parseerror(parser, "a function body has to be declared after a [frame,think] declaration");
- ast_unref(nextthink);
- ast_unref(framenum);
- return false;
- }
-
- has_frame_think = true;
- }
-
- block = ast_block_new(parser_ctx(parser));
- if (!block) {
- parseerror(parser, "failed to allocate block");