mojoshader_compiler.c
changeset 964 e8c09c28162e
parent 958 02e7826c8c75
child 966 9dd4107eed42
equal deleted inserted replaced
963:5a8f7ef13735 964:e8c09c28162e
    56 typedef union TokenData
    56 typedef union TokenData
    57 {
    57 {
    58     int64 i64;
    58     int64 i64;
    59     double dbl;
    59     double dbl;
    60     const char *string;
    60     const char *string;
       
    61     const MOJOSHADER_astDataType *datatype;
    61 } TokenData;
    62 } TokenData;
    62 
    63 
    63 
    64 
    64 // This tracks data types and variables, and notes when they enter/leave scope.
    65 // This tracks data types and variables, and notes when they enter/leave scope.
    65 
    66 
    66 typedef struct SymbolScope
    67 typedef struct SymbolScope
    67 {
    68 {
    68     const char *symbol;
    69     const char *symbol;
    69     const char *datatype;
    70     const MOJOSHADER_astDataType *datatype;
    70     struct SymbolScope *next;
    71     struct SymbolScope *next;
    71 } SymbolScope;
    72 } SymbolScope;
    72 
    73 
    73 typedef struct SymbolMap
    74 typedef struct SymbolMap
    74 {
    75 {
    94     SymbolMap usertypes;
    95     SymbolMap usertypes;
    95     SymbolMap variables;
    96     SymbolMap variables;
    96     MOJOSHADER_astNode *ast;  // Abstract Syntax Tree
    97     MOJOSHADER_astNode *ast;  // Abstract Syntax Tree
    97     const char *source_profile;
    98     const char *source_profile;
    98 
    99 
    99     // These are entries allocated in the strcache, so these pointers are
   100     // Cache intrinsic types for fast lookup and consistent pointer values.
   100     //  valid from shortly after we create the cache until we destroy it
   101     MOJOSHADER_astDataType dt_bool;
   101     //  with the rest of the context. This makes it so we can compare common
   102     MOJOSHADER_astDataType dt_int;
   102     //  strings by pointer without having to hash them every time, so long as
   103     MOJOSHADER_astDataType dt_uint;
   103     //  we're comparing a string pointer we know came from this string cache.
   104     MOJOSHADER_astDataType dt_float;
   104     // The first batch are simplifed datatype strings ("b" == bool, etc).
   105     MOJOSHADER_astDataType dt_float_snorm;
   105     const char *str_b;  // "b"
   106     MOJOSHADER_astDataType dt_float_unorm;
   106     const char *str_f;  // "f"
   107     MOJOSHADER_astDataType dt_half;
   107     const char *str_i;  // "i"
   108     MOJOSHADER_astDataType dt_double;
   108     const char *str_u;  // "u"
   109     MOJOSHADER_astDataType dt_string;
   109     const char *str_h;  // "h"
   110     MOJOSHADER_astDataType dt_sampler1d;
   110     const char *str_d;  // "d"
   111     MOJOSHADER_astDataType dt_sampler2d;
   111     const char *str_s;  // "s"
   112     MOJOSHADER_astDataType dt_sampler3d;
   112     const char *str_S;  // "S"
   113     MOJOSHADER_astDataType dt_samplercube;
   113     const char *str_s1;  // "s1"
   114     MOJOSHADER_astDataType dt_samplerstate;
   114     const char *str_s2;  // "s2"
   115     MOJOSHADER_astDataType dt_samplercompstate;
   115     const char *str_s3;  // "s3"
   116     MOJOSHADER_astDataType dt_buf_bool;
   116     const char *str_sc;  // "sc"
   117     MOJOSHADER_astDataType dt_buf_int;
   117     const char *str_ss;  // "ss"
   118     MOJOSHADER_astDataType dt_buf_uint;
   118     const char *str_sS;  // "sS"
   119     MOJOSHADER_astDataType dt_buf_half;
   119     const char *str_Fs;  // "Fs"
   120     MOJOSHADER_astDataType dt_buf_float;
   120     const char *str_Fu;  // "Fu"
   121     MOJOSHADER_astDataType dt_buf_double;
   121     const char *str_ns;  // "ns"
   122     MOJOSHADER_astDataType dt_buf_float_snorm;
   122     const char *str_nu;  // "nu"
   123     MOJOSHADER_astDataType dt_buf_float_unorm;
       
   124 
       
   125     Buffer *garbage;  // this is sort of hacky.
   123 } Context;
   126 } Context;
   124 
   127 
   125 
   128 
   126 // !!! FIXME: cut and paste between every damned source file follows...
   129 // !!! FIXME: cut and paste between every damned source file follows...
   127 // !!! FIXME: We need to make some sort of ContextBase that applies to all
   130 // !!! FIXME: We need to make some sort of ContextBase that applies to all
   217     return (map->hash != NULL);
   220     return (map->hash != NULL);
   218 } // create_symbolmap
   221 } // create_symbolmap
   219 
   222 
   220 
   223 
   221 static void push_symbol(Context *ctx, SymbolMap *map,
   224 static void push_symbol(Context *ctx, SymbolMap *map,
   222                         const char *sym, const char *datatype)
   225                         const char *sym, const MOJOSHADER_astDataType *dt)
   223 {
   226 {
   224     // !!! FIXME: decide if this symbol is defined, and if so, if it's in
   227     // !!! FIXME: decide if this symbol is defined, and if so, if it's in
   225     // !!! FIXME:  the current scope.
   228     // !!! FIXME:  the current scope.
   226 
   229 
   227     SymbolScope *item = (SymbolScope *) Malloc(ctx, sizeof (SymbolScope));
   230     SymbolScope *item = (SymbolScope *) Malloc(ctx, sizeof (SymbolScope));
   228     if (item == NULL)
   231     if (item == NULL)
   229         return;
   232         return;
   230 
   233 
   231     if (sym != NULL)
   234     if (sym != NULL)
   232     {
   235     {
   233         if (hash_insert(map->hash, sym, datatype) == -1)
   236         if (hash_insert(map->hash, sym, dt) == -1)
   234         {
   237         {
   235             Free(ctx, item);
   238             Free(ctx, item);
   236             return;
   239             return;
   237         } // if
   240         } // if
   238     } // if
   241     } // if
   239 
   242 
   240     item->symbol = sym;  // cached strings, don't copy.
   243     item->symbol = sym;  // cached strings, don't copy.
   241     item->datatype = datatype;
   244     item->datatype = dt;
   242     item->next = map->scope;
   245     item->next = map->scope;
   243     map->scope = item;
   246     map->scope = item;
   244 } // push_symbol
   247 } // push_symbol
   245 
   248 
   246 static inline void push_usertype(Context *ctx, const char *sym, const char *dt)
   249 static void push_usertype(Context *ctx, const char *sym, const MOJOSHADER_astDataType *dt)
   247 {
   250 {
       
   251     if (sym != NULL)
       
   252     {
       
   253         MOJOSHADER_astDataType *userdt;
       
   254         userdt = (MOJOSHADER_astDataType *) Malloc(ctx, sizeof (*userdt));
       
   255         if (userdt != NULL)
       
   256         {
       
   257             // !!! FIXME: this is hacky.
       
   258             if (!buffer_append(ctx->garbage, &userdt, sizeof (userdt)))
       
   259             {
       
   260                 Free(ctx, userdt);
       
   261                 userdt = NULL;
       
   262             } // if
       
   263 
       
   264             userdt->type = MOJOSHADER_AST_DATATYPE_USER;
       
   265             userdt->user.details = dt;
       
   266             userdt->user.name = sym;
       
   267 
       
   268             dt = userdt;
       
   269         } // if
       
   270     } // if
       
   271 
   248     push_symbol(ctx, &ctx->usertypes, sym, dt);
   272     push_symbol(ctx, &ctx->usertypes, sym, dt);
   249 } // push_usertype
   273 } // push_usertype
   250 
   274 
   251 static inline void push_variable(Context *ctx, const char *sym, const char *dt)
   275 static inline void push_variable(Context *ctx, const char *sym, const MOJOSHADER_astDataType *dt)
   252 {
   276 {
   253     push_symbol(ctx, &ctx->variables, sym, dt);
   277     push_symbol(ctx, &ctx->variables, sym, dt);
   254 } // push_variable
   278 } // push_variable
   255 
   279 
   256 static inline void push_scope(Context *ctx)
   280 static inline void push_scope(Context *ctx)
   285 {
   309 {
   286     pop_symbol_scope(ctx, &ctx->usertypes);
   310     pop_symbol_scope(ctx, &ctx->usertypes);
   287     pop_symbol_scope(ctx, &ctx->variables);
   311     pop_symbol_scope(ctx, &ctx->variables);
   288 } // push_scope
   312 } // push_scope
   289 
   313 
   290 static const char *find_symbol(Context *ctx, SymbolMap *map, const char *sym)
   314 static const MOJOSHADER_astDataType *find_symbol(Context *ctx, SymbolMap *map, const char *sym)
   291 {
   315 {
   292     const void *value = NULL;
   316     const void *value = NULL;
   293     hash_find(map->hash, sym, &value);
   317     hash_find(map->hash, sym, &value);
   294     return (const char *) value;
   318     return (const MOJOSHADER_astDataType *) value;
   295 } // find_symbol
   319 } // find_symbol
   296 
   320 
   297 static inline const char *find_usertype(Context *ctx, const char *sym)
   321 static inline const MOJOSHADER_astDataType *find_usertype(Context *ctx, const char *sym)
   298 {
   322 {
   299     return find_symbol(ctx, &ctx->usertypes, sym);
   323     return find_symbol(ctx, &ctx->usertypes, sym);
   300 } // find_usertype
   324 } // find_usertype
   301 
   325 
   302 static inline const char *find_variable(Context *ctx, const char *sym)
   326 static inline const MOJOSHADER_astDataType *find_variable(Context *ctx, const char *sym)
   303 {
   327 {
   304     return find_symbol(ctx, &ctx->variables, sym);
   328     return find_symbol(ctx, &ctx->variables, sym);
   305 } // find_variable
   329 } // find_variable
   306 
   330 
   307 static void destroy_symbolmap(Context *ctx, SymbolMap *map)
   331 static void destroy_symbolmap(Context *ctx, SymbolMap *map)
   310         pop_symbol(ctx, map);
   334         pop_symbol(ctx, map);
   311     hash_destroy(map->hash);
   335     hash_destroy(map->hash);
   312 } // destroy_symbolmap
   336 } // destroy_symbolmap
   313 
   337 
   314 
   338 
   315 // !!! FIXME: move this to to mojoshader_ast.c
   339 static const MOJOSHADER_astDataType *new_datatype_vector(Context *ctx,
       
   340                                             const MOJOSHADER_astDataType *dt,
       
   341                                             const int columns)
       
   342 {
       
   343     MOJOSHADER_astDataType *retval;
       
   344     retval = (MOJOSHADER_astDataType *) Malloc(ctx, sizeof (*retval));
       
   345     if (retval == NULL)
       
   346         return NULL;
       
   347 
       
   348     // !!! FIXME: this is hacky.
       
   349     // !!! FIXME:  I'd like to cache these anyhow and reuse types.
       
   350     if (!buffer_append(ctx->garbage, &retval, sizeof (retval)))
       
   351     {
       
   352         Free(ctx, retval);
       
   353         return NULL;
       
   354     } // if
       
   355 
       
   356     if ((columns < 1) || (columns > 4))
       
   357         fail(ctx, "Vector must have between 1 and 4 elements");
       
   358 
       
   359     retval->type = MOJOSHADER_AST_DATATYPE_VECTOR;
       
   360     retval->vector.base = dt;
       
   361     retval->vector.elements = columns;
       
   362     return retval;
       
   363 } // new_datatype_vector
       
   364 
       
   365 static const MOJOSHADER_astDataType *new_datatype_matrix(Context *ctx,
       
   366                                             const MOJOSHADER_astDataType *dt,
       
   367                                             const int rows, const int columns)
       
   368 {
       
   369     MOJOSHADER_astDataType *retval;
       
   370     // !!! FIXME: allocate enough for a matrix, but we need to cleanup things that copy without checking for subsize.
       
   371     retval = (MOJOSHADER_astDataType *) Malloc(ctx, sizeof (*retval));
       
   372     if (retval == NULL)
       
   373         return NULL;
       
   374 
       
   375     // !!! FIXME: this is hacky.
       
   376     // !!! FIXME:  I'd like to cache these anyhow and reuse types.
       
   377     if (!buffer_append(ctx->garbage, &retval, sizeof (retval)))
       
   378     {
       
   379         Free(ctx, retval);
       
   380         return NULL;
       
   381     } // if
       
   382 
       
   383     if ((rows < 1) || (rows > 4))
       
   384         fail(ctx, "Matrix must have between 1 and 4 rows");
       
   385     if ((columns < 1) || (columns > 4))
       
   386         fail(ctx, "Matrix must have between 1 and 4 columns");
       
   387 
       
   388     retval->type = MOJOSHADER_AST_DATATYPE_MATRIX;
       
   389     retval->matrix.base = dt;
       
   390     retval->matrix.rows = rows;
       
   391     retval->matrix.columns = columns;
       
   392     return retval;
       
   393 } // new_datatype_matrix
       
   394 
       
   395 
       
   396 // !!! FIXME: move this to mojoshader_ast.c
   316 // !!! FIXME: new_* and delete_* should take an allocator, not a context.
   397 // !!! FIXME: new_* and delete_* should take an allocator, not a context.
   317 
   398 
   318 // These functions are mostly for construction and cleanup of nodes in the
   399 // These functions are mostly for construction and cleanup of nodes in the
   319 //  parse tree. Mostly this is simple allocation and initialization, so we
   400 //  parse tree. Mostly this is simple allocation and initialization, so we
   320 //  can do as little in the lemon code as possible, and then sort it all out
   401 //  can do as little in the lemon code as possible, and then sort it all out
   331 
   412 
   332 #define DELETE_AST_NODE(cls) do { \
   413 #define DELETE_AST_NODE(cls) do { \
   333     if (!cls) return; \
   414     if (!cls) return; \
   334 } while (0)
   415 } while (0)
   335 
   416 
       
   417 
   336 static void delete_compilation_unit(Context*, MOJOSHADER_astCompilationUnit*);
   418 static void delete_compilation_unit(Context*, MOJOSHADER_astCompilationUnit*);
   337 static void delete_statement(Context *ctx, MOJOSHADER_astStatement *stmt);
   419 static void delete_statement(Context *ctx, MOJOSHADER_astStatement *stmt);
   338 
   420 
   339 static MOJOSHADER_astExpression *new_callfunc_expr(Context *ctx,
   421 static MOJOSHADER_astExpression *new_callfunc_expr(Context *ctx,
   340                                         MOJOSHADER_astExpression *identifier,
   422                                         MOJOSHADER_astExpression *identifier,
   346     retval->args = args;
   428     retval->args = args;
   347     return (MOJOSHADER_astExpression *) retval;
   429     return (MOJOSHADER_astExpression *) retval;
   348 } // new_callfunc_expr
   430 } // new_callfunc_expr
   349 
   431 
   350 static MOJOSHADER_astExpression *new_constructor_expr(Context *ctx,
   432 static MOJOSHADER_astExpression *new_constructor_expr(Context *ctx,
   351                                                 const char *datatype,
   433                                             const MOJOSHADER_astDataType *dt,
   352                                                 MOJOSHADER_astArguments *args)
   434                                             MOJOSHADER_astArguments *args)
   353 {
   435 {
   354     NEW_AST_NODE(retval, MOJOSHADER_astExpressionConstructor,
   436     NEW_AST_NODE(retval, MOJOSHADER_astExpressionConstructor,
   355                  MOJOSHADER_AST_OP_CONSTRUCTOR);
   437                  MOJOSHADER_AST_OP_CONSTRUCTOR);
   356     retval->datatype = datatype;
   438     retval->datatype = dt;
   357     retval->args = args;
   439     retval->args = args;
   358     return (MOJOSHADER_astExpression *) retval;
   440     return (MOJOSHADER_astExpression *) retval;
   359 } // new_constructor_expr
   441 } // new_constructor_expr
   360 
   442 
   361 static MOJOSHADER_astExpression *new_cast_expr(Context *ctx,
   443 static MOJOSHADER_astExpression *new_cast_expr(Context *ctx,
   362                                             const char *datatype,
   444                                             const MOJOSHADER_astDataType *dt,
   363                                             MOJOSHADER_astExpression *operand)
   445                                             MOJOSHADER_astExpression *operand)
   364 {
   446 {
   365     NEW_AST_NODE(retval, MOJOSHADER_astExpressionCast, MOJOSHADER_AST_OP_CAST);
   447     NEW_AST_NODE(retval, MOJOSHADER_astExpressionCast, MOJOSHADER_AST_OP_CAST);
   366     retval->datatype = datatype;
   448     retval->datatype = dt;
   367     retval->operand = operand;
   449     retval->operand = operand;
   368     return (MOJOSHADER_astExpression *) retval;
   450     return (MOJOSHADER_astExpression *) retval;
   369 } // new_cast_expr
   451 } // new_cast_expr
   370 
   452 
   371 static MOJOSHADER_astExpression *new_unary_expr(Context *ctx,
   453 static MOJOSHADER_astExpression *new_unary_expr(Context *ctx,
   396                                             MOJOSHADER_astExpression *center,
   478                                             MOJOSHADER_astExpression *center,
   397                                             MOJOSHADER_astExpression *right)
   479                                             MOJOSHADER_astExpression *right)
   398 {
   480 {
   399     NEW_AST_NODE(retval, MOJOSHADER_astExpressionTernary, op);
   481     NEW_AST_NODE(retval, MOJOSHADER_astExpressionTernary, op);
   400     assert(operator_is_ternary(op));
   482     assert(operator_is_ternary(op));
       
   483     assert(op == MOJOSHADER_AST_OP_CONDITIONAL);
       
   484     retval->datatype = &ctx->dt_bool;
   401     retval->left = left;
   485     retval->left = left;
   402     retval->center = center;
   486     retval->center = center;
   403     retval->right = right;
   487     retval->right = right;
   404     return (MOJOSHADER_astExpression *) retval;
   488     return (MOJOSHADER_astExpression *) retval;
   405 } // new_ternary_expr
   489 } // new_ternary_expr
   410 {
   494 {
   411     NEW_AST_NODE(retval, MOJOSHADER_astExpressionDerefStruct,
   495     NEW_AST_NODE(retval, MOJOSHADER_astExpressionDerefStruct,
   412                  MOJOSHADER_AST_OP_DEREF_STRUCT);
   496                  MOJOSHADER_AST_OP_DEREF_STRUCT);
   413     retval->identifier = identifier;
   497     retval->identifier = identifier;
   414     retval->member = member;  // cached; don't copy string.
   498     retval->member = member;  // cached; don't copy string.
       
   499     retval->isswizzle = 0;  // may change during semantic analysis.
   415     return (MOJOSHADER_astExpression *) retval;
   500     return (MOJOSHADER_astExpression *) retval;
   416 } // new_deref_struct_expr
   501 } // new_deref_struct_expr
   417 
   502 
   418 static MOJOSHADER_astExpression *new_identifier_expr(Context *ctx,
   503 static MOJOSHADER_astExpression *new_identifier_expr(Context *ctx,
   419                                                      const char *string)
   504                                                      const char *string)
   427 static MOJOSHADER_astExpression *new_literal_int_expr(Context *ctx,
   512 static MOJOSHADER_astExpression *new_literal_int_expr(Context *ctx,
   428                                                        const int value)
   513                                                        const int value)
   429 {
   514 {
   430     NEW_AST_NODE(retval, MOJOSHADER_astExpressionIntLiteral,
   515     NEW_AST_NODE(retval, MOJOSHADER_astExpressionIntLiteral,
   431                  MOJOSHADER_AST_OP_INT_LITERAL);
   516                  MOJOSHADER_AST_OP_INT_LITERAL);
       
   517     retval->datatype = &ctx->dt_int;
   432     retval->value = value;
   518     retval->value = value;
   433     return (MOJOSHADER_astExpression *) retval;
   519     return (MOJOSHADER_astExpression *) retval;
   434 } // new_literal_int_expr
   520 } // new_literal_int_expr
   435 
   521 
   436 static MOJOSHADER_astExpression *new_literal_float_expr(Context *ctx,
   522 static MOJOSHADER_astExpression *new_literal_float_expr(Context *ctx,
   437                                                         const double dbl)
   523                                                         const double dbl)
   438 {
   524 {
   439     NEW_AST_NODE(retval, MOJOSHADER_astExpressionFloatLiteral,
   525     NEW_AST_NODE(retval, MOJOSHADER_astExpressionFloatLiteral,
   440                  MOJOSHADER_AST_OP_FLOAT_LITERAL);
   526                  MOJOSHADER_AST_OP_FLOAT_LITERAL);
       
   527     retval->datatype = &ctx->dt_float;
   441     retval->value = dbl;
   528     retval->value = dbl;
   442     return (MOJOSHADER_astExpression *) retval;
   529     return (MOJOSHADER_astExpression *) retval;
   443 } // new_literal_float_expr
   530 } // new_literal_float_expr
   444 
   531 
   445 static MOJOSHADER_astExpression *new_literal_string_expr(Context *ctx,
   532 static MOJOSHADER_astExpression *new_literal_string_expr(Context *ctx,
   446                                                          const char *string)
   533                                                          const char *string)
   447 {
   534 {
   448     NEW_AST_NODE(retval, MOJOSHADER_astExpressionStringLiteral,
   535     NEW_AST_NODE(retval, MOJOSHADER_astExpressionStringLiteral,
   449                  MOJOSHADER_AST_OP_STRING_LITERAL);
   536                  MOJOSHADER_AST_OP_STRING_LITERAL);
       
   537     retval->datatype = &ctx->dt_string;
   450     retval->string = string;  // cached; don't copy string.
   538     retval->string = string;  // cached; don't copy string.
   451     return (MOJOSHADER_astExpression *) retval;
   539     return (MOJOSHADER_astExpression *) retval;
   452 } // new_literal_string_expr
   540 } // new_literal_string_expr
   453 
   541 
   454 static MOJOSHADER_astExpression *new_literal_boolean_expr(Context *ctx,
   542 static MOJOSHADER_astExpression *new_literal_boolean_expr(Context *ctx,
   455                                                           const int value)
   543                                                           const int value)
   456 {
   544 {
   457     NEW_AST_NODE(retval, MOJOSHADER_astExpressionBooleanLiteral,
   545     NEW_AST_NODE(retval, MOJOSHADER_astExpressionBooleanLiteral,
   458                  MOJOSHADER_AST_OP_BOOLEAN_LITERAL);
   546                  MOJOSHADER_AST_OP_BOOLEAN_LITERAL);
       
   547     retval->datatype = &ctx->dt_bool;
   459     retval->value = value;
   548     retval->value = value;
   460     return (MOJOSHADER_astExpression *) retval;
   549     return (MOJOSHADER_astExpression *) retval;
   461 } // new_literal_boolean_expr
   550 } // new_literal_boolean_expr
   462 
   551 
   463 static void delete_arguments(Context *ctx, MOJOSHADER_astArguments *args);
   552 static void delete_arguments(Context *ctx, MOJOSHADER_astArguments *args);
   521     Free(ctx, args);
   610     Free(ctx, args);
   522 } // delete_arguments
   611 } // delete_arguments
   523 
   612 
   524 static MOJOSHADER_astFunctionParameters *new_function_param(Context *ctx,
   613 static MOJOSHADER_astFunctionParameters *new_function_param(Context *ctx,
   525                         const MOJOSHADER_astInputModifier inputmod,
   614                         const MOJOSHADER_astInputModifier inputmod,
   526                         const char *datatype, const char *identifier,
   615                         const MOJOSHADER_astDataType *dt,
   527                         const char *semantic,
   616                         const char *identifier, const char *semantic,
   528                         const MOJOSHADER_astInterpolationModifier interpmod,
   617                         const MOJOSHADER_astInterpolationModifier interpmod,
   529                         MOJOSHADER_astExpression *initializer)
   618                         MOJOSHADER_astExpression *initializer)
   530 {
   619 {
   531     NEW_AST_NODE(retval, MOJOSHADER_astFunctionParameters,
   620     NEW_AST_NODE(retval, MOJOSHADER_astFunctionParameters,
   532                  MOJOSHADER_AST_FUNCTION_PARAMS);
   621                  MOJOSHADER_AST_FUNCTION_PARAMS);
       
   622     retval->datatype = dt;
   533     retval->input_modifier = inputmod;
   623     retval->input_modifier = inputmod;
   534     retval->datatype = datatype;
       
   535     retval->identifier = identifier;
   624     retval->identifier = identifier;
   536     retval->semantic = semantic;
   625     retval->semantic = semantic;
   537     retval->interpolation_modifier = interpmod;
   626     retval->interpolation_modifier = interpmod;
   538     retval->initializer = initializer;
   627     retval->initializer = initializer;
   539     retval->next = NULL;
   628     retval->next = NULL;
   548     delete_expr(ctx, params->initializer);
   637     delete_expr(ctx, params->initializer);
   549     Free(ctx, params);
   638     Free(ctx, params);
   550 } // delete_function_params
   639 } // delete_function_params
   551 
   640 
   552 static MOJOSHADER_astFunctionSignature *new_function_signature(Context *ctx,
   641 static MOJOSHADER_astFunctionSignature *new_function_signature(Context *ctx,
   553                                     const char *datatype,
   642                                     const MOJOSHADER_astDataType *dt,
   554                                     const char *identifier,
   643                                     const char *identifier,
   555                                     MOJOSHADER_astFunctionParameters *params)
   644                                     MOJOSHADER_astFunctionParameters *params)
   556 {
   645 {
   557     NEW_AST_NODE(retval, MOJOSHADER_astFunctionSignature,
   646     NEW_AST_NODE(retval, MOJOSHADER_astFunctionSignature,
   558                  MOJOSHADER_AST_FUNCTION_SIGNATURE);
   647                  MOJOSHADER_AST_FUNCTION_SIGNATURE);
   559     retval->datatype = datatype;
   648     retval->datatype = dt;
   560     retval->identifier = identifier;
   649     retval->identifier = identifier;
   561     retval->params = params;
   650     retval->params = params;
   562     retval->storage_class = MOJOSHADER_AST_FNSTORECLS_NONE;
   651     retval->storage_class = MOJOSHADER_AST_FNSTORECLS_NONE;
   563     retval->semantic = NULL;
   652     retval->semantic = NULL;
   564     return retval;
   653     return retval;
   612     delete_expr(ctx, s->dimension);
   701     delete_expr(ctx, s->dimension);
   613     Free(ctx, s);
   702     Free(ctx, s);
   614 } // delete_scalar_or_array
   703 } // delete_scalar_or_array
   615 
   704 
   616 static MOJOSHADER_astTypedef *new_typedef(Context *ctx, const int isconst,
   705 static MOJOSHADER_astTypedef *new_typedef(Context *ctx, const int isconst,
   617                                           const char *datatype,
   706                                           const MOJOSHADER_astDataType *dt,
   618                                           MOJOSHADER_astScalarOrArray *soa)
   707                                           MOJOSHADER_astScalarOrArray *soa)
   619 {
   708 {
   620     // we correct this datatype to the final string during semantic analysis.
   709     // we correct this datatype to the final version during semantic analysis.
   621     NEW_AST_NODE(retval, MOJOSHADER_astTypedef, MOJOSHADER_AST_TYPEDEF);
   710     NEW_AST_NODE(retval, MOJOSHADER_astTypedef, MOJOSHADER_AST_TYPEDEF);
       
   711     retval->datatype = dt;
   622     retval->isconst = isconst;
   712     retval->isconst = isconst;
   623     retval->datatype = datatype;
       
   624     retval->details = soa;
   713     retval->details = soa;
   625     return retval;
   714     return retval;
   626 } // new_typedef
   715 } // new_typedef
   627 
   716 
   628 static void delete_typedef(Context *ctx, MOJOSHADER_astTypedef *td)
   717 static void delete_typedef(Context *ctx, MOJOSHADER_astTypedef *td)
   665     delete_pack_offset(ctx, vll->packoffset);
   754     delete_pack_offset(ctx, vll->packoffset);
   666     Free(ctx, vll);
   755     Free(ctx, vll);
   667 } // delete_variable_lowlevel
   756 } // delete_variable_lowlevel
   668 
   757 
   669 static MOJOSHADER_astAnnotations *new_annotation(Context *ctx,
   758 static MOJOSHADER_astAnnotations *new_annotation(Context *ctx,
   670                                         const char *datatype,
   759                                         const MOJOSHADER_astDataType *dt,
   671                                         MOJOSHADER_astExpression *initializer)
   760                                         MOJOSHADER_astExpression *initializer)
   672 {
   761 {
   673     NEW_AST_NODE(retval, MOJOSHADER_astAnnotations, MOJOSHADER_AST_ANNOTATION);
   762     NEW_AST_NODE(retval, MOJOSHADER_astAnnotations, MOJOSHADER_AST_ANNOTATION);
   674     retval->datatype = datatype;
   763     retval->datatype = dt;
   675     retval->initializer = initializer;
   764     retval->initializer = initializer;
   676     retval->next = NULL;
   765     retval->next = NULL;
   677     return retval;
   766     return retval;
   678 } // new_annotation
   767 } // new_annotation
   679 
   768 
   693                             MOJOSHADER_astVariableLowLevel *vll)
   782                             MOJOSHADER_astVariableLowLevel *vll)
   694 {
   783 {
   695     NEW_AST_NODE(retval, MOJOSHADER_astVariableDeclaration,
   784     NEW_AST_NODE(retval, MOJOSHADER_astVariableDeclaration,
   696                  MOJOSHADER_AST_VARIABLE_DECLARATION);
   785                  MOJOSHADER_AST_VARIABLE_DECLARATION);
   697     retval->attributes = 0;
   786     retval->attributes = 0;
   698     retval->datatype = NULL;
       
   699     retval->anonymous_datatype = NULL;
   787     retval->anonymous_datatype = NULL;
   700     retval->details = soa;
   788     retval->details = soa;
   701     retval->semantic = semantic;
   789     retval->semantic = semantic;
   702     retval->annotations = annotations;
   790     retval->annotations = annotations;
   703     retval->initializer = init;
   791     retval->initializer = init;
   760                                             MOJOSHADER_astScalarOrArray *soa,
   848                                             MOJOSHADER_astScalarOrArray *soa,
   761                                             const char *semantic)
   849                                             const char *semantic)
   762 {
   850 {
   763     NEW_AST_NODE(retval, MOJOSHADER_astStructMembers,
   851     NEW_AST_NODE(retval, MOJOSHADER_astStructMembers,
   764                  MOJOSHADER_AST_STRUCT_MEMBER);
   852                  MOJOSHADER_AST_STRUCT_MEMBER);
   765     retval->datatype = NULL;
       
   766     retval->semantic = semantic;
   853     retval->semantic = semantic;
   767     retval->details = soa;
   854     retval->details = soa;
   768     retval->interpolation_mod = MOJOSHADER_AST_INTERPMOD_NONE;
   855     retval->interpolation_mod = MOJOSHADER_AST_INTERPMOD_NONE;
   769     retval->next = NULL;
   856     retval->next = NULL;
   770     return retval;
   857     return retval;
   783                                         const char *name,
   870                                         const char *name,
   784                                         MOJOSHADER_astStructMembers *members)
   871                                         MOJOSHADER_astStructMembers *members)
   785 {
   872 {
   786     NEW_AST_NODE(retval, MOJOSHADER_astStructDeclaration,
   873     NEW_AST_NODE(retval, MOJOSHADER_astStructDeclaration,
   787                  MOJOSHADER_AST_STRUCT_DECLARATION);
   874                  MOJOSHADER_AST_STRUCT_DECLARATION);
       
   875     retval->datatype = NULL;
   788     retval->name = name;
   876     retval->name = name;
   789     retval->members = members;
   877     retval->members = members;
   790     return retval;
   878     return retval;
   791 } // new_struct_declaration
   879 } // new_struct_declaration
   792 
   880 
  1224         default: assert(0 && "missing cleanup code"); break;
  1312         default: assert(0 && "missing cleanup code"); break;
  1225     } // switch
  1313     } // switch
  1226     // don't free (stmt) here, the class-specific functions do it.
  1314     // don't free (stmt) here, the class-specific functions do it.
  1227 } // delete_statement
  1315 } // delete_statement
  1228 
  1316 
  1229 static const char *get_usertype(const Context *ctx, const char *token)
  1317 
       
  1318 static const MOJOSHADER_astDataType *get_usertype(const Context *ctx,
       
  1319                                                   const char *token)
  1230 {
  1320 {
  1231     const void *value;  // search all scopes.
  1321     const void *value;  // search all scopes.
  1232     if (!hash_find(ctx->usertypes.hash, token, &value))
  1322     if (!hash_find(ctx->usertypes.hash, token, &value))
  1233         return NULL;
  1323         return NULL;
  1234     return (const char *) value;
  1324     return (MOJOSHADER_astDataType *) value;
  1235 } // get_usertype
  1325 } // get_usertype
  1236 
  1326 
  1237 
  1327 
  1238 // This is where the actual parsing happens. It's Lemon-generated!
  1328 // This is where the actual parsing happens. It's Lemon-generated!
  1239 #define __MOJOSHADER_HLSL_COMPILER__ 1
  1329 #define __MOJOSHADER_HLSL_COMPILER__ 1
  1240 #include "mojoshader_parser_hlsl.h"
  1330 #include "mojoshader_parser_hlsl.h"
  1241 
  1331 
  1242 
  1332 
  1243 /*
  1333 #if 0
  1244  * datatype strings...
  1334 static int expr_is_constant(MOJOSHADER_astExpression *expr)
  1245  *
  1335 {
  1246  * "v" == void
  1336     const MOJOSHADER_astNodeType op = expr->ast.type;
  1247  * "b" == bool
  1337     if (operator_is_unary(op))
  1248  * "i" == int
  1338         return expr_is_constant(expr->unary.operand);
  1249  * "u" == uint
  1339     else if (operator_is_binary(op))
  1250  * "h" == half
  1340     {
  1251  * "f" == float
  1341         return ( expr_is_constant(expr->binary.left) &&
  1252  * "ns" == snorm float
  1342                  expr_is_constant(expr->binary.right) );
  1253  * "nu" == unorm float
  1343     } // else if
  1254  * "B{*}" == buffer
  1344     else if (operator_is_ternary(op))
  1255  * "V{#,*}" == vector
  1345     {
  1256  * "M{#,#,*}" == matrix
  1346         return ( expr_is_constant(expr->ternary.left) &&
  1257  * "d" == double
  1347                  expr_is_constant(expr->ternary.center) &&
  1258  * "a{#,*}" == array
  1348                  expr_is_constant(expr->ternary.right) );
  1259  * "S" == string
  1349     } // else if
  1260  * "X{*}" == struct
  1350 
  1261  * "s1" == sampler1D
  1351     return ( (op == MOJOSHADER_AST_OP_INT_LITERAL) ||
  1262  * "s2" == sampler2D
  1352              (op == MOJOSHADER_AST_OP_FLOAT_LITERAL) ||
  1263  * "s3" == sampler3D
  1353              (op == MOJOSHADER_AST_OP_STRING_LITERAL) ||
  1264  * "sc" == samplerCUBE
  1354              (op == MOJOSHADER_AST_OP_BOOLEAN_LITERAL) );
  1265  * "ss" == sampler_state
  1355 } // expr_is_constant
  1266  * "sS" == SamplerComparisonState
  1356 #endif
  1267  * "U{*}" == user type.
  1357 
  1268  * "F{*,*}" == function
  1358 typedef struct AstCalcData
  1269  */
  1359 {
  1270 
  1360     int isflt;
  1271 
  1361     union
  1272 static void require_numeric_datatype(Context *ctx, const char *datatype)
  1362     {
  1273 {
  1363         double f;
  1274     if (datatype == ctx->str_f) return;  // float
  1364         int64 i;
  1275     if (datatype == ctx->str_i) return;  // int
  1365     } value;
  1276     if (datatype == ctx->str_b) return;  // bool
  1366 } AstCalcData;
  1277     if (datatype == ctx->str_u) return;  // uint
  1367 
  1278     if (datatype == ctx->str_h) return;  // half
  1368 // returns 0 if this expression is non-constant, 1 if it is.
  1279     if (datatype == ctx->str_d) return;  // double
  1369 //  calculation results land in (data).
       
  1370 static int calc_ast_const_expr(Context *ctx, void *_expr, AstCalcData *data)
       
  1371 {
       
  1372     const MOJOSHADER_astNode *expr = (MOJOSHADER_astNode *) _expr;
       
  1373     const MOJOSHADER_astNodeType op = expr->ast.type;
       
  1374 
       
  1375     ctx->sourcefile = expr->ast.filename;
       
  1376     ctx->sourceline = expr->ast.line;
       
  1377 
       
  1378     if (operator_is_unary(op))
       
  1379     {
       
  1380         if (!calc_ast_const_expr(ctx, expr->unary.operand, data))
       
  1381             return 0;
       
  1382 
       
  1383         if (data->isflt)
       
  1384         {
       
  1385             switch (op)
       
  1386             {
       
  1387                 case MOJOSHADER_AST_OP_NEGATE:
       
  1388                     data->value.f = -data->value.f;
       
  1389                     return 1;
       
  1390                 case MOJOSHADER_AST_OP_NOT:
       
  1391                     data->value.f = !data->value.f;
       
  1392                     return 1;
       
  1393                 case MOJOSHADER_AST_OP_COMPLEMENT:
       
  1394                     fail(ctx, "integer operation on floating point value");
       
  1395                     return 0;
       
  1396                 case MOJOSHADER_AST_OP_CAST:
       
  1397                     // !!! FIXME: this should work, but it's complicated.
       
  1398                     assert(0 && "write me");
       
  1399                     return 0;
       
  1400                 default: break;
       
  1401             } // switch
       
  1402         } // if
       
  1403 
       
  1404         else  // integer version
       
  1405         {
       
  1406             switch (op)
       
  1407             {
       
  1408                 case MOJOSHADER_AST_OP_NEGATE:
       
  1409                     data->value.i = -data->value.i;
       
  1410                     return 1;
       
  1411                 case MOJOSHADER_AST_OP_NOT:
       
  1412                     data->value.i = !data->value.i;
       
  1413                     return 1;
       
  1414                 case MOJOSHADER_AST_OP_COMPLEMENT:
       
  1415                     data->value.i = ~data->value.i;
       
  1416                     return 1;
       
  1417                 case MOJOSHADER_AST_OP_CAST:
       
  1418                     // !!! FIXME: this should work, but it's complicated.
       
  1419                     assert(0 && "write me");
       
  1420                     return 0;
       
  1421                 default: break;
       
  1422             } // switch
       
  1423         } // else
       
  1424         assert(0 && "unhandled operation?");
       
  1425         return 0;
       
  1426     } // if
       
  1427 
       
  1428     else if (operator_is_binary(op))
       
  1429     {
       
  1430         AstCalcData subdata2;
       
  1431         if ( (!calc_ast_const_expr(ctx, expr->binary.left, data)) ||
       
  1432              (!calc_ast_const_expr(ctx, expr->binary.right, &subdata2)) )
       
  1433             return 0;
       
  1434 
       
  1435         // upgrade to float if either operand is float.
       
  1436         if ((data->isflt) || (subdata2.isflt))
       
  1437         {
       
  1438             if (!data->isflt) data->value.f = (double) data->value.i;
       
  1439             if (!subdata2.isflt) subdata2.value.f = (double) subdata2.value.i;
       
  1440             data->isflt = subdata2.isflt = 1;
       
  1441         } // if
       
  1442 
       
  1443         switch (op)
       
  1444         {
       
  1445             // gcc doesn't handle commas here, either (fails to parse!).
       
  1446             case MOJOSHADER_AST_OP_COMMA:
       
  1447             case MOJOSHADER_AST_OP_ASSIGN:
       
  1448             case MOJOSHADER_AST_OP_MULASSIGN:
       
  1449             case MOJOSHADER_AST_OP_DIVASSIGN:
       
  1450             case MOJOSHADER_AST_OP_MODASSIGN:
       
  1451             case MOJOSHADER_AST_OP_ADDASSIGN:
       
  1452             case MOJOSHADER_AST_OP_SUBASSIGN:
       
  1453             case MOJOSHADER_AST_OP_LSHIFTASSIGN:
       
  1454             case MOJOSHADER_AST_OP_RSHIFTASSIGN:
       
  1455             case MOJOSHADER_AST_OP_ANDASSIGN:
       
  1456             case MOJOSHADER_AST_OP_XORASSIGN:
       
  1457             case MOJOSHADER_AST_OP_ORASSIGN:
       
  1458                 return 0;  // assignment is non-constant.
       
  1459             default: break;
       
  1460         } // switch
       
  1461 
       
  1462         if (data->isflt)
       
  1463         {
       
  1464             switch (op)
       
  1465             {
       
  1466                 case MOJOSHADER_AST_OP_MULTIPLY:
       
  1467                     data->value.f *= subdata2.value.f;
       
  1468                     return 1;
       
  1469                 case MOJOSHADER_AST_OP_DIVIDE:
       
  1470                     data->value.f /= subdata2.value.f;
       
  1471                     return 1;
       
  1472                 case MOJOSHADER_AST_OP_ADD:
       
  1473                     data->value.f += subdata2.value.f;
       
  1474                     return 1;
       
  1475                 case MOJOSHADER_AST_OP_SUBTRACT:
       
  1476                     data->value.f -= subdata2.value.f;
       
  1477                     return 1;
       
  1478                 case MOJOSHADER_AST_OP_LESSTHAN:
       
  1479                     data->isflt = 0;
       
  1480                     data->value.i = data->value.f < subdata2.value.f;
       
  1481                     return 1;
       
  1482                 case MOJOSHADER_AST_OP_GREATERTHAN:
       
  1483                     data->isflt = 0;
       
  1484                     data->value.i = data->value.f > subdata2.value.f;
       
  1485                     return 1;
       
  1486                 case MOJOSHADER_AST_OP_LESSTHANOREQUAL:
       
  1487                     data->isflt = 0;
       
  1488                     data->value.i = data->value.f <= subdata2.value.f;
       
  1489                     return 1;
       
  1490                 case MOJOSHADER_AST_OP_GREATERTHANOREQUAL:
       
  1491                     data->isflt = 0;
       
  1492                     data->value.i = data->value.f >= subdata2.value.f;
       
  1493                     return 1;
       
  1494                 case MOJOSHADER_AST_OP_EQUAL:
       
  1495                     data->isflt = 0;
       
  1496                     data->value.i = data->value.f == subdata2.value.f;
       
  1497                     return 1;
       
  1498                 case MOJOSHADER_AST_OP_NOTEQUAL:
       
  1499                     data->isflt = 0;
       
  1500                     data->value.i = data->value.f != subdata2.value.f;
       
  1501                     return 1;
       
  1502                 case MOJOSHADER_AST_OP_LOGICALAND:
       
  1503                     data->isflt = 0;
       
  1504                     data->value.i = data->value.f && subdata2.value.f;
       
  1505                     return 1;
       
  1506                 case MOJOSHADER_AST_OP_LOGICALOR:
       
  1507                     data->isflt = 0;
       
  1508                     data->value.i = data->value.f || subdata2.value.f;
       
  1509                     return 1;
       
  1510 
       
  1511                 case MOJOSHADER_AST_OP_LSHIFT:
       
  1512                 case MOJOSHADER_AST_OP_RSHIFT:
       
  1513                 case MOJOSHADER_AST_OP_MODULO:
       
  1514                 case MOJOSHADER_AST_OP_BINARYAND:
       
  1515                 case MOJOSHADER_AST_OP_BINARYXOR:
       
  1516                 case MOJOSHADER_AST_OP_BINARYOR:
       
  1517                     fail(ctx, "integer operation on floating point value");
       
  1518                     return 0;
       
  1519                 default: break;
       
  1520             } // switch
       
  1521         } // if
       
  1522 
       
  1523         else   // integer version.
       
  1524         {
       
  1525             switch (op)
       
  1526             {
       
  1527                 case MOJOSHADER_AST_OP_MULTIPLY:
       
  1528                     data->value.i *= subdata2.value.i;
       
  1529                     return 1;
       
  1530                 case MOJOSHADER_AST_OP_DIVIDE:
       
  1531                     data->value.i /= subdata2.value.i;
       
  1532                     return 1;
       
  1533                 case MOJOSHADER_AST_OP_ADD:
       
  1534                     data->value.i += subdata2.value.i;
       
  1535                     return 1;
       
  1536                 case MOJOSHADER_AST_OP_SUBTRACT:
       
  1537                     data->value.i -= subdata2.value.i;
       
  1538                     return 1;
       
  1539                 case MOJOSHADER_AST_OP_LESSTHAN:
       
  1540                     data->value.i = data->value.i < subdata2.value.i;
       
  1541                     return 1;
       
  1542                 case MOJOSHADER_AST_OP_GREATERTHAN:
       
  1543                     data->value.i = data->value.i > subdata2.value.i;
       
  1544                     return 1;
       
  1545                 case MOJOSHADER_AST_OP_LESSTHANOREQUAL:
       
  1546                     data->value.i = data->value.i <= subdata2.value.i;
       
  1547                     return 1;
       
  1548                 case MOJOSHADER_AST_OP_GREATERTHANOREQUAL:
       
  1549                     data->value.i = data->value.i >= subdata2.value.i;
       
  1550                     return 1;
       
  1551                 case MOJOSHADER_AST_OP_EQUAL:
       
  1552                     data->value.i = data->value.i == subdata2.value.i;
       
  1553                     return 1;
       
  1554                 case MOJOSHADER_AST_OP_NOTEQUAL:
       
  1555                     data->value.i = data->value.i != subdata2.value.i;
       
  1556                     return 1;
       
  1557                 case MOJOSHADER_AST_OP_LOGICALAND:
       
  1558                     data->value.i = data->value.i && subdata2.value.i;
       
  1559                     return 1;
       
  1560                 case MOJOSHADER_AST_OP_LOGICALOR:
       
  1561                     data->value.i = data->value.i || subdata2.value.i;
       
  1562                     return 1;
       
  1563                 case MOJOSHADER_AST_OP_LSHIFT:
       
  1564                     data->value.i = data->value.i << subdata2.value.i;
       
  1565                     return 1;
       
  1566                 case MOJOSHADER_AST_OP_RSHIFT:
       
  1567                     data->value.i = data->value.i >> subdata2.value.i;
       
  1568                     return 1;
       
  1569                 case MOJOSHADER_AST_OP_MODULO:
       
  1570                     data->value.i = data->value.i % subdata2.value.i;
       
  1571                     return 1;
       
  1572                 case MOJOSHADER_AST_OP_BINARYAND:
       
  1573                     data->value.i = data->value.i & subdata2.value.i;
       
  1574                     return 1;
       
  1575                 case MOJOSHADER_AST_OP_BINARYXOR:
       
  1576                     data->value.i = data->value.i ^ subdata2.value.i;
       
  1577                     return 1;
       
  1578                 case MOJOSHADER_AST_OP_BINARYOR:
       
  1579                     data->value.i = data->value.i | subdata2.value.i;
       
  1580                     return 1;
       
  1581                 default: break;
       
  1582             } // switch
       
  1583         } // else
       
  1584 
       
  1585         assert(0 && "unhandled operation?");
       
  1586         return 0;
       
  1587     } // else if
       
  1588 
       
  1589     else if (operator_is_ternary(op))
       
  1590     {
       
  1591         AstCalcData subdata2;
       
  1592         AstCalcData subdata3;
       
  1593 
       
  1594         assert(op == MOJOSHADER_AST_OP_CONDITIONAL);  // only one we have.
       
  1595 
       
  1596         if ( (!calc_ast_const_expr(ctx, expr->ternary.left, data)) ||
       
  1597              (!calc_ast_const_expr(ctx, expr->ternary.center, &subdata2)) ||
       
  1598              (!calc_ast_const_expr(ctx, expr->ternary.right, &subdata3)) )
       
  1599             return 0;
       
  1600 
       
  1601         // first operand should be bool (for the one ternary operator we have).
       
  1602         if (data->isflt)
       
  1603         {
       
  1604             data->isflt = 0;
       
  1605             data->value.i = (int64) subdata3.value.f;
       
  1606         } // if
       
  1607 
       
  1608         // upgrade to float if either operand is float.
       
  1609         if ((subdata2.isflt) || (subdata3.isflt))
       
  1610         {
       
  1611             if (!subdata2.isflt) subdata2.value.f = (double) subdata2.value.i;
       
  1612             if (!subdata3.isflt) subdata3.value.f = (double) subdata3.value.i;
       
  1613             subdata2.isflt = subdata3.isflt = 1;
       
  1614         } // if
       
  1615 
       
  1616         data->isflt = subdata2.isflt;
       
  1617         if (data->isflt)
       
  1618             data->value.f = data->value.i ? subdata2.value.f : subdata3.value.f;
       
  1619         else
       
  1620             data->value.i = data->value.i ? subdata2.value.i : subdata3.value.i;
       
  1621         return 1;
       
  1622     } // else if
       
  1623 
       
  1624     else  // not an operator? See if this is a literal value.
       
  1625     {
       
  1626         switch (op)
       
  1627         {
       
  1628             case MOJOSHADER_AST_OP_INT_LITERAL:
       
  1629                 data->isflt = 0;
       
  1630                 data->value.i = expr->intliteral.value;
       
  1631                 return 1;
       
  1632 
       
  1633             case MOJOSHADER_AST_OP_FLOAT_LITERAL:
       
  1634                 data->isflt = 1;
       
  1635                 data->value.f = expr->floatliteral.value;
       
  1636                 return 1;
       
  1637 
       
  1638             case MOJOSHADER_AST_OP_BOOLEAN_LITERAL:
       
  1639                 data->isflt = 0;
       
  1640                 data->value.i = expr->boolliteral.value ? 1 : 0;
       
  1641                 return 1;
       
  1642 
       
  1643             default: break;
       
  1644         } // switch
       
  1645     } // switch
       
  1646 
       
  1647     return 0;  // not constant, or unhandled.
       
  1648 } // calc_ast_const_expr
       
  1649 
       
  1650 
       
  1651 static inline const MOJOSHADER_astDataType *reduce_datatype(const MOJOSHADER_astDataType *dt)
       
  1652 {
       
  1653     const MOJOSHADER_astDataType *retval = dt;
       
  1654     while (retval && retval->type == MOJOSHADER_AST_DATATYPE_USER)
       
  1655         retval = retval->user.details;
       
  1656     return retval;
       
  1657 } // reduce_datatype
       
  1658 
       
  1659 
       
  1660 static const MOJOSHADER_astDataType *build_datatype(Context *ctx,
       
  1661                                             const int isconst,
       
  1662                                             const MOJOSHADER_astDataType *dt,
       
  1663                                             MOJOSHADER_astScalarOrArray *soa)
       
  1664 {
       
  1665     MOJOSHADER_astDataType *retval = NULL;
       
  1666 
       
  1667     assert( (soa->isarray && soa->dimension) ||
       
  1668             (!soa->isarray && !soa->dimension) );
       
  1669 
       
  1670     // see if we can just reuse the exist datatype.
       
  1671     if (!soa->isarray)
       
  1672     {
       
  1673         const int c1 = (dt->type & MOJOSHADER_AST_DATATYPE_CONST) != 0;
       
  1674         const int c2 = (isconst != 0);
       
  1675         if (c1 == c2)
       
  1676             return dt;  // reuse existing datatype!
       
  1677     } // if
       
  1678 
       
  1679     retval = (MOJOSHADER_astDataType *) Malloc(ctx, sizeof (*retval));
       
  1680     if (retval == NULL)
       
  1681         return NULL;
       
  1682 
       
  1683     // !!! FIXME: this is hacky.
       
  1684     if (!buffer_append(ctx->garbage, &retval, sizeof (retval)))
       
  1685     {
       
  1686         Free(ctx, retval);
       
  1687         return NULL;
       
  1688     } // if
       
  1689 
       
  1690     if (!soa->isarray)
       
  1691     {
       
  1692         assert(soa->dimension == NULL);
       
  1693         memcpy(retval, dt, sizeof (MOJOSHADER_astDataType));
       
  1694         if (isconst)
       
  1695             retval->type |= MOJOSHADER_AST_DATATYPE_CONST;
       
  1696         else
       
  1697             retval->type &= ~MOJOSHADER_AST_DATATYPE_CONST;
       
  1698         return retval;
       
  1699     } // if
       
  1700 
       
  1701     retval->type = MOJOSHADER_AST_DATATYPE_ARRAY;
       
  1702     retval->array.base = dt;
       
  1703     if (soa->dimension == NULL)
       
  1704     {
       
  1705         retval->array.elements = -1;
       
  1706         return retval;
       
  1707     } // if
       
  1708 
       
  1709     // Run the expression to verify it's constant and produces a positive int.
       
  1710     AstCalcData data;
       
  1711     data.isflt = 0;
       
  1712     data.value.i = 0;
       
  1713     retval->array.elements = 16;  // sane default for failure.
       
  1714     const int ok = calc_ast_const_expr(ctx, soa->dimension, &data);
       
  1715 
       
  1716     // reset error position.
       
  1717     ctx->sourcefile = soa->ast.filename;
       
  1718     ctx->sourceline = soa->ast.line;
       
  1719 
       
  1720     if (!ok)
       
  1721         fail(ctx, "array dimensions not constant");
       
  1722     else if (data.isflt)
       
  1723         fail(ctx, "array dimensions not integer");
       
  1724     else if (data.value.i < 0)
       
  1725         fail(ctx, "array dimensions negative");
       
  1726     else
       
  1727         retval->array.elements = data.value.i;
       
  1728 
       
  1729     return retval;
       
  1730 } // build_datatype
       
  1731 
       
  1732 
       
  1733 static void require_numeric_datatype(Context *ctx,
       
  1734                                      const MOJOSHADER_astDataType *datatype)
       
  1735 {
       
  1736     datatype = reduce_datatype(datatype);
       
  1737     switch (datatype->type)
       
  1738     {
       
  1739         case MOJOSHADER_AST_DATATYPE_BOOL:
       
  1740         case MOJOSHADER_AST_DATATYPE_INT:
       
  1741         case MOJOSHADER_AST_DATATYPE_UINT:
       
  1742         case MOJOSHADER_AST_DATATYPE_HALF:
       
  1743         case MOJOSHADER_AST_DATATYPE_FLOAT:
       
  1744         case MOJOSHADER_AST_DATATYPE_DOUBLE:
       
  1745             return;
       
  1746         default: break;
       
  1747     } // switch
       
  1748 
  1280     fail(ctx, "Expected numeric type");  // !!! FIXME: fmt.
  1749     fail(ctx, "Expected numeric type");  // !!! FIXME: fmt.
  1281     // !!! FIXME: replace AST node with an AST_OP_INT_LITERAL zero, keep going.
  1750     // !!! FIXME: replace AST node with an AST_OP_INT_LITERAL zero, keep going.
  1282 } // require_numeric_datatype
  1751 } // require_numeric_datatype
  1283 
  1752 
  1284 static void require_integer_datatype(Context *ctx, const char *datatype)
  1753 static void require_integer_datatype(Context *ctx,
  1285 {
  1754                                      const MOJOSHADER_astDataType *datatype)
  1286     if (datatype == ctx->str_i) return;  // int
  1755 {
  1287     if (datatype == ctx->str_u) return;  // uint
  1756     datatype = reduce_datatype(datatype);
       
  1757     switch (datatype->type)
       
  1758     {
       
  1759         case MOJOSHADER_AST_DATATYPE_INT:
       
  1760         case MOJOSHADER_AST_DATATYPE_UINT:
       
  1761             return;
       
  1762         default: break;
       
  1763     } // switch
       
  1764 
  1288     fail(ctx, "Expected integer type");  // !!! FIXME: fmt.
  1765     fail(ctx, "Expected integer type");  // !!! FIXME: fmt.
  1289     // !!! FIXME: replace AST node with an AST_OP_INT_LITERAL zero, keep going.
  1766     // !!! FIXME: replace AST node with an AST_OP_INT_LITERAL zero, keep going.
  1290 } // require_integer_datatype
  1767 } // require_integer_datatype
  1291 
  1768 
  1292 static void require_boolean_datatype(Context *ctx, const char *datatype)
  1769 static void require_boolean_datatype(Context *ctx,
  1293 {
  1770                                      const MOJOSHADER_astDataType *datatype)
  1294     if (datatype == ctx->str_b) return;  // bool
  1771 {
  1295     if (datatype == ctx->str_i) return;  // int
  1772     datatype = reduce_datatype(datatype);
  1296     if (datatype == ctx->str_u) return;  // uint
  1773     switch (datatype->type)
       
  1774     {
       
  1775         case MOJOSHADER_AST_DATATYPE_BOOL:
       
  1776         case MOJOSHADER_AST_DATATYPE_INT:
       
  1777         case MOJOSHADER_AST_DATATYPE_UINT:
       
  1778             return;
       
  1779         default: break;
       
  1780     } // switch
       
  1781 
  1297     fail(ctx, "Expected boolean type");  // !!! FIXME: fmt.
  1782     fail(ctx, "Expected boolean type");  // !!! FIXME: fmt.
  1298     // !!! FIXME: replace AST node with an AST_OP_BOOLEAN_LITERAL false, keep going.
  1783     // !!! FIXME: replace AST node with an AST_OP_BOOLEAN_LITERAL false, keep going.
  1299 } // require_numeric_datatype
  1784 } // require_numeric_datatype
  1300 
  1785 
  1301 
  1786 
  1302 static void require_array_datatype(Context *ctx, const char *datatype)
  1787 static void require_array_datatype(Context *ctx,
  1303 {
  1788                                    const MOJOSHADER_astDataType *datatype)
  1304     if (datatype[0] != 'a')
  1789 {
  1305         fail(ctx, "expected array");
  1790     datatype = reduce_datatype(datatype);
  1306         // !!! FIXME: delete array dereference for further processing.
  1791     if (datatype->type == MOJOSHADER_AST_DATATYPE_ARRAY)
       
  1792         return;
       
  1793 
       
  1794     fail(ctx, "expected array");
       
  1795     // !!! FIXME: delete array dereference for further processing.
  1307 } // require_array_datatype
  1796 } // require_array_datatype
  1308 
  1797 
  1309 
  1798 
  1310 static void require_struct_datatype(Context *ctx, const char *datatype)
  1799 static void require_struct_datatype(Context *ctx,
  1311 {
  1800                                     const MOJOSHADER_astDataType *datatype)
  1312     if (datatype[0] != 'X')
  1801 {
  1313         fail(ctx, "expected struct");
  1802     datatype = reduce_datatype(datatype);
  1314         // !!! FIXME: delete struct dereference for further processing.
  1803     if (datatype->type == MOJOSHADER_AST_DATATYPE_STRUCT)
  1315 } // require_array_datatype
  1804         return;
  1316 
  1805 
  1317 
  1806     fail(ctx, "expected struct");
  1318 static const char *require_function_datatype(Context *ctx, const char *datatype)
  1807     // !!! FIXME: delete struct dereference for further processing.
  1319 {
  1808 } // require_struct_datatype
  1320     if (datatype[0] != 'F')
  1809 
       
  1810 
       
  1811 static const MOJOSHADER_astDataType *require_function_datatype(Context *ctx,
       
  1812                                         const MOJOSHADER_astDataType *datatype)
       
  1813 {
       
  1814     datatype = reduce_datatype(datatype);
       
  1815     if (datatype->type != MOJOSHADER_AST_DATATYPE_FUNCTION)
  1321     {
  1816     {
  1322         fail(ctx, "expected function");
  1817         fail(ctx, "expected function");
  1323         // !!! FIXME: delete function call for further processing.
  1818         // !!! FIXME: delete function call for further processing.
  1324         return ctx->str_i;
  1819         return &ctx->dt_int;
  1325     } // if
  1820     } // if
  1326 
  1821 
  1327     assert(datatype[1] == '{');
  1822     return datatype->function.retval;
  1328     datatype += 2;
       
  1329     const char *ptr = strchr(datatype, ',');
       
  1330     assert(ptr != NULL);
       
  1331     return stringcache_len(ctx->strcache, datatype, (unsigned int) (ptr-datatype));
       
  1332 } // require_function_datatype
  1823 } // require_function_datatype
  1333 
  1824 
  1334 
  1825 
  1335 // Extract the individual element type from an array datatype.
  1826 // Extract the individual element type from an array datatype.
  1336 static const char *array_element_datatype(Context *ctx, const char *datatype)
  1827 static const MOJOSHADER_astDataType *array_element_datatype(Context *ctx,
  1337 {
  1828                                         const MOJOSHADER_astDataType *datatype)
  1338     const char *ptr;
  1829 {
  1339     const char *ptr2;
  1830     datatype = reduce_datatype(datatype);
  1340     unsigned int depth = 1;
  1831     assert(datatype->type == MOJOSHADER_AST_DATATYPE_ARRAY);
  1341     assert(datatype[0] == 'a');
  1832     return datatype->array.base;
  1342     assert(datatype[1] == '{');
       
  1343     ptr = strchr(datatype+2, ',');
       
  1344     assert(ptr != NULL);
       
  1345     ptr++;
       
  1346     for (ptr2 = ptr; depth > 0; ptr2++)
       
  1347     {
       
  1348         const char ch = *ptr2;
       
  1349         assert(ch != '\0');
       
  1350         if (ch == '{')
       
  1351             depth++;
       
  1352         else if (ch == '}')
       
  1353             depth--;
       
  1354     } // for
       
  1355 
       
  1356     return stringcache_len(ctx->strcache, ptr, (unsigned int) (ptr2 - ptr));
       
  1357 } // array_element_datatype
  1833 } // array_element_datatype
  1358 
  1834 
  1359 
  1835 
  1360 // This tests two datatypes to see if they are compatible, and adds cast
  1836 // This tests two datatypes to see if they are compatible, and adds cast
  1361 //  operator nodes to the AST if the program was relying on implicit
  1837 //  operator nodes to the AST if the program was relying on implicit
  1362 //  casts between then. Will fail() if the datatypes can't be coerced
  1838 //  casts between then. Will fail() if the datatypes can't be coerced
  1363 //  with a cast at all. (left) can be NULL to say that its datatype is
  1839 //  with a cast at all. (left) can be NULL to say that its datatype is
  1364 //  set in stone (an lvalue, for example). No other NULLs are allowed.
  1840 //  set in stone (an lvalue, for example). No other NULLs are allowed.
  1365 // Returns final datatype used once implicit casting is complete.
  1841 // Returns final datatype used once implicit casting is complete.
  1366 // The datatypes must be pointers from the string cache.
  1842 // The datatypes must be pointers from the string cache.
  1367 static const char *add_type_coercion(Context *ctx,
  1843 static const MOJOSHADER_astDataType *add_type_coercion(Context *ctx,
  1368                                      MOJOSHADER_astExpression **left,
  1844                                      MOJOSHADER_astExpression **left,
  1369                                      const char *ldatatype,
  1845                                      const MOJOSHADER_astDataType *_ldatatype,
  1370                                      MOJOSHADER_astExpression **right,
  1846                                      MOJOSHADER_astExpression **right,
  1371                                      const char *rdatatype)
  1847                                      const MOJOSHADER_astDataType *_rdatatype)
  1372 {
  1848 {
  1373     // !!! FIXME: this whole function is probably naive at best.
  1849     // !!! FIXME: this whole function is probably naive at best.
       
  1850     const MOJOSHADER_astDataType *ldatatype = reduce_datatype(_ldatatype);
       
  1851     const MOJOSHADER_astDataType *rdatatype = reduce_datatype(_rdatatype);
  1374 
  1852 
  1375     if (ldatatype == rdatatype)
  1853     if (ldatatype == rdatatype)
  1376         return ldatatype;   // they already match, so we're done.
  1854         return ldatatype;   // they already match, so we're done.
  1377 
  1855 
  1378     struct {
  1856     struct {
  1379         const char *datatype;
  1857         const MOJOSHADER_astDataTypeType type;
  1380         const int bits;
  1858         const int bits;
  1381         const int is_unsigned;
  1859         const int is_unsigned;
  1382         const int floating;
  1860         const int floating;
  1383     } typeinf[] = {
  1861     } typeinf[] = {
  1384         { ctx->str_b,  1, 1, 0 },
  1862         { MOJOSHADER_AST_DATATYPE_BOOL,    1, 1, 0 },
  1385         { ctx->str_h, 16, 0, 1 },
  1863         { MOJOSHADER_AST_DATATYPE_HALF,   16, 0, 1 },
  1386         { ctx->str_i, 32, 0, 0 },
  1864         { MOJOSHADER_AST_DATATYPE_INT,    32, 0, 0 },
  1387         { ctx->str_u, 32, 1, 0 },
  1865         { MOJOSHADER_AST_DATATYPE_UINT,   32, 1, 0 },
  1388         { ctx->str_f, 32, 0, 1 },
  1866         { MOJOSHADER_AST_DATATYPE_FLOAT,  32, 0, 1 },
  1389         { ctx->str_d, 64, 0, 1 },
  1867         { MOJOSHADER_AST_DATATYPE_DOUBLE, 64, 0, 1 },
  1390     };
  1868     };
  1391 
  1869 
  1392     int l, r;
  1870     int l = STATICARRAYLEN(typeinf);
  1393     for (l = 0; l < STATICARRAYLEN(typeinf); l++)
  1871     if (ldatatype != NULL)
  1394     {
  1872     {
  1395         if (typeinf[l].datatype == ldatatype)
  1873         for (l = 0; l < STATICARRAYLEN(typeinf); l++)
  1396             break;
  1874         {
  1397     } // for
  1875             if (typeinf[l].type == ldatatype->type)
  1398     for (r = 0; r < STATICARRAYLEN(typeinf); r++)
  1876                 break;
  1399     {
  1877         } // for
  1400         if (typeinf[r].datatype == rdatatype)
  1878     } // if
  1401             break;
  1879 
  1402     } // for
  1880     int r = STATICARRAYLEN(typeinf);
       
  1881     if (rdatatype != NULL)
       
  1882     {
       
  1883         for (r = 0; r < STATICARRAYLEN(typeinf); r++)
       
  1884         {
       
  1885             if (typeinf[r].type == rdatatype->type)
       
  1886                 break;
       
  1887         } // for
       
  1888     } // if
  1403 
  1889 
  1404     enum { CHOOSE_NEITHER, CHOOSE_LEFT, CHOOSE_RIGHT } choice = CHOOSE_NEITHER;
  1890     enum { CHOOSE_NEITHER, CHOOSE_LEFT, CHOOSE_RIGHT } choice = CHOOSE_NEITHER;
  1405     if ((l < STATICARRAYLEN(typeinf)) && (r < STATICARRAYLEN(typeinf)))
  1891     if ((l < STATICARRAYLEN(typeinf)) && (r < STATICARRAYLEN(typeinf)))
  1406     {
  1892     {
  1407         if (left == NULL)
  1893         if (left == NULL)
  1420             choice = CHOOSE_RIGHT;
  1906             choice = CHOOSE_RIGHT;
  1421     } // if
  1907     } // if
  1422 
  1908 
  1423     if (choice == CHOOSE_LEFT)
  1909     if (choice == CHOOSE_LEFT)
  1424     {
  1910     {
  1425         *right = new_cast_expr(ctx, ldatatype, *right);
  1911         *right = new_cast_expr(ctx, _ldatatype, *right);
  1426         return ldatatype;
  1912         return _ldatatype;
  1427     } // if
  1913     } // if
  1428     else if (choice == CHOOSE_RIGHT)
  1914     else if (choice == CHOOSE_RIGHT)
  1429     {
  1915     {
  1430         *left = new_cast_expr(ctx, rdatatype, *left);
  1916         *left = new_cast_expr(ctx, _rdatatype, *left);
  1431         return rdatatype;
  1917         return _rdatatype;
  1432     } // else if
  1918     } // else if
  1433 
  1919 
  1434     assert(choice == CHOOSE_NEITHER);
  1920     assert(choice == CHOOSE_NEITHER);
  1435     fail(ctx, "incompatible data types");
  1921     fail(ctx, "incompatible data types");
  1436     // Ditch original (*right), force a literal value that matches
  1922     // Ditch original (*right), force a literal value that matches
  1437     //  ldatatype, so further processing is normalized.
  1923     //  ldatatype, so further processing is normalized.
  1438     // !!! FIXME: force (right) to match (left).
  1924     // !!! FIXME: force (right) to match (left).
  1439     delete_expr(ctx, *right);
  1925     delete_expr(ctx, *right);
  1440     *right = new_cast_expr(ctx, ldatatype, new_literal_int_expr(ctx, 0));
  1926     *right = new_cast_expr(ctx, _ldatatype, new_literal_int_expr(ctx, 0));
  1441     return ldatatype;
  1927     return ldatatype;
  1442 } // add_type_coercion
  1928 } // add_type_coercion
       
  1929 
       
  1930 static int is_swizzle_str(const char *str)
       
  1931 {
       
  1932     int i;
       
  1933     int is_xyzw = 0;
       
  1934     int is_rgba = 0;
       
  1935 
       
  1936     assert(*str != '\0');  // can this actually happen?
       
  1937 
       
  1938     for (i = 0; i < 4; i++, str++)
       
  1939     {
       
  1940         const char ch = *str;
       
  1941         if (ch == '\0')
       
  1942             break;
       
  1943         else if ((ch == 'x') || (ch == 'y') || (ch == 'z') || (ch == 'w'))
       
  1944             is_xyzw = 1;
       
  1945         else if ((ch == 'r') || (ch == 'g') || (ch == 'b') || (ch == 'a'))
       
  1946             is_rgba = 1;
       
  1947     } // for
       
  1948 
       
  1949     if (*str != '\0')  // must be end of string here.
       
  1950         return 0;  // not a swizzle.
       
  1951     return ((is_rgba + is_xyzw) == 1);  // can only be one or the other.
       
  1952 } // is_swizzle_str
  1443 
  1953 
  1444 
  1954 
  1445 // Go through the AST and make sure all datatypes check out okay. For datatypes
  1955 // Go through the AST and make sure all datatypes check out okay. For datatypes
  1446 //  that are compatible but are relying on an implicit cast, we add explicit
  1956 //  that are compatible but are relying on an implicit cast, we add explicit
  1447 //  casts to the AST here, so further processing doesn't have to worry about
  1957 //  casts to the AST here, so further processing doesn't have to worry about
  1449 // For things that are incompatible, we generate errors and
  1959 // For things that are incompatible, we generate errors and
  1450 //  then replace them with reasonable defaults so further processing can
  1960 //  then replace them with reasonable defaults so further processing can
  1451 //  continue (but code generation will be skipped due to errors).
  1961 //  continue (but code generation will be skipped due to errors).
  1452 // This means further processing can assume the AST is sane and not have to
  1962 // This means further processing can assume the AST is sane and not have to
  1453 //  spend effort verifying it again.
  1963 //  spend effort verifying it again.
  1454 static const char *type_check_ast(Context *ctx, void *_ast)
  1964 // This stage will also set every AST node's datatype field, if it is
       
  1965 //  meaningful to do so. This will allow conversion to IR to know what
       
  1966 //  type/size a given node is.
       
  1967 static const MOJOSHADER_astDataType *type_check_ast(Context *ctx, void *_ast)
  1455 {
  1968 {
  1456     MOJOSHADER_astNode *ast = (MOJOSHADER_astNode *) _ast;
  1969     MOJOSHADER_astNode *ast = (MOJOSHADER_astNode *) _ast;
  1457     const char *datatype;
  1970     const MOJOSHADER_astDataType *datatype = NULL;
  1458     const char *datatype2;
  1971     const MOJOSHADER_astDataType *datatype2 = NULL;
  1459     const char *datatype3;
  1972     const MOJOSHADER_astDataType *datatype3 = NULL;
  1460 
  1973 
  1461     if (!ast)
  1974     if ((!ast) || (ctx->out_of_memory))
  1462         return NULL;
  1975         return NULL;
  1463 
  1976 
  1464     // upkeep so we report correct error locations...
  1977     // upkeep so we report correct error locations...
  1465     ctx->sourcefile = ast->ast.filename;
  1978     ctx->sourcefile = ast->ast.filename;
  1466     ctx->sourceline = ast->ast.line;
  1979     ctx->sourceline = ast->ast.line;
  1471         case MOJOSHADER_AST_OP_POSTDECREMENT:
  1984         case MOJOSHADER_AST_OP_POSTDECREMENT:
  1472         case MOJOSHADER_AST_OP_PREINCREMENT:
  1985         case MOJOSHADER_AST_OP_PREINCREMENT:
  1473         case MOJOSHADER_AST_OP_PREDECREMENT:
  1986         case MOJOSHADER_AST_OP_PREDECREMENT:
  1474         case MOJOSHADER_AST_OP_COMPLEMENT:
  1987         case MOJOSHADER_AST_OP_COMPLEMENT:
  1475         case MOJOSHADER_AST_OP_NEGATE:
  1988         case MOJOSHADER_AST_OP_NEGATE:
       
  1989         case MOJOSHADER_AST_OP_NOT:
  1476             datatype = type_check_ast(ctx, ast->unary.operand);
  1990             datatype = type_check_ast(ctx, ast->unary.operand);
  1477             require_numeric_datatype(ctx, datatype);
  1991             require_numeric_datatype(ctx, datatype);
  1478             return datatype;
  1992             ast->unary.datatype = datatype;
  1479 
       
  1480         case MOJOSHADER_AST_OP_NOT:
       
  1481             datatype = type_check_ast(ctx, ast->unary.operand);
       
  1482             require_boolean_datatype(ctx, datatype);
       
  1483             return datatype;
  1993             return datatype;
  1484 
  1994 
  1485         case MOJOSHADER_AST_OP_DEREF_ARRAY:
  1995         case MOJOSHADER_AST_OP_DEREF_ARRAY:
  1486             datatype = type_check_ast(ctx, ast->binary.left);
  1996             datatype = type_check_ast(ctx, ast->binary.left);
  1487             datatype2 = type_check_ast(ctx, ast->binary.right);
  1997             datatype2 = type_check_ast(ctx, ast->binary.right);
  1488             require_array_datatype(ctx, datatype);
  1998             require_array_datatype(ctx, datatype);
  1489             require_numeric_datatype(ctx, datatype2);
  1999             require_integer_datatype(ctx, datatype2);
  1490             add_type_coercion(ctx, NULL, ctx->str_i, &ast->binary.right, datatype2);
  2000             add_type_coercion(ctx, NULL, &ctx->dt_int, &ast->binary.right, datatype2);
  1491             return array_element_datatype(ctx, datatype);
  2001             ast->binary.datatype = array_element_datatype(ctx, datatype);
       
  2002             return ast->binary.datatype;
  1492 
  2003 
  1493         case MOJOSHADER_AST_OP_DEREF_STRUCT:
  2004         case MOJOSHADER_AST_OP_DEREF_STRUCT:
       
  2005         {
       
  2006             const char *member = ast->derefstruct.member;
  1494             datatype = type_check_ast(ctx, ast->derefstruct.identifier);
  2007             datatype = type_check_ast(ctx, ast->derefstruct.identifier);
  1495             require_struct_datatype(ctx, datatype);
  2008             const MOJOSHADER_astDataType *reduced = reduce_datatype(datatype);
  1496 // !!! FIXME: map member to datatype
  2009 
  1497 datatype = "!!! FIXME";
  2010             // Is this a swizzle and not a struct deref?
  1498             return datatype;
  2011             if (reduced->type == MOJOSHADER_AST_DATATYPE_VECTOR)
       
  2012             {
       
  2013                 ast->derefstruct.isswizzle = 1;
       
  2014                 if (!is_swizzle_str(member))
       
  2015                 {
       
  2016                     fail(ctx, "invalid swizzle on vector");
       
  2017                     // force this to be sane for further processing.
       
  2018                     const char *sane_swiz = stringcache(ctx->strcache, "xyzw");
       
  2019                     ast->derefstruct.member = sane_swiz;
       
  2020                 } // if
       
  2021                 ast->derefstruct.datatype = datatype;  // !!! FIXME: should float4(0,0,0,0).xy become a float2?
       
  2022                 return ast->derefstruct.datatype;
       
  2023             } // if
       
  2024 
       
  2025             // maybe this is an actual struct?
       
  2026             // !!! FIXME: replace with an int or something if not.
       
  2027             require_struct_datatype(ctx, reduced);
       
  2028 
       
  2029             // map member to datatype
       
  2030             assert(ast->derefstruct.datatype == NULL);
       
  2031             const MOJOSHADER_astDataTypeStructMember *mbrs = datatype->structure.members;
       
  2032             int i;
       
  2033             for (i = 0; i < reduced->structure.member_count; i++)
       
  2034             {
       
  2035                 if (strcmp(mbrs[i].identifier, member) == 0)
       
  2036                 {
       
  2037                     ast->derefstruct.datatype = mbrs[i].datatype;
       
  2038                     break;
       
  2039                 } // if
       
  2040             } // for
       
  2041 
       
  2042             if (ast->derefstruct.datatype == NULL)
       
  2043             {
       
  2044                 // !!! FIXME: replace with an int or something.
       
  2045                 failf(ctx, "Struct has no member named '%s'", member);
       
  2046             } // if
       
  2047 
       
  2048             return ast->derefstruct.datatype;
       
  2049         } // case
  1499 
  2050 
  1500         case MOJOSHADER_AST_OP_COMMA:
  2051         case MOJOSHADER_AST_OP_COMMA:
  1501             // evaluate and throw away left, return right.
  2052             // evaluate and throw away left, return right.
  1502             type_check_ast(ctx, ast->binary.left);
  2053             type_check_ast(ctx, ast->binary.left);
  1503             return type_check_ast(ctx, ast->binary.right);
  2054             ast->binary.datatype = type_check_ast(ctx, ast->binary.right);
       
  2055             return ast->binary.datatype;
  1504 
  2056 
  1505         case MOJOSHADER_AST_OP_MULTIPLY:
  2057         case MOJOSHADER_AST_OP_MULTIPLY:
  1506         case MOJOSHADER_AST_OP_DIVIDE:
  2058         case MOJOSHADER_AST_OP_DIVIDE:
  1507         case MOJOSHADER_AST_OP_ADD:
  2059         case MOJOSHADER_AST_OP_ADD:
  1508         case MOJOSHADER_AST_OP_SUBTRACT:
  2060         case MOJOSHADER_AST_OP_SUBTRACT:
  1509             datatype = type_check_ast(ctx, ast->binary.left);
  2061             datatype = type_check_ast(ctx, ast->binary.left);
  1510             datatype2 = type_check_ast(ctx, ast->binary.right);
  2062             datatype2 = type_check_ast(ctx, ast->binary.right);
  1511             require_numeric_datatype(ctx, datatype);
  2063             require_numeric_datatype(ctx, datatype);
  1512             require_numeric_datatype(ctx, datatype2);
  2064             require_numeric_datatype(ctx, datatype2);
  1513             return add_type_coercion(ctx, &ast->binary.left, datatype,
  2065             ast->binary.datatype = add_type_coercion(ctx, &ast->binary.left,
  1514                                      &ast->binary.right, datatype2);
  2066                                       datatype, &ast->binary.right, datatype2);
       
  2067             return ast->binary.datatype;
  1515 
  2068 
  1516         case MOJOSHADER_AST_OP_LSHIFT:
  2069         case MOJOSHADER_AST_OP_LSHIFT:
  1517         case MOJOSHADER_AST_OP_RSHIFT:
  2070         case MOJOSHADER_AST_OP_RSHIFT:
  1518         case MOJOSHADER_AST_OP_MODULO:
  2071         case MOJOSHADER_AST_OP_MODULO:
  1519             datatype = type_check_ast(ctx, ast->binary.left);
  2072             datatype = type_check_ast(ctx, ast->binary.left);
  1520             datatype2 = type_check_ast(ctx, ast->binary.right);
  2073             datatype2 = type_check_ast(ctx, ast->binary.right);
  1521             require_integer_datatype(ctx, datatype);
  2074             require_integer_datatype(ctx, datatype);
  1522             require_integer_datatype(ctx, datatype2);
  2075             require_integer_datatype(ctx, datatype2);
  1523             return add_type_coercion(ctx, &ast->binary.left, datatype,
  2076             ast->binary.datatype = add_type_coercion(ctx, &ast->binary.left,
  1524                                      &ast->binary.right, datatype2);
  2077                                      datatype,  &ast->binary.right, datatype2);
       
  2078             return ast->binary.datatype;
  1525 
  2079 
  1526         case MOJOSHADER_AST_OP_LESSTHAN:
  2080         case MOJOSHADER_AST_OP_LESSTHAN:
  1527         case MOJOSHADER_AST_OP_GREATERTHAN:
  2081         case MOJOSHADER_AST_OP_GREATERTHAN:
  1528         case MOJOSHADER_AST_OP_LESSTHANOREQUAL:
  2082         case MOJOSHADER_AST_OP_LESSTHANOREQUAL:
  1529         case MOJOSHADER_AST_OP_GREATERTHANOREQUAL:
  2083         case MOJOSHADER_AST_OP_GREATERTHANOREQUAL:
  1531         case MOJOSHADER_AST_OP_EQUAL:
  2085         case MOJOSHADER_AST_OP_EQUAL:
  1532             datatype = type_check_ast(ctx, ast->binary.left);
  2086             datatype = type_check_ast(ctx, ast->binary.left);
  1533             datatype2 = type_check_ast(ctx, ast->binary.right);
  2087             datatype2 = type_check_ast(ctx, ast->binary.right);
  1534             add_type_coercion(ctx, &ast->binary.left, datatype,
  2088             add_type_coercion(ctx, &ast->binary.left, datatype,
  1535                               &ast->binary.right, datatype2);
  2089                               &ast->binary.right, datatype2);
  1536             return ctx->str_b;
  2090             ast->binary.datatype = &ctx->dt_bool;
       
  2091             return ast->binary.datatype;
  1537 
  2092 
  1538         case MOJOSHADER_AST_OP_BINARYAND:
  2093         case MOJOSHADER_AST_OP_BINARYAND:
  1539         case MOJOSHADER_AST_OP_BINARYXOR:
  2094         case MOJOSHADER_AST_OP_BINARYXOR:
  1540         case MOJOSHADER_AST_OP_BINARYOR:
  2095         case MOJOSHADER_AST_OP_BINARYOR:
  1541             datatype = type_check_ast(ctx, ast->binary.left);
  2096             datatype = type_check_ast(ctx, ast->binary.left);
  1542             datatype2 = type_check_ast(ctx, ast->binary.right);
  2097             datatype2 = type_check_ast(ctx, ast->binary.right);
  1543             require_integer_datatype(ctx, datatype);
  2098             require_integer_datatype(ctx, datatype);
  1544             require_integer_datatype(ctx, datatype2);
  2099             require_integer_datatype(ctx, datatype2);
  1545             return add_type_coercion(ctx, &ast->binary.left, datatype,
  2100             ast->binary.datatype = add_type_coercion(ctx, &ast->binary.left,
  1546                                      &ast->binary.right, datatype2);
  2101                                       datatype, &ast->binary.right, datatype2);
       
  2102             return ast->binary.datatype;
  1547 
  2103 
  1548         case MOJOSHADER_AST_OP_LOGICALAND:
  2104         case MOJOSHADER_AST_OP_LOGICALAND:
  1549         case MOJOSHADER_AST_OP_LOGICALOR:
  2105         case MOJOSHADER_AST_OP_LOGICALOR:
  1550             datatype = type_check_ast(ctx, ast->binary.left);
  2106             datatype = type_check_ast(ctx, ast->binary.left);
  1551             datatype2 = type_check_ast(ctx, ast->binary.right);
  2107             datatype2 = type_check_ast(ctx, ast->binary.right);
  1552             require_boolean_datatype(ctx, datatype);
  2108             require_boolean_datatype(ctx, datatype);
  1553             require_boolean_datatype(ctx, datatype2);
  2109             require_boolean_datatype(ctx, datatype2);
  1554             add_type_coercion(ctx, &ast->binary.left, datatype,
  2110             add_type_coercion(ctx, &ast->binary.left, datatype,
  1555                               &ast->binary.right, datatype2);
  2111                               &ast->binary.right, datatype2);
  1556             return ctx->str_b;
  2112             ast->binary.datatype = &ctx->dt_bool;
  1557 
  2113 
  1558         case MOJOSHADER_AST_OP_ASSIGN:
  2114         case MOJOSHADER_AST_OP_ASSIGN:
  1559         case MOJOSHADER_AST_OP_MULASSIGN:
  2115         case MOJOSHADER_AST_OP_MULASSIGN:
  1560         case MOJOSHADER_AST_OP_DIVASSIGN:
  2116         case MOJOSHADER_AST_OP_DIVASSIGN:
  1561         case MOJOSHADER_AST_OP_MODASSIGN:
  2117         case MOJOSHADER_AST_OP_MODASSIGN:
  1566         case MOJOSHADER_AST_OP_ANDASSIGN:
  2122         case MOJOSHADER_AST_OP_ANDASSIGN:
  1567         case MOJOSHADER_AST_OP_XORASSIGN:
  2123         case MOJOSHADER_AST_OP_XORASSIGN:
  1568         case MOJOSHADER_AST_OP_ORASSIGN:
  2124         case MOJOSHADER_AST_OP_ORASSIGN:
  1569             datatype = type_check_ast(ctx, ast->binary.left);
  2125             datatype = type_check_ast(ctx, ast->binary.left);
  1570             datatype2 = type_check_ast(ctx, ast->binary.right);
  2126             datatype2 = type_check_ast(ctx, ast->binary.right);
  1571             add_type_coercion(ctx, NULL, datatype, &ast->binary.right, datatype2);
  2127             ast->binary.datatype = add_type_coercion(ctx, NULL, datatype,
  1572             return datatype;
  2128                                                 &ast->binary.right, datatype2);
       
  2129             return ast->binary.datatype;
  1573 
  2130 
  1574         case MOJOSHADER_AST_OP_CONDITIONAL:
  2131         case MOJOSHADER_AST_OP_CONDITIONAL:
  1575             type_check_ast(ctx, ast->ternary.left);
  2132             datatype = type_check_ast(ctx, ast->ternary.left);
  1576             type_check_ast(ctx, ast->ternary.center);
  2133             datatype2 = type_check_ast(ctx, ast->ternary.center);
  1577             type_check_ast(ctx, ast->ternary.right);
  2134             datatype3 = type_check_ast(ctx, ast->ternary.right);
  1578             require_boolean_datatype(ctx, datatype);
  2135             require_numeric_datatype(ctx, datatype);
  1579             return add_type_coercion(ctx, &ast->ternary.center, datatype2,
  2136             ast->ternary.datatype = add_type_coercion(ctx, &ast->ternary.center,
  1580                                      &ast->ternary.right, datatype3);
  2137                                     datatype2, &ast->ternary.right, datatype3);
       
  2138             return ast->ternary.datatype;
  1581 
  2139 
  1582         case MOJOSHADER_AST_OP_IDENTIFIER:
  2140         case MOJOSHADER_AST_OP_IDENTIFIER:
  1583             datatype = find_variable(ctx, ast->identifier.identifier);
  2141             datatype = find_variable(ctx, ast->identifier.identifier);
  1584             if (datatype == NULL)
  2142             if (datatype == NULL)
  1585             {
  2143             {
  1586                 fail(ctx, "Unknown identifier");
  2144                 fail(ctx, "Unknown identifier");
  1587                 // !!! FIXME: replace with a sane default, move on.
  2145                 // !!! FIXME: replace with a sane default, move on.
  1588                 datatype = ctx->str_i;
  2146                 datatype = &ctx->dt_int;
  1589             } // if
  2147             } // if
  1590             return datatype;
  2148             ast->identifier.datatype = datatype;
       
  2149             return ast->identifier.datatype;
  1591 
  2150 
  1592         case MOJOSHADER_AST_OP_INT_LITERAL:
  2151         case MOJOSHADER_AST_OP_INT_LITERAL:
  1593             return ctx->str_i;
       
  1594 
       
  1595         case MOJOSHADER_AST_OP_FLOAT_LITERAL:
  2152         case MOJOSHADER_AST_OP_FLOAT_LITERAL:
  1596             return ctx->str_f;
       
  1597 
       
  1598         case MOJOSHADER_AST_OP_STRING_LITERAL:
  2153         case MOJOSHADER_AST_OP_STRING_LITERAL:
  1599             return ctx->str_S;
       
  1600 
       
  1601         case MOJOSHADER_AST_OP_BOOLEAN_LITERAL:
  2154         case MOJOSHADER_AST_OP_BOOLEAN_LITERAL:
  1602             return ctx->str_b;
  2155             assert(ast->expression.datatype != NULL);
       
  2156             return ast->expression.datatype;  // already set up during parsing.
  1603 
  2157 
  1604         case MOJOSHADER_AST_ARGUMENTS:
  2158         case MOJOSHADER_AST_ARGUMENTS:
  1605             datatype = type_check_ast(ctx, ast->arguments.argument);
  2159             assert(0 && "Should be done by MOJOSHADER_AST_OP_CALLFUNC/CONSTRUCTOR");
  1606             if (ast->arguments.next != NULL)
  2160             return NULL;
       
  2161 
       
  2162         case MOJOSHADER_AST_OP_CALLFUNC:
       
  2163         {
       
  2164             datatype = type_check_ast(ctx, ast->callfunc.identifier);
       
  2165             const MOJOSHADER_astDataType *reduced = reduce_datatype(datatype);
       
  2166             require_function_datatype(ctx, reduced);
       
  2167             // !!! FIXME: replace with an int literal if this isn't a function.
       
  2168             MOJOSHADER_astArguments *arg = ast->callfunc.args;
       
  2169             MOJOSHADER_astArguments *prev = NULL;
       
  2170             int i;
       
  2171             for (i = 0; i < reduced->function.num_params; i++)
  1607             {
  2172             {
  1608                 datatype2 = type_check_ast(ctx, ast->arguments.next);
  2173                 if (arg == NULL)  // !!! FIXME: check for default parameters.
  1609                 datatype = stringcache_fmt(ctx->strcache, "%s%s",
  2174                 {
  1610                                            datatype, datatype2);
  2175                     fail(ctx, "Too few arguments");
       
  2176                     // !!! FIXME: replace AST here.
       
  2177                     break;
       
  2178                 } // if
       
  2179                 datatype2 = type_check_ast(ctx, arg->argument);
       
  2180                 add_type_coercion(ctx, NULL, &reduced->function.params[i],
       
  2181                                   &arg->argument, datatype2);
       
  2182                 prev = arg;
       
  2183                 arg = arg->next;
       
  2184             } // for
       
  2185 
       
  2186             if (arg != NULL)
       
  2187             {
       
  2188                 // Process extra arguments then chop them out.
       
  2189                 MOJOSHADER_astArguments *argi;
       
  2190                 for (argi = arg; argi != NULL; argi = argi->next)
       
  2191                     type_check_ast(ctx, argi->argument);
       
  2192                 if (prev != NULL)
       
  2193                     prev->next = NULL;
       
  2194                 delete_arguments(ctx, arg);
       
  2195                 fail(ctx, "Too many arguments");
  1611             } // if
  2196             } // if
  1612             return datatype;
  2197 
  1613 
  2198             ast->callfunc.datatype = reduced->function.retval;
  1614         case MOJOSHADER_AST_OP_CALLFUNC:
  2199             return ast->callfunc.datatype;
  1615             datatype = type_check_ast(ctx, ast->callfunc.identifier);
  2200         } // case
  1616             datatype2 = type_check_ast(ctx, ast->callfunc.args);
       
  1617             return require_function_datatype(ctx, datatype);
       
  1618 // !!! FIXME: test each arg against function datatype.
       
  1619             //return retval;  // this is the datatype of the func's return value.
       
  1620 
  2201 
  1621         case MOJOSHADER_AST_OP_CONSTRUCTOR:
  2202         case MOJOSHADER_AST_OP_CONSTRUCTOR:
  1622 // !!! FIXME: test each arg against constructor datatype.
  2203         {
  1623             type_check_ast(ctx, ast->constructor.args);
  2204             const MOJOSHADER_astDataType *reduced = reduce_datatype(ast->constructor.datatype);
       
  2205             const MOJOSHADER_astDataType *base_dt = reduced;
       
  2206             int num_params = 1;
       
  2207 
       
  2208             assert(reduced != NULL);
       
  2209             switch (reduced->type)
       
  2210             {
       
  2211                 case MOJOSHADER_AST_DATATYPE_VECTOR:
       
  2212                     num_params = reduced->vector.elements;
       
  2213                     base_dt = reduced->vector.base;
       
  2214                     break;
       
  2215                 case MOJOSHADER_AST_DATATYPE_MATRIX:
       
  2216                     num_params = reduced->matrix.rows * reduced->matrix.columns;
       
  2217                     base_dt = reduced->matrix.base;
       
  2218                     break;
       
  2219 
       
  2220                 case MOJOSHADER_AST_DATATYPE_BOOL:
       
  2221                 case MOJOSHADER_AST_DATATYPE_INT:
       
  2222                 case MOJOSHADER_AST_DATATYPE_UINT:
       
  2223                 case MOJOSHADER_AST_DATATYPE_FLOAT:
       
  2224                 case MOJOSHADER_AST_DATATYPE_FLOAT_SNORM:
       
  2225                 case MOJOSHADER_AST_DATATYPE_FLOAT_UNORM:
       
  2226                 case MOJOSHADER_AST_DATATYPE_HALF:
       
  2227                 case MOJOSHADER_AST_DATATYPE_DOUBLE:
       
  2228                 case MOJOSHADER_AST_DATATYPE_STRING:
       
  2229                     num_params = 1;
       
  2230                     break;
       
  2231 
       
  2232                 // !!! FIXME: can you construct a MOJOSHADER_AST_DATATYPE_STRUCT?
       
  2233                 // !!! FIXME: can you construct a MOJOSHADER_AST_DATATYPE_ARRAY?
       
  2234                 // !!! FIXME: can you construct a MOJOSHADER_AST_DATATYPE_BUFFER?
       
  2235 
       
  2236                 default:
       
  2237                     fail(ctx, "Invalid type for constructor");
       
  2238                     delete_arguments(ctx, ast->constructor.args);
       
  2239                     ast->constructor.args = new_argument(ctx, new_literal_int_expr(ctx, 0));
       
  2240                     ast->constructor.datatype = &ctx->dt_int;
       
  2241                     return ast->constructor.datatype;
       
  2242             } // switch
       
  2243 
       
  2244             assert(num_params > 0);
       
  2245 
       
  2246             MOJOSHADER_astArguments *arg = ast->constructor.args;
       
  2247             MOJOSHADER_astArguments *prev = NULL;
       
  2248             int i;
       
  2249             for (i = 0; i < num_params; i++)
       
  2250             {
       
  2251                 if (arg == NULL)  // !!! FIXME: check for default parameters.
       
  2252                 {
       
  2253                     fail(ctx, "Too few arguments");
       
  2254                     // !!! FIXME: replace AST here.
       
  2255                     break;
       
  2256                 } // if
       
  2257                 datatype2 = type_check_ast(ctx, arg->argument);
       
  2258                 add_type_coercion(ctx, NULL, base_dt, &arg->argument, datatype2);
       
  2259                 prev = arg;
       
  2260                 arg = arg->next;
       
  2261             } // for
       
  2262 
       
  2263             if (arg != NULL)
       
  2264             {
       
  2265                 fail(ctx, "Too many arguments");
       
  2266                 // Process extra arguments then chop them out.
       
  2267                 MOJOSHADER_astArguments *argi;
       
  2268                 for (argi = arg; argi != NULL; argi = argi->next)
       
  2269                     type_check_ast(ctx, argi->argument);
       
  2270                 if (prev != NULL)
       
  2271                     prev->next = NULL;
       
  2272                 delete_arguments(ctx, arg);
       
  2273             } // if
       
  2274 
  1624             return ast->constructor.datatype;
  2275             return ast->constructor.datatype;
       
  2276         } // case
  1625 
  2277 
  1626         case MOJOSHADER_AST_OP_CAST:
  2278         case MOJOSHADER_AST_OP_CAST:
  1627             datatype = ast->cast.datatype;
  2279             datatype = ast->cast.datatype;
  1628             datatype2 = type_check_ast(ctx, ast->cast.operand);
  2280             datatype2 = type_check_ast(ctx, ast->cast.operand);
  1629             // you still need type coercion, since you could do a wrong cast,
  2281             // you still need type coercion, since you could do a wrong cast,
  1723         case MOJOSHADER_AST_STATEMENT_RETURN:
  2375         case MOJOSHADER_AST_STATEMENT_RETURN:
  1724             type_check_ast(ctx, ast->returnstmt.expr);
  2376             type_check_ast(ctx, ast->returnstmt.expr);
  1725             type_check_ast(ctx, ast->returnstmt.next);
  2377             type_check_ast(ctx, ast->returnstmt.next);
  1726 
  2378 
  1727         case MOJOSHADER_AST_COMPUNIT_FUNCTION:
  2379         case MOJOSHADER_AST_COMPUNIT_FUNCTION:
       
  2380             // !!! FIXME: this is totally broken for function overloading.
       
  2381 //fsdfsdf
  1728             datatype = get_usertype(ctx, ast->funcunit.declaration->identifier);
  2382             datatype = get_usertype(ctx, ast->funcunit.declaration->identifier);
  1729             if (datatype == NULL)
  2383             if (datatype == NULL)
  1730             {
  2384             {
  1731                 // add function declaration if we've not seen it.
  2385                 // add function declaration if we've not seen it.
  1732                 datatype = ast->funcunit.declaration->datatype;
  2386                 datatype = ast->funcunit.declaration->datatype;
  1768             type_check_ast(ctx, ast->varunit.declaration);
  2422             type_check_ast(ctx, ast->varunit.declaration);
  1769             type_check_ast(ctx, ast->varunit.next);
  2423             type_check_ast(ctx, ast->varunit.next);
  1770             return NULL;
  2424             return NULL;
  1771 
  2425 
  1772         case MOJOSHADER_AST_SCALAR_OR_ARRAY:
  2426         case MOJOSHADER_AST_SCALAR_OR_ARRAY:
  1773             datatype = type_check_ast(ctx, ast->soa.dimension);
  2427             assert(0 && "Should be done by other AST nodes.");
  1774             require_integer_datatype(ctx, datatype);
       
  1775 assert(0); // !!! FIXME: figure out datatype of identifier.
       
  1776             return NULL;
  2428             return NULL;
  1777 
  2429 
  1778         case MOJOSHADER_AST_TYPEDEF:
  2430         case MOJOSHADER_AST_TYPEDEF:
  1779         {
  2431         {
  1780             MOJOSHADER_astScalarOrArray *soa = ast->typdef.details;
  2432             MOJOSHADER_astScalarOrArray *soa = ast->typdef.details;
  1781             datatype = get_usertype(ctx, soa->identifier);
  2433             datatype = get_usertype(ctx, soa->identifier);
  1782             if (datatype != NULL)
  2434             if (datatype != NULL)
  1783             {
  2435             {
  1784                 fail(ctx, "typedef already defined");
  2436                 fail(ctx, "typedef already defined");
       
  2437                 ast->typdef.datatype = datatype;
  1785                 return datatype;
  2438                 return datatype;
  1786             } // if
  2439             } // if
  1787 
  2440 
  1788             datatype = ast->typdef.datatype;
  2441             datatype = build_datatype(ctx, ast->typdef.isconst,
  1789 
  2442                                       ast->typdef.datatype, soa);
  1790             // don't walk into MOJOSHADER_AST_SCALAR_OR_ARRAY here, since it can't resolve the identifier.
  2443             if (datatype == NULL)
  1791             // !!! FIXME: SCALAR_OR_ARRAY is sort of a mess.
  2444                 return NULL;  // out of memory?
  1792             // !!! FIXME: this part is cut and paste.
  2445 
  1793             assert( (soa->isarray && soa->dimension) ||
  2446             push_usertype(ctx, soa->identifier, datatype);
  1794                     (!soa->isarray && !soa->dimension) );
  2447             ast->typdef.datatype = datatype;
  1795 
  2448             return ast->typdef.datatype;
  1796             if (soa->isarray)
  2449         } // case
       
  2450 
       
  2451         case MOJOSHADER_AST_FUNCTION_PARAMS:
       
  2452             assert(0 && "Should be done by MOJOSHADER_AST_FUNCTION_SIGNATURE");
       
  2453 
       
  2454         case MOJOSHADER_AST_FUNCTION_SIGNATURE:
       
  2455         {
       
  2456             MOJOSHADER_astFunctionParameters *param;
       
  2457             int count = 0;
       
  2458 
       
  2459             // !!! FIXME: pre-count this?
       
  2460             for (param = ast->funcsig.params; param; param = param->next)
       
  2461                 count++;
       
  2462 
       
  2463             // !!! FIXME: this is hacky.
       
  2464             MOJOSHADER_astDataType *dtparams;
       
  2465             void *ptr = Malloc(ctx, sizeof (*dtparams) * count);
       
  2466             if (ptr == NULL)
       
  2467                 return NULL;
       
  2468             if (!buffer_append(ctx->garbage, &ptr, sizeof (ptr)))
  1797             {
  2469             {
  1798                 if (soa->dimension->ast.type != MOJOSHADER_AST_OP_INT_LITERAL)
  2470                 Free(ctx, ptr);
  1799                 {
  2471                 return NULL;
  1800                     fail(ctx, "Expected integer");
       
  1801                     delete_expr(ctx, soa->dimension);  // make sane.
       
  1802                     soa->dimension = new_literal_int_expr(ctx, 1);
       
  1803                 } // if
       
  1804 
       
  1805                 const int dim = ((MOJOSHADER_astExpressionIntLiteral *) soa->dimension)->value;
       
  1806                 datatype = stringcache_fmt(ctx->strcache, "a{%d,%s}",
       
  1807                                            dim, datatype);
       
  1808             } // if
  2472             } // if
  1809 
  2473             dtparams = (MOJOSHADER_astDataType *) ptr;
  1810             ast->typdef.datatype = datatype;  // make sane.
  2474 
  1811             push_usertype(ctx, soa->identifier, datatype);
  2475             ptr = Malloc(ctx, sizeof (MOJOSHADER_astDataType));
  1812             return datatype;
  2476             if (ptr == NULL)
       
  2477                 return NULL;
       
  2478             if (!buffer_append(ctx->garbage, &ptr, sizeof (ptr)))
       
  2479             {
       
  2480                 Free(ctx, ptr);
       
  2481                 return NULL;
       
  2482             } // if
       
  2483             MOJOSHADER_astDataType *dt = (MOJOSHADER_astDataType *) ptr;
       
  2484 
       
  2485             int i = 0;
       
  2486             for (param = ast->funcsig.params; param; param = param->next)
       
  2487             {
       
  2488                 assert(i < count);
       
  2489                 push_variable(ctx, param->identifier, param->datatype);
       
  2490                 datatype2 = type_check_ast(ctx, param->initializer);
       
  2491                 add_type_coercion(ctx, NULL, param->datatype,
       
  2492                                   &param->initializer, datatype2);
       
  2493                 memcpy(&dtparams[i], param->datatype, sizeof (*param->datatype));
       
  2494                 i++;
       
  2495             } // for
       
  2496 
       
  2497             dt->type = MOJOSHADER_AST_DATATYPE_FUNCTION;
       
  2498             dt->function.retval = ast->funcsig.datatype;
       
  2499             dt->function.params = dtparams;
       
  2500             dt->function.num_params = count;
       
  2501 
       
  2502             ast->funcsig.datatype = dt;
       
  2503             return ast->funcsig.datatype;
  1813         } // case
  2504         } // case
  1814 
  2505 
  1815         case MOJOSHADER_AST_FUNCTION_PARAMS:
  2506         case MOJOSHADER_AST_STRUCT_DECLARATION:
  1816             push_variable(ctx, ast->params.identifier, ast->params.datatype);
  2507         {
  1817             type_check_ast(ctx, ast->params.initializer);
  2508             const MOJOSHADER_astStructMembers *mbrs;
  1818             type_check_ast(ctx, ast->params.next);
  2509 
       
  2510             // !!! FIXME: count this during parsing?
       
  2511             int count = 0;
       
  2512             mbrs = ast->structdecl.members;
       
  2513             while (mbrs != NULL)
       
  2514             {
       
  2515                 count++;
       
  2516                 mbrs = mbrs->next;
       
  2517             } // while
       
  2518 
       
  2519             // !!! FIXME: this is hacky.
       
  2520             MOJOSHADER_astDataTypeStructMember *dtmbrs;
       
  2521             void *ptr = Malloc(ctx, sizeof (*dtmbrs) * count);
       
  2522             if (ptr == NULL)
       
  2523                 return NULL;
       
  2524             if (!buffer_append(ctx->garbage, &ptr, sizeof (ptr)))
       
  2525             {
       
  2526                 Free(ctx, ptr);
       
  2527                 return NULL;
       
  2528             } // if
       
  2529             dtmbrs = (MOJOSHADER_astDataTypeStructMember *) ptr;
       
  2530 
       
  2531             ptr = Malloc(ctx, sizeof (MOJOSHADER_astDataType));
       
  2532             if (ptr == NULL)
       
  2533                 return NULL;
       
  2534             if (!buffer_append(ctx->garbage, &ptr, sizeof (ptr)))
       
  2535             {
       
  2536                 Free(ctx, ptr);
       
  2537                 return NULL;
       
  2538             } // if
       
  2539             MOJOSHADER_astDataType *dt = (MOJOSHADER_astDataType *) ptr;
       
  2540 
       
  2541             mbrs = ast->structdecl.members;
       
  2542             int i;
       
  2543             for (i = 0; i < count; i++)
       
  2544             {
       
  2545                 // !!! FIXME: current grammar forbids const keyword on struct members!
       
  2546                 dtmbrs[i].datatype = build_datatype(ctx, 0, mbrs->datatype, mbrs->details);
       
  2547                 dtmbrs[i].identifier = mbrs->details->identifier;  // cached!
       
  2548                 mbrs = mbrs->next;
       
  2549             } // for
       
  2550 
       
  2551             dt->structure.type = MOJOSHADER_AST_DATATYPE_STRUCT;
       
  2552             dt->structure.members = dtmbrs;
       
  2553             dt->structure.member_count = count;
       
  2554             ast->structdecl.datatype = dt;
       
  2555 
       
  2556             push_usertype(ctx, ast->structdecl.name, ast->structdecl.datatype);
       
  2557             return ast->structdecl.datatype;
       
  2558         } // case
       
  2559 
       
  2560         case MOJOSHADER_AST_STRUCT_MEMBER:
       
  2561             assert(0 && "Should be done by MOJOSHADER_AST_STRUCT_DECLARATION.");
  1819             return NULL;
  2562             return NULL;
  1820 
       
  1821         case MOJOSHADER_AST_FUNCTION_SIGNATURE:
       
  1822             type_check_ast(ctx, ast->funcsig.params);
       
  1823             return ast->funcsig.datatype;
       
  1824 
       
  1825         case MOJOSHADER_AST_STRUCT_DECLARATION:
       
  1826             datatype = type_check_ast(ctx, ast->structdecl.members);
       
  1827             datatype = stringcache_fmt(ctx->strcache, "X{%s}", datatype);
       
  1828             push_usertype(ctx, ast->structdecl.name, datatype);
       
  1829             return stringcache_fmt(ctx->strcache, "U{%s}", ast->structdecl.name);
       
  1830 
       
  1831         case MOJOSHADER_AST_STRUCT_MEMBER:
       
  1832             datatype = type_check_ast(ctx, ast->structmembers.details);
       
  1833             datatype2 = type_check_ast(ctx, ast->structmembers.next);
       
  1834             if (datatype2)
       
  1835             {
       
  1836                 return stringcache_fmt(ctx->strcache, "%s%s",
       
  1837                                        datatype, datatype2);
       
  1838             } // if
       
  1839             return datatype;
       
  1840 
  2563 
  1841         case MOJOSHADER_AST_VARIABLE_DECLARATION:
  2564         case MOJOSHADER_AST_VARIABLE_DECLARATION:
  1842             // this is true now, but we'll fill in ->datatype no matter what.
  2565             // this is true now, but we'll fill in ->datatype no matter what.
  1843             assert((ast->vardecl.datatype && !ast->vardecl.anonymous_datatype) ||
  2566             assert((ast->vardecl.datatype && !ast->vardecl.anonymous_datatype) ||
  1844                    (!ast->vardecl.datatype && ast->vardecl.anonymous_datatype));
  2567                    (!ast->vardecl.datatype && ast->vardecl.anonymous_datatype));
  1845 
  2568 
  1846             // fix up if necessary.
  2569             // An anonymous struct? That AST node does the heavy lifting.
  1847             if (ast->vardecl.anonymous_datatype != NULL)
  2570             if (ast->vardecl.anonymous_datatype != NULL)
  1848                 ast->vardecl.datatype = type_check_ast(ctx, ast->vardecl.anonymous_datatype);
  2571                 datatype = type_check_ast(ctx, ast->vardecl.anonymous_datatype);
  1849             datatype = ast->vardecl.datatype;
  2572             else
  1850 
       
  1851             // don't walk into MOJOSHADER_AST_SCALAR_OR_ARRAY here, since it can't resolve the identifier.
       
  1852             // !!! FIXME: SCALAR_OR_ARRAY is sort of a mess.
       
  1853             // !!! FIXME: this part is cut and paste.
       
  1854             assert( (ast->vardecl.details->isarray &&
       
  1855                      ast->vardecl.details->dimension) ||
       
  1856                      (!ast->vardecl.details->isarray &&
       
  1857                       !ast->vardecl.details->dimension) );
       
  1858 
       
  1859             if (ast->vardecl.details->isarray)
       
  1860             {
  2573             {
  1861                 MOJOSHADER_astScalarOrArray *soa = ast->vardecl.details;
  2574                 datatype = build_datatype(ctx, (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_CONST) != 0,
  1862                 if (soa->dimension->ast.type != MOJOSHADER_AST_OP_INT_LITERAL)
  2575                                           ast->vardecl.datatype, ast->vardecl.details);
  1863                 {
  2576             } // else
  1864                     fail(ctx, "Expected integer");
  2577 
  1865                     delete_expr(ctx, soa->dimension);  // make sane.
  2578             ast->vardecl.datatype = datatype;
  1866                     soa->dimension = new_literal_int_expr(ctx, 1);
  2579 
  1867                 } // if
  2580             push_variable(ctx, ast->vardecl.details->identifier, datatype);
  1868 
  2581             if (ast->vardecl.initializer != NULL)
  1869                 const int dim = ((MOJOSHADER_astExpressionIntLiteral *) soa->dimension)->value;
  2582             {
  1870                 datatype = stringcache_fmt(ctx->strcache, "a{%d,%s}",
  2583                 datatype2 = type_check_ast(ctx, ast->vardecl.initializer);
  1871                                            dim, datatype);
  2584                 add_type_coercion(ctx, NULL, datatype, &ast->vardecl.initializer, datatype2);
  1872             } // if
  2585             } // if
  1873 
       
  1874             ast->vardecl.datatype = datatype;  // make sane.
       
  1875             push_variable(ctx, ast->vardecl.details->identifier, datatype);
       
  1876             datatype2 = type_check_ast(ctx, ast->vardecl.initializer);
       
  1877             add_type_coercion(ctx, NULL, datatype, &ast->vardecl.initializer, datatype2);
       
  1878 
  2586 
  1879             type_check_ast(ctx, ast->vardecl.annotations);
  2587             type_check_ast(ctx, ast->vardecl.annotations);
  1880             type_check_ast(ctx, ast->vardecl.lowlevel);
  2588             type_check_ast(ctx, ast->vardecl.lowlevel);
  1881 
  2589 
  1882             datatype2 = type_check_ast(ctx, ast->vardecl.next);
  2590             datatype2 = type_check_ast(ctx, ast->vardecl.next);
  1883             assert(datatype == datatype2);
  2591             return ast->vardecl.datatype;
  1884             return datatype;
       
  1885 
  2592 
  1886         case MOJOSHADER_AST_ANNOTATION:
  2593         case MOJOSHADER_AST_ANNOTATION:
  1887         {
  2594         {
  1888             MOJOSHADER_astAnnotations *anno = &ast->annotations;
  2595             MOJOSHADER_astAnnotations *anno = &ast->annotations;
  1889             while (anno)
  2596             while (anno)
  1902             assert(0 && "unexpected type");
  2609             assert(0 && "unexpected type");
  1903     } // switch
  2610     } // switch
  1904 
  2611 
  1905     return NULL;
  2612     return NULL;
  1906 } // type_check_ast
  2613 } // type_check_ast
  1907 
       
  1908 
  2614 
  1909 
  2615 
  1910 static inline void semantic_analysis(Context *ctx)
  2616 static inline void semantic_analysis(Context *ctx)
  1911 {
  2617 {
  1912     type_check_ast(ctx, ctx->ast);
  2618     type_check_ast(ctx, ctx->ast);
  2152     if (ctx != NULL)
  2858     if (ctx != NULL)
  2153     {
  2859     {
  2154         MOJOSHADER_free f = ((ctx->free != NULL) ? ctx->free : MOJOSHADER_internal_free);
  2860         MOJOSHADER_free f = ((ctx->free != NULL) ? ctx->free : MOJOSHADER_internal_free);
  2155         void *d = ctx->malloc_data;
  2861         void *d = ctx->malloc_data;
  2156 
  2862 
       
  2863         // !!! FIXME: this is kinda hacky.
       
  2864         const size_t count = buffer_size(ctx->garbage) / sizeof (void *);
       
  2865         if (count > 0)
       
  2866         {
       
  2867             void **garbage = (void **) buffer_flatten(ctx->garbage);
       
  2868             if (garbage != NULL)
       
  2869             {
       
  2870                 size_t i;
       
  2871                 for (i = 0; i < count; i++)
       
  2872                     f(garbage[i], d);
       
  2873                 f(garbage, d);
       
  2874             } // if
       
  2875         } // if
       
  2876         buffer_destroy(ctx->garbage);
       
  2877 
  2157         delete_compilation_unit(ctx, (MOJOSHADER_astCompilationUnit*)ctx->ast);
  2878         delete_compilation_unit(ctx, (MOJOSHADER_astCompilationUnit*)ctx->ast);
  2158         destroy_symbolmap(ctx, &ctx->usertypes);
  2879         destroy_symbolmap(ctx, &ctx->usertypes);
  2159         destroy_symbolmap(ctx, &ctx->variables);
  2880         destroy_symbolmap(ctx, &ctx->variables);
  2160         stringcache_destroy(ctx->strcache);
  2881         stringcache_destroy(ctx->strcache);
  2161         errorlist_destroy(ctx->errors);
  2882         errorlist_destroy(ctx->errors);
  2185     create_symbolmap(ctx, &ctx->variables); // !!! FIXME: check for failure.
  2906     create_symbolmap(ctx, &ctx->variables); // !!! FIXME: check for failure.
  2186     ctx->strcache = stringcache_create(MallocBridge, FreeBridge, ctx);  // !!! FIXME: check for failure.
  2907     ctx->strcache = stringcache_create(MallocBridge, FreeBridge, ctx);  // !!! FIXME: check for failure.
  2187     ctx->errors = errorlist_create(MallocBridge, FreeBridge, ctx);  // !!! FIXME: check for failure.
  2908     ctx->errors = errorlist_create(MallocBridge, FreeBridge, ctx);  // !!! FIXME: check for failure.
  2188     ctx->warnings = errorlist_create(MallocBridge, FreeBridge, ctx);  // !!! FIXME: check for failure.
  2909     ctx->warnings = errorlist_create(MallocBridge, FreeBridge, ctx);  // !!! FIXME: check for failure.
  2189 
  2910 
  2190     // fill in some common strings we'll want to use without further hashing.
  2911     // !!! FIXME: this feels hacky.
  2191     ctx->str_b = stringcache(ctx->strcache, "b");
  2912     ctx->garbage = buffer_create(256*sizeof(void*),MallocBridge,FreeBridge,ctx);  // !!! FIXME: check for failure.
  2192     ctx->str_f = stringcache(ctx->strcache, "f");
  2913 
  2193     ctx->str_i = stringcache(ctx->strcache, "i");
  2914     ctx->dt_bool.type = MOJOSHADER_AST_DATATYPE_BOOL;
  2194     ctx->str_u = stringcache(ctx->strcache, "u");
  2915     ctx->dt_int.type = MOJOSHADER_AST_DATATYPE_INT;
  2195     ctx->str_h = stringcache(ctx->strcache, "h");
  2916     ctx->dt_uint.type = MOJOSHADER_AST_DATATYPE_UINT;
  2196     ctx->str_d = stringcache(ctx->strcache, "d");
  2917     ctx->dt_float.type = MOJOSHADER_AST_DATATYPE_FLOAT;
  2197     ctx->str_s = stringcache(ctx->strcache, "s");
  2918     ctx->dt_float_snorm.type = MOJOSHADER_AST_DATATYPE_FLOAT_SNORM;
  2198     ctx->str_S = stringcache(ctx->strcache, "S");
  2919     ctx->dt_float_unorm.type = MOJOSHADER_AST_DATATYPE_FLOAT_UNORM;
  2199     ctx->str_s1 = stringcache(ctx->strcache, "s1");
  2920     ctx->dt_half.type = MOJOSHADER_AST_DATATYPE_HALF;
  2200     ctx->str_s2 = stringcache(ctx->strcache, "s2");
  2921     ctx->dt_double.type = MOJOSHADER_AST_DATATYPE_DOUBLE;
  2201     ctx->str_s3 = stringcache(ctx->strcache, "s3");
  2922     ctx->dt_string.type = MOJOSHADER_AST_DATATYPE_STRING;
  2202     ctx->str_sc = stringcache(ctx->strcache, "sc");
  2923     ctx->dt_sampler1d.type = MOJOSHADER_AST_DATATYPE_SAMPLER_1D;
  2203     ctx->str_ss = stringcache(ctx->strcache, "ss");
  2924     ctx->dt_sampler2d.type = MOJOSHADER_AST_DATATYPE_SAMPLER_2D;
  2204     ctx->str_sS = stringcache(ctx->strcache, "sS");
  2925     ctx->dt_sampler3d.type = MOJOSHADER_AST_DATATYPE_SAMPLER_3D;
  2205     ctx->str_Fs = stringcache(ctx->strcache, "Fs");
  2926     ctx->dt_samplercube.type = MOJOSHADER_AST_DATATYPE_SAMPLER_CUBE;
  2206     ctx->str_Fu = stringcache(ctx->strcache, "Fu");
  2927     ctx->dt_samplerstate.type = MOJOSHADER_AST_DATATYPE_SAMPLER_STATE;
  2207     ctx->str_ns = stringcache(ctx->strcache, "ns");
  2928     ctx->dt_samplercompstate.type = MOJOSHADER_AST_DATATYPE_SAMPLER_COMPARISON_STATE;
  2208     ctx->str_nu = stringcache(ctx->strcache, "nu");
  2929 
       
  2930     #define INIT_DT_BUFFER(t) \
       
  2931         ctx->dt_buf_##t.type = MOJOSHADER_AST_DATATYPE_BUFFER; \
       
  2932         ctx->dt_buf_##t.buffer.base = &ctx->dt_##t;
       
  2933     INIT_DT_BUFFER(bool);
       
  2934     INIT_DT_BUFFER(int);
       
  2935     INIT_DT_BUFFER(uint);
       
  2936     INIT_DT_BUFFER(half);
       
  2937     INIT_DT_BUFFER(float);
       
  2938     INIT_DT_BUFFER(double);
       
  2939     INIT_DT_BUFFER(float_snorm);
       
  2940     INIT_DT_BUFFER(float_unorm);
       
  2941     #undef INIT_DT_BUFFER
  2209 
  2942 
  2210     return ctx;
  2943     return ctx;
  2211 } // build_context
  2944 } // build_context
  2212 
  2945 
  2213 
  2946 
  2214 // parse the source code into an AST.
  2947 // parse the source code into an AST.
  2215 static void parse_source(Context *ctx, const char *filename,
  2948 static void parse_source(Context *ctx, const char *filename,
  2216                         const char *source, unsigned int sourcelen,
  2949                          const char *source, unsigned int sourcelen,
  2217                         const MOJOSHADER_preprocessorDefine *defines,
  2950                          const MOJOSHADER_preprocessorDefine *defines,
  2218                         unsigned int define_count,
  2951                          unsigned int define_count,
  2219                         MOJOSHADER_includeOpen include_open,
  2952                          MOJOSHADER_includeOpen include_open,
  2220                         MOJOSHADER_includeClose include_close)
  2953                          MOJOSHADER_includeClose include_close)
  2221 {
  2954 {
  2222     TokenData data;
  2955     TokenData data;
  2223     unsigned int tokenlen;
  2956     unsigned int tokenlen;
  2224     Token tokenval;
  2957     Token tokenval;
  2225     const char *token;
  2958     const char *token;
  2232     if (!include_close) include_close = MOJOSHADER_internal_include_close;
  2965     if (!include_close) include_close = MOJOSHADER_internal_include_close;
  2233 
  2966 
  2234     pp = preprocessor_start(filename, source, sourcelen, include_open,
  2967     pp = preprocessor_start(filename, source, sourcelen, include_open,
  2235                             include_close, defines, define_count, 0,
  2968                             include_close, defines, define_count, 0,
  2236                             MallocBridge, FreeBridge, ctx);
  2969                             MallocBridge, FreeBridge, ctx);
  2237 
  2970     if (pp == NULL)
  2238     // !!! FIXME: check if (pp == NULL)...
  2971     {
       
  2972         assert(ctx->out_of_memory);  // shouldn't fail for any other reason.
       
  2973         return;
       
  2974     } // if
  2239 
  2975 
  2240     parser = ParseHLSLAlloc(ctx->malloc, ctx->malloc_data);
  2976     parser = ParseHLSLAlloc(ctx->malloc, ctx->malloc_data);
       
  2977     if (parser == NULL)
       
  2978     {
       
  2979         assert(ctx->out_of_memory);  // shouldn't fail for any other reason.
       
  2980         preprocessor_end(pp);
       
  2981         return;
       
  2982     } // if
  2241 
  2983 
  2242     // !!! FIXME: check if (parser == NULL)...
  2984     // !!! FIXME: check if (parser == NULL)...
  2243 
  2985 
  2244     #if DEBUG_COMPILER_PARSER
  2986     #if DEBUG_COMPILER_PARSER
  2245     ParseHLSLTrace(stdout, "COMPILER: ");
  2987     ParseHLSLTrace(stdout, "COMPILER: ");
  2246     #endif
  2988     #endif
  2247 
  2989 
       
  2990     // !!! FIXME: move this to a subroutine.
  2248     // add in standard typedefs...
  2991     // add in standard typedefs...
  2249     static char *types[] = { "bool", "int", "uint", "half", "float", "double" };
  2992     const struct
  2250     int i;
  2993     {
       
  2994         const char *str;
       
  2995         const MOJOSHADER_astDataType *datatype;
       
  2996     } types[] = {
       
  2997         { "bool", &ctx->dt_bool },
       
  2998         { "int", &ctx->dt_int },
       
  2999         { "uint", &ctx->dt_uint },
       
  3000         { "half", &ctx->dt_half },
       
  3001         { "float", &ctx->dt_float },
       
  3002         { "double", &ctx->dt_double },
       
  3003     };
       
  3004 
       
  3005     int i, j, k;
  2251     for (i = 0; i < STATICARRAYLEN(types); i++)
  3006     for (i = 0; i < STATICARRAYLEN(types); i++)
  2252     {
  3007     {
  2253         char buf[32];
  3008         char buf[32];
  2254         int j;
  3009         int len;
       
  3010         const MOJOSHADER_astDataType *dt;
       
  3011 
  2255         for (j = 1; j <= 4; j++)
  3012         for (j = 1; j <= 4; j++)
  2256         {
  3013         {
  2257             // "float2"
  3014             // "float2"
  2258             int len = snprintf(buf, sizeof (buf), "%s%d", types[i], j);
  3015             dt = new_datatype_vector(ctx, types[i].datatype, j);
  2259             push_usertype(ctx, stringcache_len(ctx->strcache, buf, len), "?");
  3016             len = snprintf(buf, sizeof (buf), "%s%d", types[i].str, j);
  2260             int k;
  3017             push_usertype(ctx, stringcache_len(ctx->strcache, buf, len), dt);
  2261             for (k = 1; k <= 4; k++)
  3018             for (k = 1; k <= 4; k++)
  2262             {
  3019             {
  2263                 // "float2x2"
  3020                 // "float2x2"
  2264                 len = snprintf(buf, sizeof (buf), "%s%dx%d", types[i], j, k);
  3021                 dt = new_datatype_matrix(ctx, types[i].datatype, j, k);
  2265                 push_usertype(ctx, stringcache_len(ctx->strcache, buf, len), "?");
  3022                 len = snprintf(buf, sizeof (buf), "%s%dx%d", types[i].str,j,k);
       
  3023                 push_usertype(ctx, stringcache_len(ctx->strcache,buf,len), dt);
  2266             } // for
  3024             } // for
  2267         } // for
  3025         } // for
  2268     } // for
  3026     } // for
  2269 
  3027 
  2270     // Run the preprocessor/lexer/parser...
  3028     // Run the preprocessor/lexer/parser...
  2313         else if (skipping)
  3071         else if (skipping)
  2314         {
  3072         {
  2315             continue;
  3073             continue;
  2316         }
  3074         }
  2317 
  3075 
       
  3076         // !!! FIXME: this is a mess, decide who should be doing this stuff, and only do it once.
  2318         lemon_token = convert_to_lemon_token(ctx, token, tokenlen, tokenval);
  3077         lemon_token = convert_to_lemon_token(ctx, token, tokenlen, tokenval);
  2319         switch (lemon_token)
  3078         switch (lemon_token)
  2320         {
  3079         {
  2321             case TOKEN_HLSL_INT_CONSTANT:
  3080             case TOKEN_HLSL_INT_CONSTANT:
  2322                 data.i64 = strtoi64(token, tokenlen);
  3081                 data.i64 = strtoi64(token, tokenlen);
  2325             case TOKEN_HLSL_FLOAT_CONSTANT:
  3084             case TOKEN_HLSL_FLOAT_CONSTANT:
  2326                 data.dbl = strtodouble(token, tokenlen);
  3085                 data.dbl = strtodouble(token, tokenlen);
  2327                 break;
  3086                 break;
  2328 
  3087 
  2329             case TOKEN_HLSL_USERTYPE:
  3088             case TOKEN_HLSL_USERTYPE:
       
  3089                 data.string = stringcache_len(ctx->strcache, token, tokenlen);
       
  3090                 data.datatype = get_usertype(ctx, data.string);
       
  3091                 assert(data.datatype != NULL);
       
  3092                 break;
       
  3093 
  2330             case TOKEN_HLSL_STRING_LITERAL:
  3094             case TOKEN_HLSL_STRING_LITERAL:
  2331             case TOKEN_HLSL_IDENTIFIER:
  3095             case TOKEN_HLSL_IDENTIFIER:
  2332                 data.string = stringcache_len(ctx->strcache, token, tokenlen);
  3096                 data.string = stringcache_len(ctx->strcache, token, tokenlen);
  2333                 break;
  3097                 break;
  2334 
  3098