mojoshader_compiler.c
changeset 973 6d4cdbc21301
parent 972 993c4d6e21a8
child 974 e4c4963e8889
equal deleted inserted replaced
972:993c4d6e21a8 973:6d4cdbc21301
    98     MOJOSHADER_astNode *ast;  // Abstract Syntax Tree
    98     MOJOSHADER_astNode *ast;  // Abstract Syntax Tree
    99     const char *source_profile;
    99     const char *source_profile;
   100     int is_func_scope; // non-zero if semantic analysis is in function scope.
   100     int is_func_scope; // non-zero if semantic analysis is in function scope.
   101     int var_index;  // next variable index for current function.
   101     int var_index;  // next variable index for current function.
   102     int global_var_index;  // next variable index for global scope.
   102     int global_var_index;  // next variable index for global scope.
       
   103     int user_func_index;  // next function index for user-defined functions.
       
   104     int intrinsic_func_index;  // next function index for intrinsic functions.
   103 
   105 
   104     // Cache intrinsic types for fast lookup and consistent pointer values.
   106     // Cache intrinsic types for fast lookup and consistent pointer values.
   105     MOJOSHADER_astDataType dt_bool;
   107     MOJOSHADER_astDataType dt_bool;
   106     MOJOSHADER_astDataType dt_int;
   108     MOJOSHADER_astDataType dt_int;
   107     MOJOSHADER_astDataType dt_uint;
   109     MOJOSHADER_astDataType dt_uint;
   222     map->hash = hash_create(ctx, hash_hash_string, hash_keymatch_string,
   224     map->hash = hash_create(ctx, hash_hash_string, hash_keymatch_string,
   223                             symbolmap_nuke, 1, MallocBridge, FreeBridge, ctx);
   225                             symbolmap_nuke, 1, MallocBridge, FreeBridge, ctx);
   224     return (map->hash != NULL);
   226     return (map->hash != NULL);
   225 } // create_symbolmap
   227 } // create_symbolmap
   226 
   228 
       
   229 static int datatypes_match(const MOJOSHADER_astDataType *a,
       
   230                            const MOJOSHADER_astDataType *b)
       
   231 {
       
   232     int i;
       
   233 
       
   234     if (a == b)
       
   235         return 1;
       
   236     else if (a->type != b->type)
       
   237         return 0;
       
   238 
       
   239     switch (a->type)
       
   240     {
       
   241         case MOJOSHADER_AST_DATATYPE_STRUCT:
       
   242             if (a->structure.member_count != b->structure.member_count)
       
   243                 return 0;
       
   244             for (i = 0; i < a->structure.member_count; i++)
       
   245             {
       
   246                 if (!datatypes_match(a->structure.members[i].datatype,
       
   247                                      b->structure.members[i].datatype))
       
   248                     return 0;
       
   249                 // stringcache'd, pointer compare is safe.
       
   250                 else if (a->structure.members[i].identifier !=
       
   251                          b->structure.members[i].identifier)
       
   252                     return 0;
       
   253             } // for
       
   254             return 1;
       
   255 
       
   256         case MOJOSHADER_AST_DATATYPE_ARRAY:
       
   257             if (a->array.elements != b->array.elements)
       
   258                 return 0;
       
   259             else if (!datatypes_match(a->array.base, b->array.base))
       
   260                 return 0;
       
   261             return 1;
       
   262 
       
   263         case MOJOSHADER_AST_DATATYPE_VECTOR:
       
   264             if (a->vector.elements != b->vector.elements)
       
   265                 return 0;
       
   266             else if (!datatypes_match(a->vector.base, b->vector.base))
       
   267                 return 0;
       
   268             return 1;
       
   269 
       
   270         case MOJOSHADER_AST_DATATYPE_MATRIX:
       
   271             if (a->matrix.rows != b->matrix.rows)
       
   272                 return 0;
       
   273             else if (a->matrix.columns != b->matrix.columns)
       
   274                 return 0;
       
   275             else if (!datatypes_match(a->matrix.base, b->matrix.base))
       
   276                 return 0;
       
   277             return 1;
       
   278 
       
   279         case MOJOSHADER_AST_DATATYPE_BUFFER:
       
   280             return datatypes_match(a->buffer.base, b->buffer.base);
       
   281 
       
   282         case MOJOSHADER_AST_DATATYPE_FUNCTION:
       
   283             if (a->function.num_params != b->function.num_params)
       
   284                 return 0;
       
   285             else if (a->function.intrinsic != b->function.intrinsic)
       
   286                 return 0;
       
   287             else if (!datatypes_match(a->function.retval, b->function.retval))
       
   288                 return 0;
       
   289             for (i = 0; i < a->function.num_params; i++)
       
   290             {
       
   291                 if (!datatypes_match(a->function.params[i], b->function.params[i]))
       
   292                     return 0;
       
   293             } // for
       
   294             return 1;
       
   295 
       
   296         case MOJOSHADER_AST_DATATYPE_USER:
       
   297             return 0;  // pointers must match, this clearly didn't.
       
   298 
       
   299         default:
       
   300             assert(0 && "unexpected case");
       
   301             return 0;
       
   302     } // switch
       
   303 
       
   304     return 0;
       
   305 } // datatypes_match
   227 
   306 
   228 static void push_symbol(Context *ctx, SymbolMap *map, const char *sym,
   307 static void push_symbol(Context *ctx, SymbolMap *map, const char *sym,
   229                         const MOJOSHADER_astDataType *dt, const int index)
   308                         const MOJOSHADER_astDataType *dt, const int index,
   230 {
   309                         const int check_dupes)
       
   310 {
       
   311     if (ctx->out_of_memory)
       
   312         return;
       
   313 
   231     // Decide if this symbol is defined, and if it's in the current scope.
   314     // Decide if this symbol is defined, and if it's in the current scope.
   232     SymbolScope *item = NULL;
   315     SymbolScope *item = NULL;
   233     const void *value = NULL;
   316     const void *value = NULL;
   234     void *iter = NULL;
   317     if ((check_dupes) && (sym != NULL) && (hash_find(map->hash, sym, &value)))
   235     if ((sym != NULL) && (hash_iter(map->hash, sym, &value, &iter)))
   318     {
   236     {
   319         // check the current scope for a dupe.
   237         item = (SymbolScope *) value;
   320         // !!! FIXME: note current scope's starting index, see if found
   238         // Functions are always global, so no need to search scopes.
   321         // !!! FIXME:  item is < index (and thus, a previous scope).
   239             // !!! FIXME: Functions overload, though, so we have to continue
   322         item = map->scope;
   240             // !!! FIXME: iterating to see if it matches anything.
   323         while ((item) && (item->symbol))
   241         //const MOJOSHADER_astDataType *dt = item->datatype;
       
   242         //if (dt->type == MOJOSHADER_AST_DATATYPE_FUNCTION)
       
   243         //{
       
   244         //} // if
       
   245         //else  // check the current scope for a dupe.
       
   246         {
   324         {
   247             item = map->scope;
   325             if ( ((const void *) item) == value )
   248             while ((item) && (item->symbol))
       
   249             {
   326             {
   250                 if (strcmp(item->symbol, sym) == 0)
   327                 failf(ctx, "Symbol '%s' already defined", sym);
   251                 {
   328                 return;
   252                     failf(ctx, "Symbol '%s' already defined", sym);
   329             } // if
   253                     return;
   330             item = item->next;
   254                 } // if
   331         } // while
   255                 item = item->next;
       
   256             } // while
       
   257         } // else
       
   258     } // if
   332     } // if
   259 
   333 
   260     // Add the symbol to our map and scope stack.
   334     // Add the symbol to our map and scope stack.
   261     item = (SymbolScope *) Malloc(ctx, sizeof (SymbolScope));
   335     item = (SymbolScope *) Malloc(ctx, sizeof (SymbolScope));
   262     if (item == NULL)
   336     if (item == NULL)
   299 
   373 
   300             dt = userdt;
   374             dt = userdt;
   301         } // if
   375         } // if
   302     } // if
   376     } // if
   303 
   377 
   304     push_symbol(ctx, &ctx->usertypes, sym, dt, 0);
   378     push_symbol(ctx, &ctx->usertypes, sym, dt, 0, 1);
   305 } // push_usertype
   379 } // push_usertype
   306 
   380 
   307 static inline void push_variable(Context *ctx, const char *sym, const MOJOSHADER_astDataType *dt)
   381 static inline void push_variable(Context *ctx, const char *sym, const MOJOSHADER_astDataType *dt)
   308 {
   382 {
   309     int idx = 0;
   383     int idx = 0;
   313             idx = ++ctx->var_index;  // these are positive.
   387             idx = ++ctx->var_index;  // these are positive.
   314         else
   388         else
   315             idx = --ctx->global_var_index;  // these are negative.
   389             idx = --ctx->global_var_index;  // these are negative.
   316     } // if
   390     } // if
   317 
   391 
   318     push_symbol(ctx, &ctx->variables, sym, dt, idx);
   392     push_symbol(ctx, &ctx->variables, sym, dt, idx, 1);
   319 } // push_variable
   393 } // push_variable
       
   394 
       
   395 static void push_function(Context *ctx, const char *sym,
       
   396                           const MOJOSHADER_astDataType *dt,
       
   397                           const int just_declare)
       
   398 {
       
   399     // we don't have any reason to support nested functions at the moment,
       
   400     //  so this would be a bug.
       
   401     assert(!ctx->is_func_scope);
       
   402     assert(dt->type == MOJOSHADER_AST_DATATYPE_FUNCTION);
       
   403 
       
   404     int idx = 0;
       
   405     if ((sym != NULL) && (dt != NULL))
       
   406     {
       
   407         if (!dt->function.intrinsic)
       
   408             idx = ++ctx->user_func_index;  // these are positive.
       
   409         else
       
   410             idx = --ctx->intrinsic_func_index;  // these are negative.
       
   411     } // if
       
   412 
       
   413     // Functions are always global, so no need to search scopes.
       
   414     //  Functions overload, though, so we have to continue iterating to
       
   415     //  see if it matches anything.
       
   416     const void *value = NULL;
       
   417     void *iter = NULL;
       
   418     while (hash_iter(ctx->variables.hash, sym, &value, &iter))
       
   419     {
       
   420         // there's already something called this.
       
   421         if (datatypes_match(dt, ((SymbolScope *) value)->datatype))
       
   422         {
       
   423             if (!just_declare)
       
   424                 failf(ctx, "Function '%s' already defined.", sym);
       
   425             return;
       
   426         } // if
       
   427     } // while
       
   428 
       
   429     // push_symbol() doesn't check dupes, because we just did.
       
   430     push_symbol(ctx, &ctx->variables, sym, dt, idx, 0);
       
   431 } // push_function
   320 
   432 
   321 static inline void push_scope(Context *ctx)
   433 static inline void push_scope(Context *ctx)
   322 {
   434 {
   323     push_usertype(ctx, NULL, NULL);
   435     push_usertype(ctx, NULL, NULL);
   324     push_variable(ctx, NULL, NULL);
   436     push_variable(ctx, NULL, NULL);
   459 
   571 
   460 
   572 
   461 static void delete_compilation_unit(Context*, MOJOSHADER_astCompilationUnit*);
   573 static void delete_compilation_unit(Context*, MOJOSHADER_astCompilationUnit*);
   462 static void delete_statement(Context *ctx, MOJOSHADER_astStatement *stmt);
   574 static void delete_statement(Context *ctx, MOJOSHADER_astStatement *stmt);
   463 
   575 
       
   576 static MOJOSHADER_astExpression *new_identifier_expr(Context *ctx,
       
   577                                                      const char *string)
       
   578 {
       
   579     NEW_AST_NODE(retval, MOJOSHADER_astExpressionIdentifier,
       
   580                  MOJOSHADER_AST_OP_IDENTIFIER);
       
   581     retval->identifier = string;  // cached; don't copy string.
       
   582     return (MOJOSHADER_astExpression *) retval;
       
   583 } // new_identifier_expr
       
   584 
   464 static MOJOSHADER_astExpression *new_callfunc_expr(Context *ctx,
   585 static MOJOSHADER_astExpression *new_callfunc_expr(Context *ctx,
   465                                         MOJOSHADER_astExpression *identifier,
   586                                         const char *identifier,
   466                                         MOJOSHADER_astArguments *args)
   587                                         MOJOSHADER_astArguments *args)
   467 {
   588 {
   468     NEW_AST_NODE(retval, MOJOSHADER_astExpressionCallFunction,
   589     NEW_AST_NODE(retval, MOJOSHADER_astExpressionCallFunction,
   469                  MOJOSHADER_AST_OP_CALLFUNC);
   590                  MOJOSHADER_AST_OP_CALLFUNC);
   470     retval->identifier = identifier;
   591     MOJOSHADER_astExpression *expr = new_identifier_expr(ctx, identifier);
       
   592     retval->identifier = (MOJOSHADER_astExpressionIdentifier *) expr;
   471     retval->args = args;
   593     retval->args = args;
   472     return (MOJOSHADER_astExpression *) retval;
   594     return (MOJOSHADER_astExpression *) retval;
   473 } // new_callfunc_expr
   595 } // new_callfunc_expr
   474 
   596 
   475 static MOJOSHADER_astExpression *new_constructor_expr(Context *ctx,
   597 static MOJOSHADER_astExpression *new_constructor_expr(Context *ctx,
   541     retval->member = member;  // cached; don't copy string.
   663     retval->member = member;  // cached; don't copy string.
   542     retval->isswizzle = 0;  // may change during semantic analysis.
   664     retval->isswizzle = 0;  // may change during semantic analysis.
   543     return (MOJOSHADER_astExpression *) retval;
   665     return (MOJOSHADER_astExpression *) retval;
   544 } // new_deref_struct_expr
   666 } // new_deref_struct_expr
   545 
   667 
   546 static MOJOSHADER_astExpression *new_identifier_expr(Context *ctx,
       
   547                                                      const char *string)
       
   548 {
       
   549     NEW_AST_NODE(retval, MOJOSHADER_astExpressionIdentifier,
       
   550                  MOJOSHADER_AST_OP_IDENTIFIER);
       
   551     retval->identifier = string;  // cached; don't copy string.
       
   552     return (MOJOSHADER_astExpression *) retval;
       
   553 } // new_identifier_expr
       
   554 
       
   555 static MOJOSHADER_astExpression *new_literal_int_expr(Context *ctx,
   668 static MOJOSHADER_astExpression *new_literal_int_expr(Context *ctx,
   556                                                        const int value)
   669                                                        const int value)
   557 {
   670 {
   558     NEW_AST_NODE(retval, MOJOSHADER_astExpressionIntLiteral,
   671     NEW_AST_NODE(retval, MOJOSHADER_astExpressionIntLiteral,
   559                  MOJOSHADER_AST_OP_INT_LITERAL);
   672                  MOJOSHADER_AST_OP_INT_LITERAL);
   625         delete_expr(ctx, expr->ternary.right);
   738         delete_expr(ctx, expr->ternary.right);
   626     } // else if
   739     } // else if
   627 
   740 
   628     else if (expr->ast.type == MOJOSHADER_AST_OP_CALLFUNC)
   741     else if (expr->ast.type == MOJOSHADER_AST_OP_CALLFUNC)
   629     {
   742     {
   630         delete_expr(ctx, expr->callfunc.identifier);
   743         delete_expr(ctx, (MOJOSHADER_astExpression*)expr->callfunc.identifier);
   631         delete_arguments(ctx, expr->callfunc.args);
   744         delete_arguments(ctx, expr->callfunc.args);
   632     } // else if
   745     } // else if
   633 
   746 
   634     // rest of operators don't have extra data to free.
   747     // rest of operators don't have extra data to free.
   635 
   748 
  1698         retval = retval->user.details;
  1811         retval = retval->user.details;
  1699     return retval;
  1812     return retval;
  1700 } // reduce_datatype
  1813 } // reduce_datatype
  1701 
  1814 
  1702 
  1815 
       
  1816 static const MOJOSHADER_astDataType *build_function_datatype(Context *ctx,
       
  1817                                         const MOJOSHADER_astDataType *rettype,
       
  1818                                         const int paramcount,
       
  1819                                         const MOJOSHADER_astDataType **params,
       
  1820                                         const int intrinsic)
       
  1821 {
       
  1822     assert( ((paramcount == 0) && (params == NULL)) ||
       
  1823             ((paramcount > 0) && (params != NULL)) );
       
  1824 
       
  1825     // !!! FIXME: this is hacky.
       
  1826     const MOJOSHADER_astDataType **dtparams;
       
  1827     void *ptr = Malloc(ctx, sizeof (*params) * paramcount);
       
  1828     if (ptr == NULL)
       
  1829         return NULL;
       
  1830     if (!buffer_append(ctx->garbage, &ptr, sizeof (ptr)))
       
  1831     {
       
  1832         Free(ctx, ptr);
       
  1833         return NULL;
       
  1834     } // if
       
  1835     dtparams = (const MOJOSHADER_astDataType **) ptr;
       
  1836     memcpy(dtparams, params, sizeof (*params) * paramcount);
       
  1837 
       
  1838     ptr = Malloc(ctx, sizeof (MOJOSHADER_astDataType));
       
  1839     if (ptr == NULL)
       
  1840         return NULL;
       
  1841     if (!buffer_append(ctx->garbage, &ptr, sizeof (ptr)))
       
  1842     {
       
  1843         Free(ctx, ptr);
       
  1844         return NULL;
       
  1845     } // if
       
  1846 
       
  1847     MOJOSHADER_astDataType *dt = (MOJOSHADER_astDataType *) ptr;
       
  1848     dt->type = MOJOSHADER_AST_DATATYPE_FUNCTION;
       
  1849     dt->function.retval = rettype;
       
  1850     dt->function.params = dtparams;
       
  1851     dt->function.num_params = paramcount;
       
  1852     dt->function.intrinsic = intrinsic;
       
  1853     return dt;
       
  1854 } // build_function_datatype
       
  1855 
       
  1856 
  1703 static const MOJOSHADER_astDataType *build_datatype(Context *ctx,
  1857 static const MOJOSHADER_astDataType *build_datatype(Context *ctx,
  1704                                             const int isconst,
  1858                                             const int isconst,
  1705                                             const MOJOSHADER_astDataType *dt,
  1859                                             const MOJOSHADER_astDataType *dt,
  1706                                             MOJOSHADER_astScalarOrArray *soa)
  1860                                             MOJOSHADER_astScalarOrArray *soa)
  1707 {
  1861 {
  1849     fail(ctx, "expected struct");
  2003     fail(ctx, "expected struct");
  1850     // !!! FIXME: delete struct dereference for further processing.
  2004     // !!! FIXME: delete struct dereference for further processing.
  1851 } // require_struct_datatype
  2005 } // require_struct_datatype
  1852 
  2006 
  1853 
  2007 
  1854 static const MOJOSHADER_astDataType *require_function_datatype(Context *ctx,
  2008 static int require_function_datatype(Context *ctx,
  1855                                         const MOJOSHADER_astDataType *datatype)
  2009                                      const MOJOSHADER_astDataType *datatype)
  1856 {
  2010 {
  1857     datatype = reduce_datatype(datatype);
  2011     datatype = reduce_datatype(datatype);
  1858     if (datatype->type != MOJOSHADER_AST_DATATYPE_FUNCTION)
  2012     if ((!datatype) || (datatype->type != MOJOSHADER_AST_DATATYPE_FUNCTION))
  1859     {
  2013     {
  1860         fail(ctx, "expected function");
  2014         fail(ctx, "expected function");
  1861         // !!! FIXME: delete function call for further processing.
  2015         return 0;
  1862         return &ctx->dt_int;
       
  1863     } // if
  2016     } // if
  1864 
  2017 
  1865     return datatype->function.retval;
  2018     return 1;
  1866 } // require_function_datatype
  2019 } // require_function_datatype
  1867 
  2020 
  1868 
  2021 
  1869 // Extract the individual element type from an array datatype.
  2022 // Extract the individual element type from an array datatype.
  1870 static const MOJOSHADER_astDataType *array_element_datatype(Context *ctx,
  2023 static const MOJOSHADER_astDataType *array_element_datatype(Context *ctx,
  1991 
  2144 
  1992     if (*str != '\0')  // must be end of string here.
  2145     if (*str != '\0')  // must be end of string here.
  1993         return 0;  // not a swizzle.
  2146         return 0;  // not a swizzle.
  1994     return ((is_rgba + is_xyzw) == 1);  // can only be one or the other.
  2147     return ((is_rgba + is_xyzw) == 1);  // can only be one or the other.
  1995 } // is_swizzle_str
  2148 } // is_swizzle_str
       
  2149 
       
  2150 static const MOJOSHADER_astDataType *type_check_ast(Context *ctx, void *_ast);
       
  2151 
       
  2152 // !!! FIXME: this function sucks.
       
  2153 static const MOJOSHADER_astDataType *match_func_to_call(Context *ctx,
       
  2154                                     MOJOSHADER_astExpressionCallFunction *ast)
       
  2155 {
       
  2156     SymbolScope *best = NULL;  // best choice we find.
       
  2157     MOJOSHADER_astExpressionIdentifier *ident = ast->identifier;
       
  2158     const char *sym = ident->identifier;
       
  2159     const void *value = NULL;
       
  2160     void *iter = NULL;
       
  2161 
       
  2162     int argcount = 0;
       
  2163     MOJOSHADER_astArguments *args = ast->args;
       
  2164     while (args != NULL)
       
  2165     {
       
  2166         argcount++;
       
  2167         type_check_ast(ctx, args->argument);
       
  2168         args = args->next;
       
  2169     } // while;
       
  2170 
       
  2171     // we do some tapdancing to handle function overloading here.
       
  2172     while (hash_iter(ctx->variables.hash, sym, &value, &iter))
       
  2173     {
       
  2174         SymbolScope *item = (SymbolScope *) value;
       
  2175         const MOJOSHADER_astDataType *dt = item->datatype;
       
  2176         dt = reduce_datatype(dt);
       
  2177         // there's a locally-scoped symbol with this name? It takes precedence.
       
  2178         if (dt->type != MOJOSHADER_AST_DATATYPE_FUNCTION)
       
  2179             return dt;
       
  2180 
       
  2181         // !!! FIXME: this needs to find functions that implicit casts would catch:
       
  2182         //          void fn(int x);
       
  2183         //          needs to match:
       
  2184         //          short q = 2; fn(q);
       
  2185         const MOJOSHADER_astDataTypeFunction *dtfn = (MOJOSHADER_astDataTypeFunction *) dt;
       
  2186         args = ast->args;
       
  2187         int match = 1;
       
  2188         int i;
       
  2189 
       
  2190         if (argcount != dtfn->num_params)  // !!! FIXME: default args.
       
  2191             match = 0;
       
  2192         else
       
  2193         {
       
  2194             for (i = 0; i < argcount; i++)
       
  2195             {
       
  2196                 assert(args != NULL);
       
  2197                 dt = args->argument->datatype;
       
  2198                 args = args->next;
       
  2199 
       
  2200                 if (!datatypes_match(dt, dtfn->params[i]))
       
  2201                 {
       
  2202                     match = 0;  // can't be perfect match.
       
  2203                     break;
       
  2204                 } // if
       
  2205             } // for
       
  2206 
       
  2207             if (args != NULL)
       
  2208                 match = 0;  // too many arguments supplied. No match.
       
  2209         } // else
       
  2210 
       
  2211         if (match)
       
  2212         {
       
  2213             best = item;
       
  2214             break;
       
  2215         } // if
       
  2216     } // while
       
  2217 
       
  2218     if (best == NULL)
       
  2219         failf(ctx, "No matching function named '%s'", sym);
       
  2220     else
       
  2221     {
       
  2222         ident->datatype = reduce_datatype(best->datatype);
       
  2223         ident->index = best->index;
       
  2224     } // else
       
  2225 
       
  2226     return ident->datatype;
       
  2227 } // match_func_to_call
  1996 
  2228 
  1997 
  2229 
  1998 // Go through the AST and make sure all datatypes check out okay. For datatypes
  2230 // Go through the AST and make sure all datatypes check out okay. For datatypes
  1999 //  that are compatible but are relying on an implicit cast, we add explicit
  2231 //  that are compatible but are relying on an implicit cast, we add explicit
  2000 //  casts to the AST here, so further processing doesn't have to worry about
  2232 //  casts to the AST here, so further processing doesn't have to worry about
  2202             assert(0 && "Should be done by MOJOSHADER_AST_OP_CALLFUNC/CONSTRUCTOR");
  2434             assert(0 && "Should be done by MOJOSHADER_AST_OP_CALLFUNC/CONSTRUCTOR");
  2203             return NULL;
  2435             return NULL;
  2204 
  2436 
  2205         case MOJOSHADER_AST_OP_CALLFUNC:
  2437         case MOJOSHADER_AST_OP_CALLFUNC:
  2206         {
  2438         {
  2207             datatype = type_check_ast(ctx, ast->callfunc.identifier);
  2439             datatype = match_func_to_call(ctx, &ast->callfunc);
  2208             const MOJOSHADER_astDataType *reduced = reduce_datatype(datatype);
  2440             const MOJOSHADER_astDataType *reduced = reduce_datatype(datatype);
  2209             require_function_datatype(ctx, reduced);
  2441             // !!! FIXME: replace AST node with an int if this isn't a func.
  2210             // !!! FIXME: replace with an int literal if this isn't a function.
  2442             if (!require_function_datatype(ctx, reduced))
       
  2443             {
       
  2444                 ast->callfunc.datatype = &ctx->dt_int;
       
  2445                 return ast->callfunc.datatype;
       
  2446             } // if
       
  2447 
  2211             MOJOSHADER_astArguments *arg = ast->callfunc.args;
  2448             MOJOSHADER_astArguments *arg = ast->callfunc.args;
  2212             MOJOSHADER_astArguments *prev = NULL;
  2449             MOJOSHADER_astArguments *prev = NULL;
  2213             int i;
  2450             int i;
  2214             for (i = 0; i < reduced->function.num_params; i++)
  2451             for (i = 0; i < reduced->function.num_params; i++)
  2215             {
  2452             {
  2216                 if (arg == NULL)  // !!! FIXME: check for default parameters.
  2453                 if (arg == NULL)  // !!! FIXME: check for default parameters, fill them in.
  2217                 {
  2454                 {
  2218                     fail(ctx, "Too few arguments");
  2455                     fail(ctx, "Too few arguments");
  2219                     // !!! FIXME: replace AST here.
  2456                     // !!! FIXME: replace AST here.
  2220                     break;
  2457                     break;
  2221                 } // if
  2458                 } // if
  2222                 datatype2 = type_check_ast(ctx, arg->argument);
  2459                 datatype2 = arg->argument->datatype;  // already type-checked.
  2223                 add_type_coercion(ctx, NULL, &reduced->function.params[i],
  2460                 add_type_coercion(ctx, NULL, reduced->function.params[i],
  2224                                   &arg->argument, datatype2);
  2461                                   &arg->argument, datatype2);
  2225                 prev = arg;
  2462                 prev = arg;
  2226                 arg = arg->next;
  2463                 arg = arg->next;
  2227             } // for
  2464             } // for
  2228 
  2465 
  2229             if (arg != NULL)
  2466             assert(arg == NULL);  // shouldn't have chosen func if too many args.
  2230             {
       
  2231                 // Process extra arguments then chop them out.
       
  2232                 MOJOSHADER_astArguments *argi;
       
  2233                 for (argi = arg; argi != NULL; argi = argi->next)
       
  2234                     type_check_ast(ctx, argi->argument);
       
  2235                 if (prev != NULL)
       
  2236                     prev->next = NULL;
       
  2237                 delete_arguments(ctx, arg);
       
  2238                 fail(ctx, "Too many arguments");
       
  2239             } // if
       
  2240 
  2467 
  2241             ast->callfunc.datatype = reduced->function.retval;
  2468             ast->callfunc.datatype = reduced->function.retval;
  2242             return ast->callfunc.datatype;
  2469             return ast->callfunc.datatype;
  2243         } // case
  2470         } // case
  2244 
  2471 
  2420             type_check_ast(ctx, ast->returnstmt.expr);
  2647             type_check_ast(ctx, ast->returnstmt.expr);
  2421             type_check_ast(ctx, ast->returnstmt.next);
  2648             type_check_ast(ctx, ast->returnstmt.next);
  2422             return NULL;
  2649             return NULL;
  2423 
  2650 
  2424         case MOJOSHADER_AST_COMPUNIT_FUNCTION:
  2651         case MOJOSHADER_AST_COMPUNIT_FUNCTION:
  2425             // !!! FIXME: this is totally broken for function overloading.
  2652             assert(!ctx->is_func_scope);
  2426 //fsdfsdf
  2653 
  2427             datatype = get_usertype(ctx, ast->funcunit.declaration->identifier);
  2654             // We have to tapdance here to make sure the function is in
  2428             if (datatype == NULL)
  2655             //  the global scope, but it's parameters are pushed as variables
       
  2656             //  in the function's scope.
       
  2657 
       
  2658             datatype = type_check_ast(ctx, ast->funcunit.declaration);
       
  2659             push_function(ctx, ast->funcunit.declaration->identifier,
       
  2660                           datatype, ast->funcunit.definition == NULL);
       
  2661 
       
  2662             // not just a declaration, but a full function definition?
       
  2663             if (ast->funcunit.definition != NULL)
  2429             {
  2664             {
  2430                 // add function declaration if we've not seen it.
  2665                 ctx->is_func_scope = 1;
  2431                 datatype = ast->funcunit.declaration->datatype;
  2666                 ctx->var_index = 0;  // reset this every function.
  2432                 push_usertype(ctx, ast->funcunit.declaration->identifier, datatype);
  2667                 push_scope(ctx);  // so function params are in function scope.
  2433             } // if
  2668                 // repush the parameters before checking the actual function.
  2434 
  2669                 MOJOSHADER_astFunctionParameters *param;
  2435             // declarations can be done multiple times if they match.
  2670                 for (param = ast->funcunit.declaration->params; param; param = param->next)
  2436             else if (datatype != ast->funcunit.declaration->datatype)
  2671                     push_variable(ctx, param->identifier, param->datatype);
  2437             {
       
  2438                 // !!! FIXME: function overloading is legal.
       
  2439                 fail(ctx, "function sigs don't match");
       
  2440             } // else
       
  2441 
       
  2442             ctx->is_func_scope = 1;
       
  2443             ctx->var_index = 0;  // reset this every function.
       
  2444             push_scope(ctx);  // so function params are in function scope.
       
  2445             type_check_ast(ctx, ast->funcunit.declaration);
       
  2446             if (ast->funcunit.definition == NULL)
       
  2447                 pop_scope(ctx);
       
  2448             else
       
  2449             {
       
  2450                 type_check_ast(ctx, ast->funcunit.definition);
  2672                 type_check_ast(ctx, ast->funcunit.definition);
  2451                 pop_scope(ctx);
  2673                 pop_scope(ctx);
  2452                 push_variable(ctx, ast->funcunit.declaration->identifier, datatype);
  2674                 ctx->is_func_scope = 0;
  2453             } // else
  2675             } // else
  2454             ctx->is_func_scope = 0;
       
  2455 
  2676 
  2456             type_check_ast(ctx, ast->funcunit.next);
  2677             type_check_ast(ctx, ast->funcunit.next);
  2457             return NULL;
  2678             return NULL;
  2458 
  2679 
  2459         case MOJOSHADER_AST_COMPUNIT_TYPEDEF:
  2680         case MOJOSHADER_AST_COMPUNIT_TYPEDEF:
  2500             assert(0 && "Should be done by MOJOSHADER_AST_FUNCTION_SIGNATURE");
  2721             assert(0 && "Should be done by MOJOSHADER_AST_FUNCTION_SIGNATURE");
  2501 
  2722 
  2502         case MOJOSHADER_AST_FUNCTION_SIGNATURE:
  2723         case MOJOSHADER_AST_FUNCTION_SIGNATURE:
  2503         {
  2724         {
  2504             MOJOSHADER_astFunctionParameters *param;
  2725             MOJOSHADER_astFunctionParameters *param;
  2505             int count = 0;
  2726             const MOJOSHADER_astDataType *dtparams[64];
  2506 
       
  2507             // !!! FIXME: pre-count this?
       
  2508             for (param = ast->funcsig.params; param; param = param->next)
       
  2509                 count++;
       
  2510 
       
  2511             // !!! FIXME: this is hacky.
       
  2512             MOJOSHADER_astDataType *dtparams;
       
  2513             void *ptr = Malloc(ctx, sizeof (*dtparams) * count);
       
  2514             if (ptr == NULL)
       
  2515                 return NULL;
       
  2516             if (!buffer_append(ctx->garbage, &ptr, sizeof (ptr)))
       
  2517             {
       
  2518                 Free(ctx, ptr);
       
  2519                 return NULL;
       
  2520             } // if
       
  2521             dtparams = (MOJOSHADER_astDataType *) ptr;
       
  2522 
       
  2523             ptr = Malloc(ctx, sizeof (MOJOSHADER_astDataType));
       
  2524             if (ptr == NULL)
       
  2525                 return NULL;
       
  2526             if (!buffer_append(ctx->garbage, &ptr, sizeof (ptr)))
       
  2527             {
       
  2528                 Free(ctx, ptr);
       
  2529                 return NULL;
       
  2530             } // if
       
  2531             MOJOSHADER_astDataType *dt = (MOJOSHADER_astDataType *) ptr;
       
  2532 
  2727 
  2533             int i = 0;
  2728             int i = 0;
  2534             for (param = ast->funcsig.params; param; param = param->next)
  2729             for (param = ast->funcsig.params; param; param = param->next)
  2535             {
  2730             {
  2536                 assert(i < count);
  2731                 assert(i <= STATICARRAYLEN(dtparams));  // laziness.
  2537                 push_variable(ctx, param->identifier, param->datatype);
  2732                 if (param->initializer != NULL)
  2538                 datatype2 = type_check_ast(ctx, param->initializer);
  2733                 {
  2539                 add_type_coercion(ctx, NULL, param->datatype,
  2734                     datatype2 = type_check_ast(ctx, param->initializer);
  2540                                   &param->initializer, datatype2);
  2735                     add_type_coercion(ctx, NULL, param->datatype,
  2541                 memcpy(&dtparams[i], param->datatype, sizeof (*param->datatype));
  2736                                       &param->initializer, datatype2);
       
  2737                 } // if
       
  2738                 dtparams[i] = param->datatype;
  2542                 i++;
  2739                 i++;
  2543             } // for
  2740             } // for
  2544 
  2741 
  2545             dt->type = MOJOSHADER_AST_DATATYPE_FUNCTION;
  2742             ast->funcsig.datatype = build_function_datatype(ctx,
  2546             dt->function.retval = ast->funcsig.datatype;
  2743                                                         ast->funcsig.datatype,
  2547             dt->function.params = dtparams;
  2744                                                         i, dtparams, 0);
  2548             dt->function.num_params = count;
       
  2549 
       
  2550             ast->funcsig.datatype = dt;
       
  2551             return ast->funcsig.datatype;
  2745             return ast->funcsig.datatype;
  2552         } // case
  2746         } // case
  2553 
  2747 
  2554         case MOJOSHADER_AST_STRUCT_DECLARATION:
  2748         case MOJOSHADER_AST_STRUCT_DECLARATION:
  2555         {
  2749         {