glsl: Finish out the reduce/reduce error fixes
authorIan Romanick <ian.d.romanick@intel.com>
Fri, 28 Jan 2011 01:52:19 +0000 (17:52 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 11 Feb 2011 22:12:43 +0000 (14:12 -0800)
Track variables, functions, and types during parsing.  Use this
information in the lexer to return the currect "type" for identifiers.

Change the handling of structure constructors.  They will now show up
in the AST as constructors (instead of plain function calls).

Fixes piglit tests constructor-18.vert, constructor-19.vert, and
constructor-20.vert.  Also fixes bugzilla #29926.

NOTE: This is a candidate for the 7.9 and 7.10 branches.

src/glsl/ast_function.cpp
src/glsl/glsl_lexer.lpp
src/glsl/glsl_parser.ypp

index 7611617df7e74a3b6af900a6c57f88bf3c8a4ee0..e5cb8733952f3f05266f3618afdc4253cd1c58b1 100644 (file)
@@ -1017,6 +1017,16 @@ ast_function_expression::hir(exec_list *instructions,
 
       const glsl_type *const constructor_type = type->glsl_type(& name, state);
 
+      /* constructor_type can be NULL if a variable with the same name as the
+       * structure has come into scope.
+       */
+      if (constructor_type == NULL) {
+        _mesa_glsl_error(& loc, state, "unknown type `%s' (structure name "
+                         "may be shadowed by a variable with the same name)",
+                         type->type_name);
+        return ir_call::get_error_instruction(ctx);
+      }
+
 
       /* Constructors for samplers are illegal.
        */
@@ -1046,6 +1056,57 @@ ast_function_expression::hir(exec_list *instructions,
        * correct order.  These constructors follow essentially the same type
        * matching rules as functions.
        */
+      if (constructor_type->is_record()) {
+        exec_list actual_parameters;
+
+        process_parameters(instructions, &actual_parameters,
+                           &this->expressions, state);
+
+        exec_node *node = actual_parameters.head;
+        for (unsigned i = 0; i < constructor_type->length; i++) {
+           ir_rvalue *ir = (ir_rvalue *) node;
+
+           if (node->is_tail_sentinel()) {
+              _mesa_glsl_error(&loc, state,
+                               "insufficient parameters to constructor "
+                               "for `%s'",
+                               constructor_type->name);
+              return ir_call::get_error_instruction(ctx);
+           }
+
+           if (apply_implicit_conversion(constructor_type->fields.structure[i].type,
+                                         ir, state)) {
+              node->replace_with(ir);
+           } else {
+              _mesa_glsl_error(&loc, state,
+                               "parameter type mismatch in constructor "
+                               "for `%s.%s' (%s vs %s)",
+                               constructor_type->name,
+                               constructor_type->fields.structure[i].name,
+                               ir->type->name,
+                               constructor_type->fields.structure[i].type->name);
+              return ir_call::get_error_instruction(ctx);;
+           }
+
+           node = node->next;
+        }
+
+        if (!node->is_tail_sentinel()) {
+           _mesa_glsl_error(&loc, state, "too many parameters in constructor "
+                            "for `%s'", constructor_type->name);
+           return ir_call::get_error_instruction(ctx);
+        }
+
+        ir_rvalue *const constant =
+           constant_record_constructor(constructor_type, &actual_parameters,
+                                       state);
+
+        return (constant != NULL)
+           ? constant
+           : emit_inline_record_constructor(constructor_type, instructions,
+                                            &actual_parameters, state);
+      }
+
       if (!constructor_type->is_numeric() && !constructor_type->is_boolean())
         return ir_call::get_error_instruction(ctx);
 
@@ -1221,54 +1282,6 @@ ast_function_expression::hir(exec_list *instructions,
       process_parameters(instructions, &actual_parameters, &this->expressions,
                         state);
 
-      const glsl_type *const type =
-        state->symbols->get_type(id->primary_expression.identifier);
-
-      if ((type != NULL) && type->is_record()) {
-        exec_node *node = actual_parameters.head;
-        for (unsigned i = 0; i < type->length; i++) {
-           ir_rvalue *ir = (ir_rvalue *) node;
-
-           if (node->is_tail_sentinel()) {
-              _mesa_glsl_error(&loc, state,
-                               "insufficient parameters to constructor "
-                               "for `%s'",
-                               type->name);
-              return ir_call::get_error_instruction(ctx);
-           }
-
-           if (apply_implicit_conversion(type->fields.structure[i].type, ir,
-                                         state)) {
-              node->replace_with(ir);
-           } else {
-              _mesa_glsl_error(&loc, state,
-                               "parameter type mismatch in constructor "
-                               "for `%s.%s' (%s vs %s)",
-                               type->name,
-                               type->fields.structure[i].name,
-                               ir->type->name,
-                               type->fields.structure[i].type->name);
-              return ir_call::get_error_instruction(ctx);;
-           }
-
-           node = node->next;
-        }
-
-        if (!node->is_tail_sentinel()) {
-           _mesa_glsl_error(&loc, state, "too many parameters in constructor "
-                            "for `%s'", type->name);
-           return ir_call::get_error_instruction(ctx);
-        }
-
-        ir_rvalue *const constant =
-           constant_record_constructor(type, &actual_parameters, state);
-
-        return (constant != NULL)
-           ? constant
-           : emit_inline_record_constructor(type, instructions,
-                                            &actual_parameters, state);
-      }
-
       return match_function_by_name(instructions, 
                                    id->primary_expression.identifier, & loc,
                                    &actual_parameters, state);
index d3d53ffb68e0966360d58a56bd98cedd7711a341..e4c469f9e0af8be3185bb0a64426dafc21b32ab7 100644 (file)
@@ -27,6 +27,8 @@
 #include "glsl_parser_extras.h"
 #include "glsl_parser.h"
 
+static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
+
 #define YY_USER_ACTION                                         \
    do {                                                                \
       yylloc->source = 0;                                      \
@@ -62,7 +64,7 @@
         return ERROR_TOK;                                              \
       } else {                                                         \
         yylval->identifier = strdup(yytext);                           \
-        return IDENTIFIER;                                             \
+        return classify_identifier(yyextra, yytext);                   \
       }                                                                        \
    } while (0)
 
@@ -419,13 +421,24 @@ row_major KEYWORD(130, 999, ROW_MAJOR);
                            struct _mesa_glsl_parse_state *state = yyextra;
                            void *ctx = state;  
                            yylval->identifier = ralloc_strdup(ctx, yytext);
-                           return IDENTIFIER;
+                           return classify_identifier(state, yytext);
                        }
 
 .                      { return yytext[0]; }
 
 %%
 
+int
+classify_identifier(struct _mesa_glsl_parse_state *state, const char *name)
+{
+   if (state->symbols->get_variable(name) || state->symbols->get_function(name))
+      return IDENTIFIER;
+   else if (state->symbols->get_type(name))
+      return TYPE_IDENTIFIER;
+   else
+      return NEW_IDENTIFIER;
+}
+
 void
 _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
 {
index dd23279aaae2e9a273bee2ce784d82ddae400525..2c0498ece7a946a357ffc01d6e40a3b90d2a3faf 100644 (file)
@@ -219,6 +219,11 @@ translation_unit:
           _mesa_glsl_initialize_types(state);
        }
        external_declaration_list
+       {
+          delete state->symbols;
+          state->symbols = new(ralloc_parent(state)) glsl_symbol_table;
+          _mesa_glsl_initialize_types(state);
+       }
        ;
 
 version_statement:
@@ -759,6 +764,7 @@ constant_expression:
 declaration:
        function_prototype ';'
        {
+          state->symbols->pop_scope();
           $$ = $1;
        }
        | init_declarator_list ';'
@@ -803,6 +809,9 @@ function_header:
           $$->set_location(yylloc);
           $$->return_type = $1;
           $$->identifier = $2;
+
+          state->symbols->add_function(new(state) ir_function($2));
+          state->symbols->push_scope();
        }
        ;
 
@@ -903,6 +912,7 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
        | init_declarator_list ',' any_identifier '[' ']'
        {
@@ -912,6 +922,7 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
        | init_declarator_list ',' any_identifier '[' constant_expression ']'
        {
@@ -921,6 +932,7 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
        | init_declarator_list ',' any_identifier '[' ']' '=' initializer
        {
@@ -930,6 +942,7 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
        | init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer
        {
@@ -939,6 +952,7 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
        | init_declarator_list ',' any_identifier '=' initializer
        {
@@ -948,6 +962,7 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
        ;
 
@@ -1018,7 +1033,7 @@ single_declaration:
           $$->set_location(yylloc);
           $$->declarations.push_tail(&decl->link);
        }
-       | INVARIANT IDENTIFIER // Vertex only.
+       | INVARIANT variable_identifier // Vertex only.
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
@@ -1077,7 +1092,7 @@ layout_qualifier_id_list:
        ;
 
 layout_qualifier_id:
-       IDENTIFIER
+       any_identifier
        {
           bool got_one = false;
 
@@ -1129,7 +1144,7 @@ layout_qualifier_id:
              YYERROR;
           }
        }
-       | IDENTIFIER '=' INTCONSTANT
+       | any_identifier '=' INTCONSTANT
        {
           bool got_one = false;
 
@@ -1413,11 +1428,12 @@ precision_qualifier:
        ;
 
 struct_specifier:
-       STRUCT IDENTIFIER '{' struct_declaration_list '}'
+       STRUCT any_identifier '{' struct_declaration_list '}'
        {
           void *ctx = state;
           $$ = new(ctx) ast_struct_specifier($2, $4);
           $$->set_location(yylloc);
+          state->symbols->add_type($2, glsl_type::void_type);
        }
        | STRUCT '{' struct_declaration_list '}'
        {
@@ -1469,13 +1485,14 @@ struct_declarator_list:
        ;
 
 struct_declarator:
-       IDENTIFIER
+       any_identifier
        {
           void *ctx = state;
           $$ = new(ctx) ast_declaration($1, false, NULL, NULL);
           $$->set_location(yylloc);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $1, ir_var_auto));
        }
-       | IDENTIFIER '[' constant_expression ']'
+       | any_identifier '[' constant_expression ']'
        {
           void *ctx = state;
           $$ = new(ctx) ast_declaration($1, true, $3, NULL);
@@ -1515,11 +1532,16 @@ compound_statement:
           $$ = new(ctx) ast_compound_statement(true, NULL);
           $$->set_location(yylloc);
        }
-       | '{' statement_list '}'
+       | '{'
+       {
+          state->symbols->push_scope();
+       }
+       statement_list '}'
        {
           void *ctx = state;
-          $$ = new(ctx) ast_compound_statement(true, $2);
+          $$ = new(ctx) ast_compound_statement(true, $3);
           $$->set_location(yylloc);
+          state->symbols->pop_scope();
        }
        ;
 
@@ -1607,7 +1629,7 @@ condition:
        {
           $$ = (ast_node *) $1;
        }
-       | fully_specified_type IDENTIFIER '=' initializer
+       | fully_specified_type any_identifier '=' initializer
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
@@ -1727,5 +1749,7 @@ function_definition:
           $$->set_location(yylloc);
           $$->prototype = $1;
           $$->body = $2;
+
+          state->symbols->pop_scope();
        }
        ;