From d64bcad37fef90aea2f57302339ecfd4db6b7291 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 28 Oct 2010 03:42:12 -0400 Subject: [PATCH] Heavy rework of the AST code. Moved AST stuff to a public API and filled in AST and compile API stubs. print_ast() has been cleaned up, and moved from MojoShader to the compiler application. type_check_ast() is much cleaner, too. This has turned into a massive (and incomplete) undertaking. Next steps are filling in the formal API code, moving the AST stuff to a separate file, and wiring it up to the compiler application. (Not to mention polishing up semantic analysis, finishing up the IR, reworking the nasty datatype system, etc, etc, etc...) --- mojoshader.h | 859 ++++++++++++ mojoshader_compiler.c | 2575 ++++++++++------------------------ mojoshader_parser_hlsl.lemon | 322 ++--- utils/mojoshader-compiler.c | 589 +++++++- 4 files changed, 2306 insertions(+), 2039 deletions(-) diff --git a/mojoshader.h b/mojoshader.h index b95d7696..cd8c4de3 100644 --- a/mojoshader.h +++ b/mojoshader.h @@ -882,6 +882,865 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *filename, MOJOSHADER_malloc m, MOJOSHADER_free f, void *d); +/* High level shading language support... */ + +/* + * Source profile strings for HLSL: Direct3D High Level Shading Language. + */ +#define MOJOSHADER_SRC_PROFILE_HLSL_VS_1_1 "hlsl_vs_1_1" +#define MOJOSHADER_SRC_PROFILE_HLSL_VS_2_0 "hlsl_vs_2_0" +#define MOJOSHADER_SRC_PROFILE_HLSL_VS_3_0 "hlsl_vs_3_0" +#define MOJOSHADER_SRC_PROFILE_HLSL_PS_1_1 "hlsl_ps_1_1" +#define MOJOSHADER_SRC_PROFILE_HLSL_PS_1_2 "hlsl_ps_1_2" +#define MOJOSHADER_SRC_PROFILE_HLSL_PS_1_3 "hlsl_ps_1_3" +#define MOJOSHADER_SRC_PROFILE_HLSL_PS_1_4 "hlsl_ps_1_4" +#define MOJOSHADER_SRC_PROFILE_HLSL_PS_2_0 "hlsl_ps_2_0" +#define MOJOSHADER_SRC_PROFILE_HLSL_PS_3_0 "hlsl_ps_3_0" + + +/* Abstract Syntax Tree interface... */ + +/* + * ATTENTION: This adds a lot of stuff to the API, but almost everyone can + * ignore this section. Seriously, go ahead and skip over anything that has + * "AST" in it, unless you know why you'd want to use it. + * + * ALSO: This API is still evolving! We make no promises at this time to keep + * source or binary compatibility for the AST pieces. + */ + +/* Structures that make up the parse tree... */ + +typedef enum MOJOSHADER_astNodeType +{ + MOJOSHADER_AST_OP_START_RANGE, /* expression operators. */ + + MOJOSHADER_AST_OP_START_RANGE_UNARY, /* unary operators. */ + MOJOSHADER_AST_OP_PREINCREMENT, + MOJOSHADER_AST_OP_PREDECREMENT, + MOJOSHADER_AST_OP_NEGATE, + MOJOSHADER_AST_OP_COMPLEMENT, + MOJOSHADER_AST_OP_NOT, + MOJOSHADER_AST_OP_POSTINCREMENT, + MOJOSHADER_AST_OP_POSTDECREMENT, + MOJOSHADER_AST_OP_END_RANGE_UNARY, + + MOJOSHADER_AST_OP_START_RANGE_BINARY, /* binary operators. */ + MOJOSHADER_AST_OP_COMMA, + MOJOSHADER_AST_OP_MULTIPLY, + MOJOSHADER_AST_OP_DIVIDE, + MOJOSHADER_AST_OP_MODULO, + MOJOSHADER_AST_OP_ADD, + MOJOSHADER_AST_OP_SUBTRACT, + MOJOSHADER_AST_OP_LSHIFT, + MOJOSHADER_AST_OP_RSHIFT, + MOJOSHADER_AST_OP_LESSTHAN, + MOJOSHADER_AST_OP_GREATERTHAN, + MOJOSHADER_AST_OP_LESSTHANOREQUAL, + MOJOSHADER_AST_OP_GREATERTHANOREQUAL, + MOJOSHADER_AST_OP_EQUAL, + MOJOSHADER_AST_OP_NOTEQUAL, + MOJOSHADER_AST_OP_BINARYAND, + MOJOSHADER_AST_OP_BINARYXOR, + MOJOSHADER_AST_OP_BINARYOR, + MOJOSHADER_AST_OP_LOGICALAND, + MOJOSHADER_AST_OP_LOGICALOR, + MOJOSHADER_AST_OP_ASSIGN, + MOJOSHADER_AST_OP_MULASSIGN, + MOJOSHADER_AST_OP_DIVASSIGN, + MOJOSHADER_AST_OP_MODASSIGN, + MOJOSHADER_AST_OP_ADDASSIGN, + MOJOSHADER_AST_OP_SUBASSIGN, + MOJOSHADER_AST_OP_LSHIFTASSIGN, + MOJOSHADER_AST_OP_RSHIFTASSIGN, + MOJOSHADER_AST_OP_ANDASSIGN, + MOJOSHADER_AST_OP_XORASSIGN, + MOJOSHADER_AST_OP_ORASSIGN, + MOJOSHADER_AST_OP_DEREF_ARRAY, + MOJOSHADER_AST_OP_END_RANGE_BINARY, + + MOJOSHADER_AST_OP_START_RANGE_TERNARY, /* ternary operators. */ + MOJOSHADER_AST_OP_CONDITIONAL, + MOJOSHADER_AST_OP_END_RANGE_TERNARY, + + MOJOSHADER_AST_OP_START_RANGE_DATA, /* expression operands. */ + MOJOSHADER_AST_OP_IDENTIFIER, + MOJOSHADER_AST_OP_INT_LITERAL, + MOJOSHADER_AST_OP_FLOAT_LITERAL, + MOJOSHADER_AST_OP_STRING_LITERAL, + MOJOSHADER_AST_OP_BOOLEAN_LITERAL, + MOJOSHADER_AST_OP_END_RANGE_DATA, + + MOJOSHADER_AST_OP_START_RANGE_MISC, /* other expression things. */ + MOJOSHADER_AST_OP_DEREF_STRUCT, + MOJOSHADER_AST_OP_CALLFUNC, + MOJOSHADER_AST_OP_CONSTRUCTOR, + MOJOSHADER_AST_OP_CAST, + MOJOSHADER_AST_OP_END_RANGE_MISC, + MOJOSHADER_AST_OP_END_RANGE, + + MOJOSHADER_AST_COMPUNIT_START_RANGE, /* things in global scope. */ + MOJOSHADER_AST_COMPUNIT_FUNCTION, + MOJOSHADER_AST_COMPUNIT_TYPEDEF, + MOJOSHADER_AST_COMPUNIT_STRUCT, + MOJOSHADER_AST_COMPUNIT_VARIABLE, + MOJOSHADER_AST_COMPUNIT_END_RANGE, + + MOJOSHADER_AST_STATEMENT_START_RANGE, /* statements in function scope. */ + MOJOSHADER_AST_STATEMENT_EMPTY, + MOJOSHADER_AST_STATEMENT_BREAK, + MOJOSHADER_AST_STATEMENT_CONTINUE, + MOJOSHADER_AST_STATEMENT_DISCARD, + MOJOSHADER_AST_STATEMENT_BLOCK, + MOJOSHADER_AST_STATEMENT_EXPRESSION, + MOJOSHADER_AST_STATEMENT_IF, + MOJOSHADER_AST_STATEMENT_SWITCH, + MOJOSHADER_AST_STATEMENT_FOR, + MOJOSHADER_AST_STATEMENT_DO, + MOJOSHADER_AST_STATEMENT_WHILE, + MOJOSHADER_AST_STATEMENT_RETURN, + MOJOSHADER_AST_STATEMENT_TYPEDEF, + MOJOSHADER_AST_STATEMENT_STRUCT, + MOJOSHADER_AST_STATEMENT_VARDECL, + MOJOSHADER_AST_STATEMENT_END_RANGE, + + MOJOSHADER_AST_MISC_START_RANGE, /* misc. syntactic glue. */ + MOJOSHADER_AST_FUNCTION_PARAMS, + MOJOSHADER_AST_FUNCTION_SIGNATURE, + MOJOSHADER_AST_SCALAR_OR_ARRAY, + MOJOSHADER_AST_TYPEDEF, + MOJOSHADER_AST_PACK_OFFSET, + MOJOSHADER_AST_VARIABLE_LOWLEVEL, + MOJOSHADER_AST_ANNOTATION, + MOJOSHADER_AST_VARIABLE_DECLARATION, + MOJOSHADER_AST_STRUCT_DECLARATION, + MOJOSHADER_AST_STRUCT_MEMBER, + MOJOSHADER_AST_SWITCH_CASE, + MOJOSHADER_AST_ARGUMENTS, + MOJOSHADER_AST_MISC_END_RANGE, + + MOJOSHADER_AST_END_RANGE +} MOJOSHADER_astNodeType; + +typedef struct MOJOSHADER_astNodeInfo +{ + MOJOSHADER_astNodeType type; + const char *filename; + unsigned int line; +} MOJOSHADER_astNodeInfo; + +typedef enum MOJOSHADER_astVariableAttributes +{ + MOJOSHADER_AST_VARATTR_EXTERN = (1 << 0), + MOJOSHADER_AST_VARATTR_NOINTERPOLATION = (1 << 1), + MOJOSHADER_AST_VARATTR_SHARED = (1 << 2), + MOJOSHADER_AST_VARATTR_STATIC = (1 << 3), + MOJOSHADER_AST_VARATTR_UNIFORM = (1 << 4), + MOJOSHADER_AST_VARATTR_VOLATILE = (1 << 5), + MOJOSHADER_AST_VARATTR_CONST = (1 << 6), + MOJOSHADER_AST_VARATTR_ROWMAJOR = (1 << 7), + MOJOSHADER_AST_VARATTR_COLUMNMAJOR = (1 << 8) +} MOJOSHADER_astVariableAttributes; + +typedef enum MOJOSHADER_astIfAttributes +{ + MOJOSHADER_AST_IFATTR_NONE, + MOJOSHADER_AST_IFATTR_BRANCH, + MOJOSHADER_AST_IFATTR_FLATTEN, + MOJOSHADER_AST_IFATTR_IFALL, + MOJOSHADER_AST_IFATTR_IFANY, + MOJOSHADER_AST_IFATTR_PREDICATE, + MOJOSHADER_AST_IFATTR_PREDICATEBLOCK, +} MOJOSHADER_astIfAttributes; + +typedef enum MOJOSHADER_astSwitchAttributes +{ + MOJOSHADER_AST_SWITCHATTR_NONE, + MOJOSHADER_AST_SWITCHATTR_FLATTEN, + MOJOSHADER_AST_SWITCHATTR_BRANCH, + MOJOSHADER_AST_SWITCHATTR_FORCECASE, + MOJOSHADER_AST_SWITCHATTR_CALL +} MOJOSHADER_astSwitchAttributes; + +/* You can cast any AST node pointer to this. */ +typedef struct MOJOSHADER_astGeneric +{ + MOJOSHADER_astNodeInfo ast; +} MOJOSHADER_astGeneric; + +typedef MOJOSHADER_astGeneric MOJOSHADER_astExpression; + +typedef struct MOJOSHADER_astArguments +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_ARGUMENTS */ + MOJOSHADER_astExpression *argument; + struct MOJOSHADER_astArguments *next; +} MOJOSHADER_astArguments; + +typedef struct MOJOSHADER_astExpressionUnary +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astExpression *operand; +} MOJOSHADER_astExpressionUnary; + +typedef struct MOJOSHADER_astExpressionBinary +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astExpression *left; + MOJOSHADER_astExpression *right; +} MOJOSHADER_astExpressionBinary; + +typedef struct MOJOSHADER_astExpressionTernary +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astExpression *left; + MOJOSHADER_astExpression *center; + MOJOSHADER_astExpression *right; +} MOJOSHADER_astExpressionTernary; + +typedef struct MOJOSHADER_astExpressionIdentifier +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_OP_IDENTIFIER */ + const char *identifier; +} MOJOSHADER_astExpressionIdentifier; + +typedef struct MOJOSHADER_astExpressionIntLiteral +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_OP_INT_LITERAL */ + int value; +} MOJOSHADER_astExpressionIntLiteral; + +typedef struct MOJOSHADER_astExpressionFloatLiteral +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_OP_FLOAT_LITERAL */ + double value; +} MOJOSHADER_astExpressionFloatLiteral; + +typedef struct MOJOSHADER_astExpressionStringLiteral +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_OP_STRING_LITERAL */ + const char *string; +} MOJOSHADER_astExpressionStringLiteral; + +typedef struct MOJOSHADER_astExpressionBooleanLiteral +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_OP_BOOLEAN_LITERAL */ + int value; /* Always 1 or 0. */ +} MOJOSHADER_astExpressionBooleanLiteral; + +typedef struct MOJOSHADER_astExpressionConstructor +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_OP_CONSTRUCTOR */ + const char *datatype; + MOJOSHADER_astArguments *args; +} MOJOSHADER_astExpressionConstructor; + +typedef struct MOJOSHADER_astExpressionDerefStruct +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_OP_DEREF_STRUCT */ + MOJOSHADER_astExpression *identifier; + const char *member; +} MOJOSHADER_astExpressionDerefStruct; + +typedef struct MOJOSHADER_astExpressionCallFunction +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_OP_CALLFUNC */ + MOJOSHADER_astExpression *identifier; + MOJOSHADER_astArguments *args; +} MOJOSHADER_astExpressionCallFunction; + +typedef struct MOJOSHADER_astExpressionCast +{ + MOJOSHADER_astNodeInfo ast; /* Always MOJOSHADER_AST_OP_CAST */ + const char *datatype; + MOJOSHADER_astExpression *operand; +} MOJOSHADER_astExpressionCast; + +typedef struct MOJOSHADER_astCompilationUnit +{ + MOJOSHADER_astNodeInfo ast; + struct MOJOSHADER_astCompilationUnit *next; +} MOJOSHADER_astCompilationUnit; + +typedef enum MOJOSHADER_astFunctionStorageClass +{ + MOJOSHADER_AST_FNSTORECLS_NONE, + MOJOSHADER_AST_FNSTORECLS_INLINE +} MOJOSHADER_astFunctionStorageClass; + +typedef enum MOJOSHADER_astInputModifier +{ + MOJOSHADER_AST_INPUTMOD_NONE, + MOJOSHADER_AST_INPUTMOD_IN, + MOJOSHADER_AST_INPUTMOD_OUT, + MOJOSHADER_AST_INPUTMOD_INOUT, + MOJOSHADER_AST_INPUTMOD_UNIFORM +} MOJOSHADER_astInputModifier; + +typedef enum MOJOSHADER_astInterpolationModifier +{ + MOJOSHADER_AST_INTERPMOD_NONE, + MOJOSHADER_AST_INTERPMOD_LINEAR, + MOJOSHADER_AST_INTERPMOD_CENTROID, + MOJOSHADER_AST_INTERPMOD_NOINTERPOLATION, + MOJOSHADER_AST_INTERPMOD_NOPERSPECTIVE, + MOJOSHADER_AST_INTERPMOD_SAMPLE +} MOJOSHADER_astInterpolationModifier; + +typedef struct MOJOSHADER_astFunctionParameters +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astInputModifier input_modifier; + const char *datatype; + const char *identifier; + const char *semantic; + MOJOSHADER_astInterpolationModifier interpolation_modifier; + MOJOSHADER_astExpression *initializer; + struct MOJOSHADER_astFunctionParameters *next; +} MOJOSHADER_astFunctionParameters; + +typedef struct MOJOSHADER_astFunctionSignature +{ + MOJOSHADER_astNodeInfo ast; + const char *datatype; + const char *identifier; + MOJOSHADER_astFunctionParameters *params; + MOJOSHADER_astFunctionStorageClass storage_class; + const char *semantic; +} MOJOSHADER_astFunctionSignature; + +typedef struct MOJOSHADER_astScalarOrArray +{ + MOJOSHADER_astNodeInfo ast; + const char *identifier; + int isarray; /* boolean: 1 or 0 */ + MOJOSHADER_astExpression *dimension; +} MOJOSHADER_astScalarOrArray; + +typedef struct MOJOSHADER_astAnnotations +{ + MOJOSHADER_astNodeInfo ast; + const char *datatype; + MOJOSHADER_astExpression *initializer; + struct MOJOSHADER_astAnnotations *next; +} MOJOSHADER_astAnnotations; + +typedef struct MOJOSHADER_astPackOffset +{ + MOJOSHADER_astNodeInfo ast; + const char *ident1; /* !!! FIXME: rename this. */ + const char *ident2; +} MOJOSHADER_astPackOffset; + +typedef struct MOJOSHADER_astVariableLowLevel +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astPackOffset *packoffset; + const char *register_name; +} MOJOSHADER_astVariableLowLevel; + +typedef struct MOJOSHADER_astStructMembers +{ + MOJOSHADER_astNodeInfo ast; + const char *datatype; + const char *semantic; + MOJOSHADER_astScalarOrArray *details; + MOJOSHADER_astInterpolationModifier interpolation_mod; + struct MOJOSHADER_astStructMembers *next; +} MOJOSHADER_astStructMembers; + +typedef struct MOJOSHADER_astStructDeclaration +{ + MOJOSHADER_astNodeInfo ast; + const char *name; + MOJOSHADER_astStructMembers *members; +} MOJOSHADER_astStructDeclaration; + +typedef struct MOJOSHADER_astVariableDeclaration +{ + MOJOSHADER_astNodeInfo ast; + int attributes; + const char *datatype; + MOJOSHADER_astStructDeclaration *anonymous_datatype; + MOJOSHADER_astScalarOrArray *details; + const char *semantic; + MOJOSHADER_astAnnotations *annotations; + MOJOSHADER_astExpression *initializer; + MOJOSHADER_astVariableLowLevel *lowlevel; + struct MOJOSHADER_astVariableDeclaration *next; +} MOJOSHADER_astVariableDeclaration; + +typedef struct MOJOSHADER_astStatement +{ + MOJOSHADER_astNodeInfo ast; + struct MOJOSHADER_astStatement *next; +} MOJOSHADER_astStatement; + +typedef MOJOSHADER_astStatement MOJOSHADER_astEmptyStatement; +typedef MOJOSHADER_astStatement MOJOSHADER_astBreakStatement; +typedef MOJOSHADER_astStatement MOJOSHADER_astContinueStatement; +typedef MOJOSHADER_astStatement MOJOSHADER_astDiscardStatement; + +/* something enclosed in "{}" braces. */ +typedef struct MOJOSHADER_astBlockStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + MOJOSHADER_astStatement *statements; /* list of child statements. */ +} MOJOSHADER_astBlockStatement; + +typedef struct MOJOSHADER_astReturnStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + MOJOSHADER_astExpression *expr; +} MOJOSHADER_astReturnStatement; + +typedef struct MOJOSHADER_astExpressionStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + MOJOSHADER_astExpression *expr; +} MOJOSHADER_astExpressionStatement; + +typedef struct MOJOSHADER_astIfStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + int attributes; + MOJOSHADER_astExpression *expr; + MOJOSHADER_astStatement *statement; + MOJOSHADER_astStatement *else_statement; +} MOJOSHADER_astIfStatement; + +typedef struct MOJOSHADER_astSwitchCases +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astExpression *expr; + MOJOSHADER_astStatement *statement; + struct MOJOSHADER_astSwitchCases *next; +} MOJOSHADER_astSwitchCases; + +typedef struct MOJOSHADER_astSwitchStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + int attributes; + MOJOSHADER_astExpression *expr; + MOJOSHADER_astSwitchCases *cases; +} MOJOSHADER_astSwitchStatement; + +typedef struct MOJOSHADER_astWhileStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + int unroll; /* # times to unroll, 0 to loop, < 0 == compiler's choice. */ + MOJOSHADER_astExpression *expr; + MOJOSHADER_astStatement *statement; +} MOJOSHADER_astWhileStatement; + +typedef MOJOSHADER_astWhileStatement MOJOSHADER_astDoStatement; + +typedef struct MOJOSHADER_astForStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + int unroll; /* # times to unroll, 0 to loop, < 0 == compiler's choice. */ + MOJOSHADER_astVariableDeclaration *var_decl; + MOJOSHADER_astExpression *initializer; + MOJOSHADER_astExpression *looptest; + MOJOSHADER_astExpression *counter; + MOJOSHADER_astStatement *statement; +} MOJOSHADER_astForStatement; + +typedef struct MOJOSHADER_astTypedef +{ + MOJOSHADER_astNodeInfo ast; + int isconst; /* boolean: 1 or 0 */ + const char *datatype; + MOJOSHADER_astScalarOrArray *details; +} MOJOSHADER_astTypedef; + +typedef struct MOJOSHADER_astTypedefStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + MOJOSHADER_astTypedef *type_info; +} MOJOSHADER_astTypedefStatement; + +typedef struct MOJOSHADER_astVarDeclStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + MOJOSHADER_astVariableDeclaration *declaration; +} MOJOSHADER_astVarDeclStatement; + +typedef struct MOJOSHADER_astStructStatement +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astStatement *next; + MOJOSHADER_astStructDeclaration *struct_info; +} MOJOSHADER_astStructStatement; + +typedef struct MOJOSHADER_astCompilationUnitFunction +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astCompilationUnit *next; + MOJOSHADER_astFunctionSignature *declaration; + MOJOSHADER_astStatement *definition; +} MOJOSHADER_astCompilationUnitFunction; + +typedef struct MOJOSHADER_astCompilationUnitTypedef +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astCompilationUnit *next; + MOJOSHADER_astTypedef *type_info; +} MOJOSHADER_astCompilationUnitTypedef; + +typedef struct MOJOSHADER_astCompilationUnitStruct +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astCompilationUnit *next; + MOJOSHADER_astStructDeclaration *struct_info; +} MOJOSHADER_astCompilationUnitStruct; + +typedef struct MOJOSHADER_astCompilationUnitVariable +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astCompilationUnit *next; + MOJOSHADER_astVariableDeclaration *declaration; +} MOJOSHADER_astCompilationUnitVariable; + + +/* this is way cleaner than all the nasty typecasting. */ +typedef union MOJOSHADER_astNode +{ + MOJOSHADER_astNodeInfo ast; + MOJOSHADER_astGeneric generic; + MOJOSHADER_astExpression expression; + MOJOSHADER_astArguments arguments; + MOJOSHADER_astExpressionUnary unary; + MOJOSHADER_astExpressionBinary binary; + MOJOSHADER_astExpressionTernary ternary; + MOJOSHADER_astExpressionIdentifier identifier; + MOJOSHADER_astExpressionIntLiteral intliteral; + MOJOSHADER_astExpressionFloatLiteral floatliteral; + MOJOSHADER_astExpressionStringLiteral stringliteral; + MOJOSHADER_astExpressionBooleanLiteral boolliteral; + MOJOSHADER_astExpressionConstructor constructor; + MOJOSHADER_astExpressionDerefStruct derefstruct; + MOJOSHADER_astExpressionCallFunction callfunc; + MOJOSHADER_astExpressionCast cast; + MOJOSHADER_astCompilationUnit compunit; + MOJOSHADER_astFunctionParameters params; + MOJOSHADER_astFunctionSignature funcsig; + MOJOSHADER_astScalarOrArray soa; + MOJOSHADER_astAnnotations annotations; + MOJOSHADER_astPackOffset packoffset; + MOJOSHADER_astVariableLowLevel varlowlevel; + MOJOSHADER_astStructMembers structmembers; + MOJOSHADER_astStructDeclaration structdecl; + MOJOSHADER_astVariableDeclaration vardecl; + MOJOSHADER_astStatement stmt; + MOJOSHADER_astEmptyStatement emptystmt; + MOJOSHADER_astBreakStatement breakstmt; + MOJOSHADER_astContinueStatement contstmt; + MOJOSHADER_astDiscardStatement discardstmt; + MOJOSHADER_astBlockStatement blockstmt; + MOJOSHADER_astReturnStatement returnstmt; + MOJOSHADER_astExpressionStatement exprstmt; + MOJOSHADER_astIfStatement ifstmt; + MOJOSHADER_astSwitchCases cases; + MOJOSHADER_astSwitchStatement switchstmt; + MOJOSHADER_astWhileStatement whilestmt; + MOJOSHADER_astDoStatement dostmt; + MOJOSHADER_astForStatement forstmt; + MOJOSHADER_astTypedef typdef; + MOJOSHADER_astTypedefStatement typedefstmt; + MOJOSHADER_astVarDeclStatement vardeclstmt; + MOJOSHADER_astStructStatement structstmt; + MOJOSHADER_astCompilationUnitFunction funcunit; + MOJOSHADER_astCompilationUnitTypedef typedefunit; + MOJOSHADER_astCompilationUnitStruct structunit; + MOJOSHADER_astCompilationUnitVariable varunit; +} MOJOSHADER_astNode; + + +/* + * Structure used to return data from parsing of a shader into an AST... + */ +/* !!! FIXME: most of these ints should be unsigned. */ +typedef struct MOJOSHADER_astData +{ + /* + * The number of elements pointed to by (errors). + */ + int error_count; + + /* + * (error_count) elements of data that specify errors that were generated + * by parsing this shader. + * This can be NULL if there were no errors or if (error_count) is zero. + * Note that this will only produce errors for syntax problems. Most of + * the things we expect a compiler to produce errors for--incompatible + * types, unknown identifiers, etc--are not checked at all during + * initial generation of the syntax tree...bogus programs that would + * fail to compile will pass here without error, if they are syntactically + * correct! + */ + MOJOSHADER_error *errors; + + /* + * The name of the source profile used to parse the shader. Will be NULL + * on error. + */ + const char *source_profile; + + /* + * The actual syntax tree. You are responsible for walking it yourself. + * CompilationUnits are always the top of the tree (functions, typedefs, + * global variables, etc). + */ + const MOJOSHADER_astNode *ast; + + /* + * This is the malloc implementation you passed to MOJOSHADER_parse(). + */ + MOJOSHADER_malloc malloc; + + /* + * This is the free implementation you passed to MOJOSHADER_parse(). + */ + MOJOSHADER_free free; + + /* + * This is the pointer you passed as opaque data for your allocator. + */ + void *malloc_data; +} MOJOSHADER_astData; + + +/* + * You almost certainly don't need this function, unless you absolutely know + * why you need it without hesitation. This is almost certainly only good for + * building code analysis tools on top of. + * + * This is intended to parse HLSL source code, turning it into an abstract + * syntax tree. + * + * (srcprofile) specifies the source language of the shader. You can specify + * a shader model with this, too. See MOJOSHADER_SRC_PROFILE_* constants. + * + * (filename) is a NULL-terminated UTF-8 filename. It can be NULL. We do not + * actually access this file, as we obtain our data from (source). This + * string is copied when we need to report errors while processing (source), + * as opposed to errors in a file referenced via the #include directive in + * (source). If this is NULL, then errors will report the filename as NULL, + * too. + * + * (source) is an UTF-8 string of valid high-level shader source code. + * It does not need to be NULL-terminated. + * + * (sourcelen) is the length of the string pointed to by (source), in bytes. + * + * (defines) points to (define_count) preprocessor definitions, and can be + * NULL. These are treated by the preprocessor as if the source code started + * with one #define for each entry you pass in here. + * + * (include_open) and (include_close) let the app control the preprocessor's + * behaviour for #include statements. Both are optional and can be NULL, but + * both must be specified if either is specified. + * + * This will return a MOJOSHADER_astData. The data supplied here gives the + * application a tree-like structure they can walk to see the layout of + * a given program. When you are done with this data, pass it to + * MOJOSHADER_freeCompileData() to deallocate resources. + * + * This function will never return NULL, even if the system is completely + * out of memory upon entry (in which case, this function returns a static + * MOJOSHADER_astData object, which is still safe to pass to + * MOJOSHADER_freeAstData()). + * + * As parsing requires some memory to be allocated, you may provide a + * custom allocator to this function, which will be used to allocate/free + * memory. They function just like malloc() and free(). We do not use + * realloc(). If you don't care, pass NULL in for the allocator functions. + * If your allocator needs instance-specific data, you may supply it with the + * (d) parameter. This pointer is passed as-is to your (m) and (f) functions. + * + * This function is thread safe, so long as the various callback functions + * are, too, and that the parameters remains intact for the duration of the + * call. This allows you to parse several shaders on separate CPU cores + * at the same time. + */ +const MOJOSHADER_astData *MOJOSHADER_parseAst(const char *srcprofile, + const char *filename, const char *source, + unsigned int sourcelen, + const MOJOSHADER_preprocessorDefine *defs, + unsigned int define_count, + MOJOSHADER_includeOpen include_open, + MOJOSHADER_includeClose include_close, + MOJOSHADER_malloc m, MOJOSHADER_free f, + void *d); + +/* + * Call this to dispose of AST parsing results when you are done with them. + * This will call the MOJOSHADER_free function you provided to + * MOJOSHADER_parseAst() multiple times, if you provided one. + * Passing a NULL here is a safe no-op. + * + * This function is thread safe, so long as any allocator you passed into + * MOJOSHADER_parseAst() is, too. + */ +void MOJOSHADER_freeAstData(const MOJOSHADER_astData *data); + + + +/* Compiler interface... */ + +/* + * Structure used to return data from parsing of a shader... + */ +/* !!! FIXME: most of these ints should be unsigned. */ +typedef struct MOJOSHADER_compileData +{ + /* + * The number of elements pointed to by (errors). + */ + int error_count; + + /* + * (error_count) elements of data that specify errors that were generated + * by compiling this shader. + * This can be NULL if there were no errors or if (error_count) is zero. + */ + MOJOSHADER_error *errors; + + /* + * The number of elements pointed to by (warnings). + */ + int warning_count; + + /* + * (warning_count) elements of data that specify errors that were + * generated by compiling this shader. + * This can be NULL if there were no errors or if (warning_count) is zero. + */ + MOJOSHADER_error *warnings; + + /* + * The name of the source profile used to compile the shader. Will be NULL + * on error. + */ + const char *source_profile; + + /* + * Bytes of output from compiling. This will be a null-terminated ASCII + * string of D3D assembly source code. + */ + const char *output; + + /* + * Byte count for output, not counting any null terminator. + * Will be 0 on error. + */ + int output_len; + + /* + * The number of elements pointed to by (symbols). + */ + int symbol_count; + + /* + * (symbol_count) elements of data that specify high-level symbol data + * for the shader. This can be used by MOJOSHADER_assemble() to + * generate a CTAB section in bytecode, which is needed by + * MOJOSHADER_parseData() to handle some shaders. This can be NULL on + * error or if (symbol_count) is zero. + */ + MOJOSHADER_symbol *symbols; + + /* + * This is the malloc implementation you passed to MOJOSHADER_parse(). + */ + MOJOSHADER_malloc malloc; + + /* + * This is the free implementation you passed to MOJOSHADER_parse(). + */ + MOJOSHADER_free free; + + /* + * This is the pointer you passed as opaque data for your allocator. + */ + void *malloc_data; +} MOJOSHADER_compileData; + + +/* + * This function is optional. Use this to compile high-level shader programs. + * + * This is intended to turn HLSL source code into D3D assembly code, which + * can then be passed to MOJOSHADER_assemble() to convert it to D3D bytecode + * (which can then be used with MOJOSHADER_parseData() to support other + * shading targets). + * + * (srcprofile) specifies the source language of the shader. You can specify + * a shader model with this, too. See MOJOSHADER_SRC_PROFILE_* constants. + * + * (filename) is a NULL-terminated UTF-8 filename. It can be NULL. We do not + * actually access this file, as we obtain our data from (source). This + * string is copied when we need to report errors while processing (source), + * as opposed to errors in a file referenced via the #include directive in + * (source). If this is NULL, then errors will report the filename as NULL, + * too. + * + * (source) is an UTF-8 string of valid high-level shader source code. + * It does not need to be NULL-terminated. + * + * (sourcelen) is the length of the string pointed to by (source), in bytes. + * + * (defines) points to (define_count) preprocessor definitions, and can be + * NULL. These are treated by the preprocessor as if the source code started + * with one #define for each entry you pass in here. + * + * (include_open) and (include_close) let the app control the preprocessor's + * behaviour for #include statements. Both are optional and can be NULL, but + * both must be specified if either is specified. + * + * This will return a MOJOSHADER_compileData. The data supplied here is + * sufficient to supply to MOJOSHADER_assemble() for further processing. + * When you are done with this data, pass it to MOJOSHADER_freeCompileData() + * to deallocate resources. + * + * This function will never return NULL, even if the system is completely + * out of memory upon entry (in which case, this function returns a static + * MOJOSHADER_compileData object, which is still safe to pass to + * MOJOSHADER_freeCompileData()). + * + * As compiling requires some memory to be allocated, you may provide a + * custom allocator to this function, which will be used to allocate/free + * memory. They function just like malloc() and free(). We do not use + * realloc(). If you don't care, pass NULL in for the allocator functions. + * If your allocator needs instance-specific data, you may supply it with the + * (d) parameter. This pointer is passed as-is to your (m) and (f) functions. + * + * This function is thread safe, so long as the various callback functions + * are, too, and that the parameters remains intact for the duration of the + * call. This allows you to compile several shaders on separate CPU cores + * at the same time. + */ +const MOJOSHADER_compileData *MOJOSHADER_compile(const char *srcprofile, + const char *filename, const char *source, + unsigned int sourcelen, + const MOJOSHADER_preprocessorDefine *defs, + unsigned int define_count, + MOJOSHADER_includeOpen include_open, + MOJOSHADER_includeClose include_close, + MOJOSHADER_malloc m, MOJOSHADER_free f, + void *d); + + /* OpenGL interface... */ /* diff --git a/mojoshader_compiler.c b/mojoshader_compiler.c index 11d4c1c8..ee8f2900 100644 --- a/mojoshader_compiler.c +++ b/mojoshader_compiler.c @@ -34,527 +34,31 @@ } \ } -typedef union TokenData +static inline int operator_is_unary(const MOJOSHADER_astNodeType op) { - int64 i64; - double dbl; - const char *string; -} TokenData; - - -// Structures that make up the parse tree... - -typedef enum ASTNodeType -{ - AST_OP_START_RANGE, - AST_OP_START_RANGE_UNARY, - AST_OP_POSTINCREMENT, - AST_OP_POSTDECREMENT, - AST_OP_PREINCREMENT, - AST_OP_PREDECREMENT, - AST_OP_NEGATE, - AST_OP_COMPLEMENT, - AST_OP_NOT, - AST_OP_END_RANGE_UNARY, - - AST_OP_START_RANGE_BINARY, - AST_OP_DEREF_ARRAY, - AST_OP_COMMA, - AST_OP_MULTIPLY, - AST_OP_DIVIDE, - AST_OP_MODULO, - AST_OP_ADD, - AST_OP_SUBTRACT, - AST_OP_LSHIFT, - AST_OP_RSHIFT, - AST_OP_LESSTHAN, - AST_OP_GREATERTHAN, - AST_OP_LESSTHANOREQUAL, - AST_OP_GREATERTHANOREQUAL, - AST_OP_EQUAL, - AST_OP_NOTEQUAL, - AST_OP_BINARYAND, - AST_OP_BINARYXOR, - AST_OP_BINARYOR, - AST_OP_LOGICALAND, - AST_OP_LOGICALOR, - AST_OP_ASSIGN, - AST_OP_MULASSIGN, - AST_OP_DIVASSIGN, - AST_OP_MODASSIGN, - AST_OP_ADDASSIGN, - AST_OP_SUBASSIGN, - AST_OP_LSHIFTASSIGN, - AST_OP_RSHIFTASSIGN, - AST_OP_ANDASSIGN, - AST_OP_XORASSIGN, - AST_OP_ORASSIGN, - AST_OP_END_RANGE_BINARY, - - AST_OP_START_RANGE_TERNARY, - AST_OP_CONDITIONAL, - AST_OP_END_RANGE_TERNARY, - - AST_OP_START_RANGE_DATA, - AST_OP_IDENTIFIER, - AST_OP_INT_LITERAL, - AST_OP_FLOAT_LITERAL, - AST_OP_STRING_LITERAL, - AST_OP_BOOLEAN_LITERAL, - AST_OP_END_RANGE_DATA, - - AST_OP_START_RANGE_MISC, - AST_OP_DEREF_STRUCT, - AST_OP_CALLFUNC, - AST_OP_CONSTRUCTOR, - AST_OP_CAST, - AST_OP_END_RANGE_MISC, - AST_OP_END_RANGE, - - AST_COMPUNIT_START_RANGE, - AST_COMPUNIT_FUNCTION, // function declaration or definition - AST_COMPUNIT_TYPEDEF, // typedef or struct - AST_COMPUNIT_STRUCT, // global struct - AST_COMPUNIT_VARIABLE, // global variable - AST_COMPUNIT_END_RANGE, - - AST_STATEMENT_START_RANGE, - AST_STATEMENT_BLOCK, - AST_STATEMENT_EMPTY, - AST_STATEMENT_EXPRESSION, - AST_STATEMENT_IF, - AST_STATEMENT_SWITCH, - AST_STATEMENT_FOR, - AST_STATEMENT_DO, - AST_STATEMENT_WHILE, - AST_STATEMENT_RETURN, - AST_STATEMENT_BREAK, - AST_STATEMENT_CONTINUE, - AST_STATEMENT_DISCARD, - AST_STATEMENT_TYPEDEF, - AST_STATEMENT_STRUCT, - AST_STATEMENT_VARDECL, - AST_STATEMENT_END_RANGE, - - AST_MISC_START_RANGE, - AST_FUNCTION_PARAMS, - AST_FUNCTION_SIGNATURE, - AST_SCALAR_OR_ARRAY, - AST_TYPEDEF, - AST_PACK_OFFSET, - AST_VARIABLE_LOWLEVEL, - AST_ANNOTATION, - AST_VARIABLE_DECLARATION, - AST_STRUCT_DECLARATION, - AST_STRUCT_MEMBER, - AST_SWITCH_CASE, - AST_ARGUMENTS, - AST_MISC_END_RANGE, - - AST_END_RANGE -} ASTNodeType; - -typedef struct ASTNode -{ - ASTNodeType type; - const char *filename; - uint32 line; -} ASTNode; - -typedef enum VariableAttributes -{ - VARATTR_EXTERN = (1 << 0), - VARATTR_NOINTERPOLATION = (1 << 1), - VARATTR_SHARED = (1 << 2), - VARATTR_STATIC = (1 << 3), - VARATTR_UNIFORM = (1 << 4), - VARATTR_VOLATILE = (1 << 5), - VARATTR_CONST = (1 << 6), - VARATTR_ROWMAJOR = (1 << 7), - VARATTR_COLUMNMAJOR = (1 << 8) -} VariableAttributes; - -typedef enum IfAttributes -{ - IFATTR_NONE, - IFATTR_BRANCH, - IFATTR_FLATTEN, - IFATTR_IFALL, - IFATTR_IFANY, - IFATTR_PREDICATE, - IFATTR_PREDICATEBLOCK, -} IfAttributes; - -typedef enum SwitchAttributes -{ - SWITCHATTR_NONE, - SWITCHATTR_FLATTEN, - SWITCHATTR_BRANCH, - SWITCHATTR_FORCECASE, - SWITCHATTR_CALL -} SwitchAttributes; - -static inline int operator_is_unary(const ASTNodeType op) -{ - return ((op > AST_OP_START_RANGE_UNARY) && (op < AST_OP_END_RANGE_UNARY)); + return ( (op > MOJOSHADER_AST_OP_START_RANGE_UNARY) && + (op < MOJOSHADER_AST_OP_END_RANGE_UNARY) ); } // operator_is_unary -static inline int operator_is_binary(const ASTNodeType op) +static inline int operator_is_binary(const MOJOSHADER_astNodeType op) { - return ((op > AST_OP_START_RANGE_BINARY) && (op < AST_OP_END_RANGE_BINARY)); + return ( (op > MOJOSHADER_AST_OP_START_RANGE_BINARY) && + (op < MOJOSHADER_AST_OP_END_RANGE_BINARY) ); } // operator_is_binary -static inline int operator_is_ternary(const ASTNodeType op) +static inline int operator_is_ternary(const MOJOSHADER_astNodeType op) { - return ((op > AST_OP_START_RANGE_TERNARY) && (op < AST_OP_END_RANGE_TERNARY)); + return ( (op > MOJOSHADER_AST_OP_START_RANGE_TERNARY) && + (op < MOJOSHADER_AST_OP_END_RANGE_TERNARY) ); } // operator_is_ternary -typedef struct ASTGeneric -{ - ASTNode ast; -} ASTGeneric; - -typedef ASTGeneric Expression; - -typedef struct Arguments -{ - ASTNode ast; // Always AST_ARGUMENTS - Expression *argument; - struct Arguments *next; -} Arguments; - -typedef struct ExpressionUnary -{ - ASTNode ast; - Expression *operand; -} ExpressionUnary; - -typedef struct ExpressionBinary -{ - ASTNode ast; - Expression *left; - Expression *right; -} ExpressionBinary; -typedef struct ExpressionTernary -{ - ASTNode ast; - Expression *left; - Expression *center; - Expression *right; -} ExpressionTernary; - -typedef struct ExpressionIdentifier -{ - ASTNode ast; // Always AST_OP_IDENTIFIER - const char *identifier; -} ExpressionIdentifier; - -typedef struct ExpressionIntLiteral -{ - ASTNode ast; // Always AST_OP_INT_LITERAL - int64 value; -} ExpressionIntLiteral; - -typedef struct ExpressionFloatLiteral -{ - ASTNode ast; // Always AST_OP_FLOAT_LITERAL - double value; -} ExpressionFloatLiteral; - -typedef struct ExpressionStringLiteral +typedef union TokenData { - ASTNode ast; // Always AST_OP_STRING_LITERAL + int64 i64; + double dbl; const char *string; -} ExpressionStringLiteral; - -typedef struct ExpressionBooleanLiteral -{ - ASTNode ast; // Always AST_OP_BOOLEAN_LITERAL - int value; // Always 1 or 0. -} ExpressionBooleanLiteral; - -typedef struct ExpressionConstructor -{ - ASTNode ast; // Always AST_OP_CONSTRUCTOR - const char *datatype; - Arguments *args; -} ExpressionConstructor; - -typedef struct ExpressionDerefStruct -{ - ASTNode ast; // Always AST_OP_DEREF_STRUCT - Expression *identifier; - const char *member; -} ExpressionDerefStruct; - -typedef struct ExpressionCallFunction -{ - ASTNode ast; // Always AST_OP_CALLFUNC - Expression *identifier; - Arguments *args; -} ExpressionCallFunction; - -typedef struct ExpressionCast -{ - ASTNode ast; // Always AST_OP_CAST - const char *datatype; - Expression *operand; -} ExpressionCast; - -typedef struct CompilationUnit -{ - ASTNode ast; - struct CompilationUnit *next; -} CompilationUnit; - -typedef enum FunctionStorageClass -{ - FNSTORECLS_NONE, - FNSTORECLS_INLINE -} FunctionStorageClass; - -typedef enum InputModifier -{ - INPUTMOD_NONE, - INPUTMOD_IN, - INPUTMOD_OUT, - INPUTMOD_INOUT, - INPUTMOD_UNIFORM -} InputModifier; - -typedef enum InterpolationModifier -{ - INTERPMOD_NONE, - INTERPMOD_LINEAR, - INTERPMOD_CENTROID, - INTERPMOD_NOINTERPOLATION, - INTERPMOD_NOPERSPECTIVE, - INTERPMOD_SAMPLE -} InterpolationModifier; - -typedef struct FunctionParameters -{ - ASTNode ast; - InputModifier input_modifier; - const char *datatype; - const char *identifier; - const char *semantic; - InterpolationModifier interpolation_modifier; - Expression *initializer; - struct FunctionParameters *next; -} FunctionParameters; - -typedef struct FunctionSignature -{ - ASTNode ast; - const char *datatype; - const char *identifier; - FunctionParameters *params; - FunctionStorageClass storage_class; - const char *semantic; -} FunctionSignature; - -typedef struct ScalarOrArray -{ - ASTNode ast; - const char *identifier; - int isarray; - Expression *dimension; -} ScalarOrArray; - -typedef struct Annotations -{ - ASTNode ast; - const char *datatype; - Expression *initializer; - struct Annotations *next; -} Annotations; - -typedef struct PackOffset -{ - ASTNode ast; - const char *ident1; // !!! FIXME: rename this. - const char *ident2; -} PackOffset; - -typedef struct VariableLowLevel -{ - ASTNode ast; - PackOffset *packoffset; - const char *register_name; -} VariableLowLevel; - -typedef struct StructMembers -{ - ASTNode ast; - const char *datatype; - const char *semantic; - ScalarOrArray *details; - InterpolationModifier interpolation_mod; - struct StructMembers *next; -} StructMembers; - -typedef struct StructDeclaration -{ - ASTNode ast; - const char *name; - StructMembers *members; -} StructDeclaration; - -typedef struct VariableDeclaration -{ - ASTNode ast; - int attributes; - const char *datatype; - StructDeclaration *anonymous_datatype; - ScalarOrArray *details; - const char *semantic; - Annotations *annotations; - Expression *initializer; - VariableLowLevel *lowlevel; - struct VariableDeclaration *next; -} VariableDeclaration; - -typedef struct Statement -{ - ASTNode ast; - struct Statement *next; -} Statement; - -typedef Statement EmptyStatement; -typedef Statement BreakStatement; -typedef Statement ContinueStatement; -typedef Statement DiscardStatement; - -typedef struct BlockStatement // something enclosed in "{}" braces. -{ - ASTNode ast; - struct Statement *next; - Statement *statements; // list of statements enclosed by this block. -} BlockStatement; - -typedef struct ReturnStatement -{ - ASTNode ast; - struct Statement *next; - Expression *expr; -} ReturnStatement; - -typedef struct ExpressionStatement -{ - ASTNode ast; - struct Statement *next; - Expression *expr; -} ExpressionStatement; - -typedef struct IfStatement -{ - ASTNode ast; - struct Statement *next; - int attributes; - Expression *expr; - Statement *statement; - Statement *else_statement; -} IfStatement; - -typedef struct SwitchCases -{ - ASTNode ast; - Expression *expr; - Statement *statement; - struct SwitchCases *next; -} SwitchCases; - -typedef struct SwitchStatement -{ - ASTNode ast; - struct Statement *next; - int attributes; - Expression *expr; - SwitchCases *cases; -} SwitchStatement; - -typedef struct WhileStatement -{ - ASTNode ast; - struct Statement *next; - int64 unroll; // # times to unroll, 0 to loop, negative for compiler's choice. - Expression *expr; - Statement *statement; -} WhileStatement; - -typedef WhileStatement DoStatement; - -typedef struct ForStatement -{ - ASTNode ast; - struct Statement *next; - int64 unroll; // # times to unroll, 0 to loop, negative for compiler's choice. - VariableDeclaration *var_decl; - Expression *initializer; - Expression *looptest; - Expression *counter; - Statement *statement; -} ForStatement; - -typedef struct Typedef -{ - ASTNode ast; - int isconst; - const char *datatype; - ScalarOrArray *details; -} Typedef; - -typedef struct TypedefStatement -{ - ASTNode ast; - struct Statement *next; - Typedef *type_info; -} TypedefStatement; - -typedef struct VarDeclStatement -{ - ASTNode ast; - struct Statement *next; - VariableDeclaration *declaration; -} VarDeclStatement; - -typedef struct StructStatement -{ - ASTNode ast; - struct Statement *next; - StructDeclaration *struct_info; -} StructStatement; - -typedef struct CompilationUnitFunction -{ - ASTNode ast; - struct CompilationUnit *next; - FunctionSignature *declaration; - Statement *definition; -} CompilationUnitFunction; - -typedef struct CompilationUnitTypedef -{ - ASTNode ast; - struct CompilationUnit *next; - Typedef *type_info; -} CompilationUnitTypedef; - -typedef struct CompilationUnitStruct -{ - ASTNode ast; - struct CompilationUnit *next; - StructDeclaration *struct_info; -} CompilationUnitStruct; - -typedef struct CompilationUnitVariable -{ - ASTNode ast; - struct CompilationUnit *next; - VariableDeclaration *declaration; -} CompilationUnitVariable; +} TokenData; // This tracks data types and variables, and notes when they enter/leave scope. @@ -589,7 +93,7 @@ typedef struct Context unsigned int sourceline; // current line in sourcefile that we're parsing. SymbolMap usertypes; SymbolMap variables; - CompilationUnit *ast; // Abstract Syntax Tree + MOJOSHADER_astNode *ast; // Abstract Syntax Tree // These are entries allocated in the strcache, so these pointers are // valid from shortly after we create the cache until we destroy it @@ -787,150 +291,170 @@ static void destroy_symbolmap(Context *ctx, SymbolMap *map) if (!cls) return; \ } while (0) -static void delete_compilation_unit(Context *ctx, CompilationUnit *unit); -static void delete_statement(Context *ctx, Statement *stmt); +static void delete_compilation_unit(Context*, MOJOSHADER_astCompilationUnit*); +static void delete_statement(Context *ctx, MOJOSHADER_astStatement *stmt); -static Expression *new_callfunc_expr(Context *ctx, Expression *identifier, - Arguments *args) +static MOJOSHADER_astExpression *new_callfunc_expr(Context *ctx, + MOJOSHADER_astExpression *identifier, + MOJOSHADER_astArguments *args) { - NEW_AST_NODE(retval, ExpressionCallFunction, AST_OP_CALLFUNC); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionCallFunction, + MOJOSHADER_AST_OP_CALLFUNC); retval->identifier = identifier; retval->args = args; - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_callfunc_expr -static Expression *new_constructor_expr(Context *ctx, const char *datatype, - Arguments *args) +static MOJOSHADER_astExpression *new_constructor_expr(Context *ctx, + const char *datatype, + MOJOSHADER_astArguments *args) { - NEW_AST_NODE(retval, ExpressionConstructor, AST_OP_CONSTRUCTOR); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionConstructor, + MOJOSHADER_AST_OP_CONSTRUCTOR); retval->datatype = datatype; retval->args = args; - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_constructor_expr -static Expression *new_cast_expr(Context *ctx, const char *datatype, - Expression *operand) +static MOJOSHADER_astExpression *new_cast_expr(Context *ctx, + const char *datatype, + MOJOSHADER_astExpression *operand) { - NEW_AST_NODE(retval, ExpressionCast, AST_OP_CAST); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionCast, MOJOSHADER_AST_OP_CAST); retval->datatype = datatype; retval->operand = operand; - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_cast_expr -static Expression *new_unary_expr(Context *ctx, const ASTNodeType op, - Expression *operand) +static MOJOSHADER_astExpression *new_unary_expr(Context *ctx, + const MOJOSHADER_astNodeType op, + MOJOSHADER_astExpression *operand) { - NEW_AST_NODE(retval, ExpressionUnary, op); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionUnary, op); assert(operator_is_unary(op)); retval->operand = operand; - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_unary_expr -static Expression *new_binary_expr(Context *ctx, const ASTNodeType op, - Expression *left, Expression *right) +static MOJOSHADER_astExpression *new_binary_expr(Context *ctx, + const MOJOSHADER_astNodeType op, + MOJOSHADER_astExpression *left, + MOJOSHADER_astExpression *right) { - NEW_AST_NODE(retval, ExpressionBinary, op); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionBinary, op); assert(operator_is_binary(op)); retval->left = left; retval->right = right; - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_binary_expr -static Expression *new_ternary_expr(Context *ctx, const ASTNodeType op, - Expression *left, Expression *center, - Expression *right) +static MOJOSHADER_astExpression *new_ternary_expr(Context *ctx, + const MOJOSHADER_astNodeType op, + MOJOSHADER_astExpression *left, + MOJOSHADER_astExpression *center, + MOJOSHADER_astExpression *right) { - NEW_AST_NODE(retval, ExpressionTernary, op); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionTernary, op); assert(operator_is_ternary(op)); retval->left = left; retval->center = center; retval->right = right; - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_ternary_expr -static Expression *new_deref_struct_expr(Context *ctx, Expression *identifier, - const char *member) +static MOJOSHADER_astExpression *new_deref_struct_expr(Context *ctx, + MOJOSHADER_astExpression *identifier, + const char *member) { - NEW_AST_NODE(retval, ExpressionDerefStruct, AST_OP_DEREF_STRUCT); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionDerefStruct, + MOJOSHADER_AST_OP_DEREF_STRUCT); retval->identifier = identifier; retval->member = member; // cached; don't copy string. - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_deref_struct_expr -static Expression *new_identifier_expr(Context *ctx, const char *string) +static MOJOSHADER_astExpression *new_identifier_expr(Context *ctx, + const char *string) { - NEW_AST_NODE(retval, ExpressionIdentifier, AST_OP_IDENTIFIER); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionIdentifier, + MOJOSHADER_AST_OP_IDENTIFIER); retval->identifier = string; // cached; don't copy string. - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_identifier_expr -static Expression *new_literal_int_expr(Context *ctx, const int64 value) +static MOJOSHADER_astExpression *new_literal_int_expr(Context *ctx, + const int value) { - NEW_AST_NODE(retval, ExpressionIntLiteral, AST_OP_INT_LITERAL); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionIntLiteral, + MOJOSHADER_AST_OP_INT_LITERAL); retval->value = value; - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_literal_int_expr -static Expression *new_literal_float_expr(Context *ctx, const double dbl) +static MOJOSHADER_astExpression *new_literal_float_expr(Context *ctx, + const double dbl) { - NEW_AST_NODE(retval, ExpressionFloatLiteral, AST_OP_FLOAT_LITERAL); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionFloatLiteral, + MOJOSHADER_AST_OP_FLOAT_LITERAL); retval->value = dbl; - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_literal_float_expr -static Expression *new_literal_string_expr(Context *ctx, const char *string) +static MOJOSHADER_astExpression *new_literal_string_expr(Context *ctx, + const char *string) { - NEW_AST_NODE(retval, ExpressionStringLiteral, AST_OP_STRING_LITERAL); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionStringLiteral, + MOJOSHADER_AST_OP_STRING_LITERAL); retval->string = string; // cached; don't copy string. - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_literal_string_expr -static Expression *new_literal_boolean_expr(Context *ctx, const int value) +static MOJOSHADER_astExpression *new_literal_boolean_expr(Context *ctx, + const int value) { - NEW_AST_NODE(retval, ExpressionBooleanLiteral, AST_OP_BOOLEAN_LITERAL); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionBooleanLiteral, + MOJOSHADER_AST_OP_BOOLEAN_LITERAL); retval->value = value; - return (Expression *) retval; + return (MOJOSHADER_astExpression *) retval; } // new_literal_boolean_expr -static void delete_arguments(Context *ctx, Arguments *args); +static void delete_arguments(Context *ctx, MOJOSHADER_astArguments *args); -static void delete_expr(Context *ctx, Expression *expr) +static void delete_expr(Context *ctx, MOJOSHADER_astExpression *_expr) { + MOJOSHADER_astNode *expr = (MOJOSHADER_astNode *) _expr; + DELETE_AST_NODE(expr); - if (operator_is_unary(expr->ast.type)) - { - const ExpressionUnary *unary = (const ExpressionUnary *) expr; - delete_expr(ctx, unary->operand); - } // if + + if (expr->ast.type == MOJOSHADER_AST_OP_CAST) + delete_expr(ctx, expr->cast.operand); + + else if (expr->ast.type == MOJOSHADER_AST_OP_CONSTRUCTOR) + delete_arguments(ctx, expr->constructor.args); + + else if (expr->ast.type == MOJOSHADER_AST_OP_DEREF_STRUCT) + delete_expr(ctx, expr->derefstruct.identifier); + + else if (operator_is_unary(expr->ast.type)) + delete_expr(ctx, expr->unary.operand); + else if (operator_is_binary(expr->ast.type)) { - const ExpressionBinary *binary = (const ExpressionBinary *) expr; - delete_expr(ctx, binary->left); - delete_expr(ctx, binary->right); + delete_expr(ctx, expr->binary.left); + delete_expr(ctx, expr->binary.right); } // else if + else if (operator_is_ternary(expr->ast.type)) { - const ExpressionTernary *ternary = (const ExpressionTernary *) expr; - delete_expr(ctx, ternary->left); - delete_expr(ctx, ternary->center); - delete_expr(ctx, ternary->right); - } // else if - else if (expr->ast.type == AST_OP_CAST) - { - delete_expr(ctx, ((ExpressionCast *) expr)->operand); - } // else if - else if (expr->ast.type == AST_OP_CONSTRUCTOR) - { - delete_arguments(ctx, ((ExpressionConstructor *) expr)->args); - } // else if - else if (expr->ast.type == AST_OP_DEREF_STRUCT) - { - delete_expr(ctx, ((ExpressionDerefStruct *) expr)->identifier); + delete_expr(ctx, expr->ternary.left); + delete_expr(ctx, expr->ternary.center); + delete_expr(ctx, expr->ternary.right); } // else if - else if (expr->ast.type == AST_OP_CALLFUNC) + + else if (expr->ast.type == MOJOSHADER_AST_OP_CALLFUNC) { - delete_expr(ctx, ((ExpressionCallFunction *) expr)->identifier); - delete_arguments(ctx, ((ExpressionCallFunction *) expr)->args); + delete_expr(ctx, expr->callfunc.identifier); + delete_arguments(ctx, expr->callfunc.args); } // else if // rest of operators don't have extra data to free. @@ -938,15 +462,16 @@ static void delete_expr(Context *ctx, Expression *expr) Free(ctx, expr); } // delete_expr -static Arguments *new_argument(Context *ctx, Expression *argument) +static MOJOSHADER_astArguments *new_argument(Context *ctx, + MOJOSHADER_astExpression *arg) { - NEW_AST_NODE(retval, Arguments, AST_ARGUMENTS); - retval->argument = argument; + NEW_AST_NODE(retval, MOJOSHADER_astArguments, MOJOSHADER_AST_ARGUMENTS); + retval->argument = arg; retval->next = NULL; return retval; } // new_argument -static void delete_arguments(Context *ctx, Arguments *args) +static void delete_arguments(Context *ctx, MOJOSHADER_astArguments *args) { DELETE_AST_NODE(args); delete_arguments(ctx, args->next); @@ -954,15 +479,15 @@ static void delete_arguments(Context *ctx, Arguments *args) Free(ctx, args); } // delete_arguments -static FunctionParameters *new_function_param(Context *ctx, - const InputModifier inputmod, - const char *datatype, - const char *identifier, - const char *semantic, - const InterpolationModifier interpmod, - Expression *initializer) +static MOJOSHADER_astFunctionParameters *new_function_param(Context *ctx, + const MOJOSHADER_astInputModifier inputmod, + const char *datatype, const char *identifier, + const char *semantic, + const MOJOSHADER_astInterpolationModifier interpmod, + MOJOSHADER_astExpression *initializer) { - NEW_AST_NODE(retval, FunctionParameters, AST_FUNCTION_PARAMS); + NEW_AST_NODE(retval, MOJOSHADER_astFunctionParameters, + MOJOSHADER_AST_FUNCTION_PARAMS); retval->input_modifier = inputmod; retval->datatype = datatype; retval->identifier = identifier; @@ -973,7 +498,8 @@ static FunctionParameters *new_function_param(Context *ctx, return retval; } // new_function_param -static void delete_function_params(Context *ctx, FunctionParameters *params) +static void delete_function_params(Context *ctx, + MOJOSHADER_astFunctionParameters *params) { DELETE_AST_NODE(params); delete_function_params(ctx, params->next); @@ -981,39 +507,43 @@ static void delete_function_params(Context *ctx, FunctionParameters *params) Free(ctx, params); } // delete_function_params -static FunctionSignature *new_function_signature(Context *ctx, - const char *datatype, - const char *identifier, - FunctionParameters *params) +static MOJOSHADER_astFunctionSignature *new_function_signature(Context *ctx, + const char *datatype, + const char *identifier, + MOJOSHADER_astFunctionParameters *params) { - NEW_AST_NODE(retval, FunctionSignature, AST_FUNCTION_SIGNATURE); + NEW_AST_NODE(retval, MOJOSHADER_astFunctionSignature, + MOJOSHADER_AST_FUNCTION_SIGNATURE); retval->datatype = datatype; retval->identifier = identifier; retval->params = params; - retval->storage_class = FNSTORECLS_NONE; + retval->storage_class = MOJOSHADER_AST_FNSTORECLS_NONE; retval->semantic = NULL; return retval; } // new_function_signature -static void delete_function_signature(Context *ctx, FunctionSignature *sig) +static void delete_function_signature(Context *ctx, + MOJOSHADER_astFunctionSignature *sig) { DELETE_AST_NODE(sig); delete_function_params(ctx, sig->params); Free(ctx, sig); } // delete_function_signature -static CompilationUnit *new_function(Context *ctx, - FunctionSignature *declaration, - Statement *definition) +static MOJOSHADER_astCompilationUnit *new_function(Context *ctx, + MOJOSHADER_astFunctionSignature *declaration, + MOJOSHADER_astStatement *definition) { - NEW_AST_NODE(retval, CompilationUnitFunction, AST_COMPUNIT_FUNCTION); + NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitFunction, + MOJOSHADER_AST_COMPUNIT_FUNCTION); retval->next = NULL; retval->declaration = declaration; retval->definition = definition; - return (CompilationUnit *) retval; + return (MOJOSHADER_astCompilationUnit *) retval; } // new_function -static void delete_function(Context *ctx, CompilationUnitFunction *unitfn) +static void delete_function(Context *ctx, + MOJOSHADER_astCompilationUnitFunction *unitfn) { DELETE_AST_NODE(unitfn); delete_compilation_unit(ctx, unitfn->next); @@ -1022,95 +552,106 @@ static void delete_function(Context *ctx, CompilationUnitFunction *unitfn) Free(ctx, unitfn); } // delete_function -static ScalarOrArray *new_scalar_or_array(Context *ctx, const char *ident, - const int isvec, Expression *dim) +static MOJOSHADER_astScalarOrArray *new_scalar_or_array(Context *ctx, + const char *ident, const int isvec, + MOJOSHADER_astExpression *dim) { - NEW_AST_NODE(retval, ScalarOrArray, AST_SCALAR_OR_ARRAY); + NEW_AST_NODE(retval, MOJOSHADER_astScalarOrArray, + MOJOSHADER_AST_SCALAR_OR_ARRAY); retval->identifier = ident; retval->isarray = isvec; retval->dimension = dim; return retval; } // new_scalar_or_array -static void delete_scalar_or_array(Context *ctx, ScalarOrArray *soa) +static void delete_scalar_or_array(Context *ctx,MOJOSHADER_astScalarOrArray *s) { - DELETE_AST_NODE(soa); - delete_expr(ctx, soa->dimension); - Free(ctx, soa); + DELETE_AST_NODE(s); + delete_expr(ctx, s->dimension); + Free(ctx, s); } // delete_scalar_or_array -static Typedef *new_typedef(Context *ctx, int isconst, const char *datatype, - ScalarOrArray *soa) +static MOJOSHADER_astTypedef *new_typedef(Context *ctx, const int isconst, + const char *datatype, + MOJOSHADER_astScalarOrArray *soa) { // we correct this datatype to the final string during semantic analysis. - NEW_AST_NODE(retval, Typedef, AST_TYPEDEF); + NEW_AST_NODE(retval, MOJOSHADER_astTypedef, MOJOSHADER_AST_TYPEDEF); retval->isconst = isconst; retval->datatype = datatype; retval->details = soa; return retval; } // new_typedef -static void delete_typedef(Context *ctx, Typedef *td) +static void delete_typedef(Context *ctx, MOJOSHADER_astTypedef *td) { DELETE_AST_NODE(td); delete_scalar_or_array(ctx, td->details); Free(ctx, td); } // delete_typedef -static PackOffset *new_pack_offset(Context *ctx, const char *a, const char *b) +static MOJOSHADER_astPackOffset *new_pack_offset(Context *ctx, + const char *a, const char *b) { - NEW_AST_NODE(retval, PackOffset, AST_PACK_OFFSET); + NEW_AST_NODE(retval, MOJOSHADER_astPackOffset, MOJOSHADER_AST_PACK_OFFSET); retval->ident1 = a; retval->ident2 = b; return retval; } // new_pack_offset -static void delete_pack_offset(Context *ctx, PackOffset *o) +static void delete_pack_offset(Context *ctx, MOJOSHADER_astPackOffset *o) { DELETE_AST_NODE(o); Free(ctx, o); } // delete_pack_offset -static VariableLowLevel *new_variable_lowlevel(Context *ctx, PackOffset *po, +static MOJOSHADER_astVariableLowLevel *new_variable_lowlevel(Context *ctx, + MOJOSHADER_astPackOffset *po, const char *reg) { - NEW_AST_NODE(retval, VariableLowLevel, AST_VARIABLE_LOWLEVEL); + NEW_AST_NODE(retval, MOJOSHADER_astVariableLowLevel, + MOJOSHADER_AST_VARIABLE_LOWLEVEL); retval->packoffset = po; retval->register_name = reg; return retval; } // new_variable_lowlevel -static void delete_variable_lowlevel(Context *ctx, VariableLowLevel *vll) +static void delete_variable_lowlevel(Context *ctx, + MOJOSHADER_astVariableLowLevel *vll) { DELETE_AST_NODE(vll); delete_pack_offset(ctx, vll->packoffset); Free(ctx, vll); } // delete_variable_lowlevel -static Annotations *new_annotation(Context *ctx, const char *datatype, - Expression *initializer) +static MOJOSHADER_astAnnotations *new_annotation(Context *ctx, + const char *datatype, + MOJOSHADER_astExpression *initializer) { - NEW_AST_NODE(retval, Annotations, AST_ANNOTATION); + NEW_AST_NODE(retval, MOJOSHADER_astAnnotations, MOJOSHADER_AST_ANNOTATION); retval->datatype = datatype; retval->initializer = initializer; retval->next = NULL; return retval; } // new_annotation -static void delete_annotation(Context *ctx, Annotations *annotations) +static void delete_annotation(Context *ctx, MOJOSHADER_astAnnotations *annos) { - DELETE_AST_NODE(annotations); - delete_annotation(ctx, annotations->next); - delete_expr(ctx, annotations->initializer); - Free(ctx, annotations); + DELETE_AST_NODE(annos); + delete_annotation(ctx, annos->next); + delete_expr(ctx, annos->initializer); + Free(ctx, annos); } // delete_annotation -static VariableDeclaration *new_variable_declaration(Context *ctx, - ScalarOrArray *soa, const char *semantic, - Annotations *annotations, Expression *init, - VariableLowLevel *vll) +static MOJOSHADER_astVariableDeclaration *new_variable_declaration( + Context *ctx, MOJOSHADER_astScalarOrArray *soa, + const char *semantic, + MOJOSHADER_astAnnotations *annotations, + MOJOSHADER_astExpression *init, + MOJOSHADER_astVariableLowLevel *vll) { - NEW_AST_NODE(retval, VariableDeclaration, AST_VARIABLE_DECLARATION); + NEW_AST_NODE(retval, MOJOSHADER_astVariableDeclaration, + MOJOSHADER_AST_VARIABLE_DECLARATION); retval->attributes = 0; retval->datatype = NULL; retval->anonymous_datatype = NULL; @@ -1123,7 +664,8 @@ static VariableDeclaration *new_variable_declaration(Context *ctx, return retval; } // new_variable_declaration -static void delete_variable_declaration(Context *ctx, VariableDeclaration *dcl) +static void delete_variable_declaration(Context *ctx, + MOJOSHADER_astVariableDeclaration *dcl) { DELETE_AST_NODE(dcl); delete_variable_declaration(ctx, dcl->next); @@ -1134,16 +676,18 @@ static void delete_variable_declaration(Context *ctx, VariableDeclaration *dcl) Free(ctx, dcl); } // delete_variable_declaration -static CompilationUnit *new_global_variable(Context *ctx, - VariableDeclaration *decl) +static MOJOSHADER_astCompilationUnit *new_global_variable(Context *ctx, + MOJOSHADER_astVariableDeclaration *decl) { - NEW_AST_NODE(retval, CompilationUnitVariable, AST_COMPUNIT_VARIABLE); + NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitVariable, + MOJOSHADER_AST_COMPUNIT_VARIABLE); retval->next = NULL; retval->declaration = decl; - return (CompilationUnit *) retval; + return (MOJOSHADER_astCompilationUnit *) retval; } // new_global_variable -static void delete_global_variable(Context *ctx, CompilationUnitVariable *var) +static void delete_global_variable(Context *ctx, + MOJOSHADER_astCompilationUnitVariable *var) { DELETE_AST_NODE(var); delete_compilation_unit(ctx, var->next); @@ -1151,15 +695,18 @@ static void delete_global_variable(Context *ctx, CompilationUnitVariable *var) Free(ctx, var); } // delete_global_variable -static CompilationUnit *new_global_typedef(Context *ctx, Typedef *td) +static MOJOSHADER_astCompilationUnit *new_global_typedef(Context *ctx, + MOJOSHADER_astTypedef *td) { - NEW_AST_NODE(retval, CompilationUnitTypedef, AST_COMPUNIT_TYPEDEF); + NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitTypedef, + MOJOSHADER_AST_COMPUNIT_TYPEDEF); retval->next = NULL; retval->type_info = td; - return (CompilationUnit *) retval; + return (MOJOSHADER_astCompilationUnit *) retval; } // new_global_typedef -static void delete_global_typedef(Context *ctx, CompilationUnitTypedef *unit) +static void delete_global_typedef(Context *ctx, + MOJOSHADER_astCompilationUnitTypedef *unit) { DELETE_AST_NODE(unit); delete_compilation_unit(ctx, unit->next); @@ -1167,19 +714,22 @@ static void delete_global_typedef(Context *ctx, CompilationUnitTypedef *unit) Free(ctx, unit); } // delete_global_typedef -static StructMembers *new_struct_member(Context *ctx, ScalarOrArray *soa, - const char *semantic) +static MOJOSHADER_astStructMembers *new_struct_member(Context *ctx, + MOJOSHADER_astScalarOrArray *soa, + const char *semantic) { - NEW_AST_NODE(retval, StructMembers, AST_STRUCT_MEMBER); + NEW_AST_NODE(retval, MOJOSHADER_astStructMembers, + MOJOSHADER_AST_STRUCT_MEMBER); retval->datatype = NULL; retval->semantic = semantic; retval->details = soa; - retval->interpolation_mod = INTERPMOD_NONE; + retval->interpolation_mod = MOJOSHADER_AST_INTERPMOD_NONE; retval->next = NULL; return retval; } // new_struct_member -static void delete_struct_member(Context *ctx, StructMembers *member) +static void delete_struct_member(Context *ctx, + MOJOSHADER_astStructMembers *member) { DELETE_AST_NODE(member); delete_struct_member(ctx, member->next); @@ -1187,31 +737,37 @@ static void delete_struct_member(Context *ctx, StructMembers *member) Free(ctx, member); } // delete_struct_member -static StructDeclaration *new_struct_declaration(Context *ctx, - const char *name, StructMembers *members) +static MOJOSHADER_astStructDeclaration *new_struct_declaration(Context *ctx, + const char *name, + MOJOSHADER_astStructMembers *members) { - NEW_AST_NODE(retval, StructDeclaration, AST_STRUCT_DECLARATION); + NEW_AST_NODE(retval, MOJOSHADER_astStructDeclaration, + MOJOSHADER_AST_STRUCT_DECLARATION); retval->name = name; retval->members = members; return retval; } // new_struct_declaration -static void delete_struct_declaration(Context *ctx, StructDeclaration *decl) +static void delete_struct_declaration(Context *ctx, + MOJOSHADER_astStructDeclaration *decl) { DELETE_AST_NODE(decl); delete_struct_member(ctx, decl->members); Free(ctx, decl); } // delete_struct_declaration -static CompilationUnit *new_global_struct(Context *ctx, StructDeclaration *sd) +static MOJOSHADER_astCompilationUnit *new_global_struct(Context *ctx, + MOJOSHADER_astStructDeclaration *sd) { - NEW_AST_NODE(retval, CompilationUnitStruct, AST_COMPUNIT_STRUCT); + NEW_AST_NODE(retval, MOJOSHADER_astCompilationUnitStruct, + MOJOSHADER_AST_COMPUNIT_STRUCT); retval->next = NULL; retval->struct_info = sd; - return (CompilationUnit *) retval; + return (MOJOSHADER_astCompilationUnit *) retval; } // new_global_struct -static void delete_global_struct(Context *ctx, CompilationUnitStruct *unit) +static void delete_global_struct(Context *ctx, + MOJOSHADER_astCompilationUnitStruct *unit) { DELETE_AST_NODE(unit); delete_compilation_unit(ctx, unit->next); @@ -1219,7 +775,8 @@ static void delete_global_struct(Context *ctx, CompilationUnitStruct *unit) Free(ctx, unit); } // delete_global_struct -static void delete_compilation_unit(Context *ctx, CompilationUnit *unit) +static void delete_compilation_unit(Context *ctx, + MOJOSHADER_astCompilationUnit *unit) { if (!unit) return; @@ -1231,11 +788,11 @@ static void delete_compilation_unit(Context *ctx, CompilationUnit *unit) // Please note that everyone should _try_ to delete their "next" member, // just in case, but hopefully this cleaned it out. - CompilationUnit *i = unit->next; + MOJOSHADER_astCompilationUnit *i = unit->next; unit->next = NULL; while (i) { - CompilationUnit *next = i->next; + MOJOSHADER_astCompilationUnit *next = i->next; i->next = NULL; delete_compilation_unit(ctx, i); i = next; @@ -1244,11 +801,11 @@ static void delete_compilation_unit(Context *ctx, CompilationUnit *unit) switch (unit->ast.type) { #define DELETE_UNIT(typ, cls, fn) \ - case AST_COMPUNIT_##typ: delete_##fn(ctx, (cls *) unit); break; - DELETE_UNIT(FUNCTION, CompilationUnitFunction, function); - DELETE_UNIT(TYPEDEF, CompilationUnitTypedef, global_typedef); - DELETE_UNIT(VARIABLE, CompilationUnitVariable, global_variable); - DELETE_UNIT(STRUCT, CompilationUnitStruct, global_struct); + case MOJOSHADER_AST_COMPUNIT_##typ: delete_##fn(ctx, (cls *) unit); break; + DELETE_UNIT(FUNCTION, MOJOSHADER_astCompilationUnitFunction, function); + DELETE_UNIT(TYPEDEF, MOJOSHADER_astCompilationUnitTypedef, global_typedef); + DELETE_UNIT(VARIABLE, MOJOSHADER_astCompilationUnitVariable, global_variable); + DELETE_UNIT(STRUCT, MOJOSHADER_astCompilationUnitStruct, global_struct); #undef DELETE_UNIT default: assert(0 && "missing cleanup code"); break; } // switch @@ -1256,15 +813,18 @@ static void delete_compilation_unit(Context *ctx, CompilationUnit *unit) // don't free (unit) here, the class-specific functions do it. } // delete_compilation_unit -static Statement *new_typedef_statement(Context *ctx, Typedef *td) +static MOJOSHADER_astStatement *new_typedef_statement(Context *ctx, + MOJOSHADER_astTypedef *td) { - NEW_AST_NODE(retval, TypedefStatement, AST_STATEMENT_TYPEDEF); + NEW_AST_NODE(retval, MOJOSHADER_astTypedefStatement, + MOJOSHADER_AST_STATEMENT_TYPEDEF); retval->next = NULL; retval->type_info = td; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_typedef_statement -static void delete_typedef_statement(Context *ctx, TypedefStatement *stmt) +static void delete_typedef_statement(Context *ctx, + MOJOSHADER_astTypedefStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); @@ -1272,15 +832,18 @@ static void delete_typedef_statement(Context *ctx, TypedefStatement *stmt) Free(ctx, stmt); } // delete_typedef_statement -static Statement *new_return_statement(Context *ctx, Expression *expr) +static MOJOSHADER_astStatement *new_return_statement(Context *ctx, + MOJOSHADER_astExpression *expr) { - NEW_AST_NODE(retval, ReturnStatement, AST_STATEMENT_RETURN); + NEW_AST_NODE(retval, MOJOSHADER_astReturnStatement, + MOJOSHADER_AST_STATEMENT_RETURN); retval->next = NULL; retval->expr = expr; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_return_statement -static void delete_return_statement(Context *ctx, ReturnStatement *stmt) +static void delete_return_statement(Context *ctx, + MOJOSHADER_astReturnStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); @@ -1288,15 +851,18 @@ static void delete_return_statement(Context *ctx, ReturnStatement *stmt) Free(ctx, stmt); } // delete_return_statement -static Statement *new_block_statement(Context *ctx, Statement *statements) +static MOJOSHADER_astStatement *new_block_statement(Context *ctx, + MOJOSHADER_astStatement *stmts) { - NEW_AST_NODE(retval, BlockStatement, AST_STATEMENT_BLOCK); + NEW_AST_NODE(retval, MOJOSHADER_astBlockStatement, + MOJOSHADER_AST_STATEMENT_BLOCK); retval->next = NULL; - retval->statements = statements; - return (Statement *) retval; + retval->statements = stmts; + return (MOJOSHADER_astStatement *) retval; } // new_block_statement -static void delete_block_statement(Context *ctx, BlockStatement *stmt) +static void delete_block_statement(Context *ctx, + MOJOSHADER_astBlockStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->statements); @@ -1304,12 +870,15 @@ static void delete_block_statement(Context *ctx, BlockStatement *stmt) Free(ctx, stmt); } // delete_statement_block -static Statement *new_for_statement(Context *ctx, VariableDeclaration *decl, - Expression *initializer, - Expression *looptest, Expression *counter, - Statement *statement) +static MOJOSHADER_astStatement *new_for_statement(Context *ctx, + MOJOSHADER_astVariableDeclaration *decl, + MOJOSHADER_astExpression *initializer, + MOJOSHADER_astExpression *looptest, + MOJOSHADER_astExpression *counter, + MOJOSHADER_astStatement *statement) { - NEW_AST_NODE(retval, ForStatement, AST_STATEMENT_FOR); + NEW_AST_NODE(retval, MOJOSHADER_astForStatement, + MOJOSHADER_AST_STATEMENT_FOR); retval->next = NULL; retval->unroll = -1; retval->var_decl = decl; @@ -1317,10 +886,10 @@ static Statement *new_for_statement(Context *ctx, VariableDeclaration *decl, retval->looptest = looptest; retval->counter = counter; retval->statement = statement; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_for_statement -static void delete_for_statement(Context *ctx, ForStatement *stmt) +static void delete_for_statement(Context *ctx,MOJOSHADER_astForStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); @@ -1332,18 +901,20 @@ static void delete_for_statement(Context *ctx, ForStatement *stmt) Free(ctx, stmt); } // delete_for_statement -static Statement *new_do_statement(Context *ctx, int64 unroll, - Statement *stmt, Expression *expr) +static MOJOSHADER_astStatement *new_do_statement(Context *ctx, + const int unroll, + MOJOSHADER_astStatement *stmt, + MOJOSHADER_astExpression *expr) { - NEW_AST_NODE(retval, DoStatement, AST_STATEMENT_DO); + NEW_AST_NODE(retval,MOJOSHADER_astDoStatement,MOJOSHADER_AST_STATEMENT_DO); retval->next = NULL; retval->unroll = unroll; retval->expr = expr; retval->statement = stmt; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_do_statement -static void delete_do_statement(Context *ctx, DoStatement *stmt) +static void delete_do_statement(Context *ctx, MOJOSHADER_astDoStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); @@ -1352,18 +923,22 @@ static void delete_do_statement(Context *ctx, DoStatement *stmt) Free(ctx, stmt); } // delete_do_statement -static Statement *new_while_statement(Context *ctx, int64 unroll, - Expression *expr, Statement *stmt) +static MOJOSHADER_astStatement *new_while_statement(Context *ctx, + const int unroll, + MOJOSHADER_astExpression *expr, + MOJOSHADER_astStatement *stmt) { - NEW_AST_NODE(retval, WhileStatement, AST_STATEMENT_WHILE); + NEW_AST_NODE(retval, MOJOSHADER_astWhileStatement, + MOJOSHADER_AST_STATEMENT_WHILE); retval->next = NULL; retval->unroll = unroll; retval->expr = expr; retval->statement = stmt; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_while_statement -static void delete_while_statement(Context *ctx, WhileStatement *stmt) +static void delete_while_statement(Context *ctx, + MOJOSHADER_astWhileStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); @@ -1372,19 +947,22 @@ static void delete_while_statement(Context *ctx, WhileStatement *stmt) Free(ctx, stmt); } // delete_while_statement -static Statement *new_if_statement(Context *ctx, int attr, Expression *expr, - Statement *stmt, Statement *elsestmt) +static MOJOSHADER_astStatement *new_if_statement(Context *ctx, + const int attr, + MOJOSHADER_astExpression *expr, + MOJOSHADER_astStatement *stmt, + MOJOSHADER_astStatement *elsestmt) { - NEW_AST_NODE(retval, IfStatement, AST_STATEMENT_IF); + NEW_AST_NODE(retval,MOJOSHADER_astIfStatement,MOJOSHADER_AST_STATEMENT_IF); retval->next = NULL; retval->attributes = attr; retval->expr = expr; retval->statement = stmt; retval->else_statement = elsestmt; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_if_statement -static void delete_if_statement(Context *ctx, IfStatement *stmt) +static void delete_if_statement(Context *ctx, MOJOSHADER_astIfStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); @@ -1394,17 +972,18 @@ static void delete_if_statement(Context *ctx, IfStatement *stmt) Free(ctx, stmt); } // delete_if_statement -static SwitchCases *new_switch_case(Context *ctx, Expression *expr, - Statement *stmt) +static MOJOSHADER_astSwitchCases *new_switch_case(Context *ctx, + MOJOSHADER_astExpression *expr, + MOJOSHADER_astStatement *stmt) { - NEW_AST_NODE(retval, SwitchCases, AST_SWITCH_CASE); + NEW_AST_NODE(retval, MOJOSHADER_astSwitchCases, MOJOSHADER_AST_SWITCH_CASE); retval->expr = expr; retval->statement = stmt; retval->next = NULL; return retval; } // new_switch_case -static void delete_switch_case(Context *ctx, SwitchCases *sc) +static void delete_switch_case(Context *ctx, MOJOSHADER_astSwitchCases *sc) { DELETE_AST_NODE(sc); delete_switch_case(ctx, sc->next); @@ -1413,71 +992,82 @@ static void delete_switch_case(Context *ctx, SwitchCases *sc) Free(ctx, sc); } // delete_switch_case -static Statement *new_empty_statement(Context *ctx) +static MOJOSHADER_astStatement *new_empty_statement(Context *ctx) { - NEW_AST_NODE(retval, EmptyStatement, AST_STATEMENT_EMPTY); + NEW_AST_NODE(retval, MOJOSHADER_astEmptyStatement, + MOJOSHADER_AST_STATEMENT_EMPTY); retval->next = NULL; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_empty_statement -static void delete_empty_statement(Context *ctx, EmptyStatement *stmt) +static void delete_empty_statement(Context *ctx, + MOJOSHADER_astEmptyStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); Free(ctx, stmt); } // delete_empty_statement -static Statement *new_break_statement(Context *ctx) +static MOJOSHADER_astStatement *new_break_statement(Context *ctx) { - NEW_AST_NODE(retval, BreakStatement, AST_STATEMENT_BREAK); + NEW_AST_NODE(retval, MOJOSHADER_astBreakStatement, + MOJOSHADER_AST_STATEMENT_BREAK); retval->next = NULL; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_break_statement -static void delete_break_statement(Context *ctx, BreakStatement *stmt) +static void delete_break_statement(Context *ctx, + MOJOSHADER_astBreakStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); Free(ctx, stmt); } // delete_break_statement -static Statement *new_continue_statement(Context *ctx) +static MOJOSHADER_astStatement *new_continue_statement(Context *ctx) { - NEW_AST_NODE(retval, ContinueStatement, AST_STATEMENT_CONTINUE); + NEW_AST_NODE(retval, MOJOSHADER_astContinueStatement, + MOJOSHADER_AST_STATEMENT_CONTINUE); retval->next = NULL; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_continue_statement -static void delete_continue_statement(Context *ctx, ContinueStatement *stmt) +static void delete_continue_statement(Context *ctx, + MOJOSHADER_astContinueStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); Free(ctx, stmt); } // delete_continue_statement -static Statement *new_discard_statement(Context *ctx) +static MOJOSHADER_astStatement *new_discard_statement(Context *ctx) { - NEW_AST_NODE(retval, DiscardStatement, AST_STATEMENT_DISCARD); + NEW_AST_NODE(retval, MOJOSHADER_astDiscardStatement, + MOJOSHADER_AST_STATEMENT_DISCARD); retval->next = NULL; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_discard_statement -static void delete_discard_statement(Context *ctx, DiscardStatement *stmt) +static void delete_discard_statement(Context *ctx, + MOJOSHADER_astDiscardStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); Free(ctx, stmt); } // delete_discard_statement -static Statement *new_expr_statement(Context *ctx, Expression *expr) +static MOJOSHADER_astStatement *new_expr_statement(Context *ctx, + MOJOSHADER_astExpression *expr) { - NEW_AST_NODE(retval, ExpressionStatement, AST_STATEMENT_EXPRESSION); + NEW_AST_NODE(retval, MOJOSHADER_astExpressionStatement, + MOJOSHADER_AST_STATEMENT_EXPRESSION); retval->next = NULL; retval->expr = expr; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_expr_statement -static void delete_expr_statement(Context *ctx, ExpressionStatement *stmt) +static void delete_expr_statement(Context *ctx, + MOJOSHADER_astExpressionStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); @@ -1485,18 +1075,22 @@ static void delete_expr_statement(Context *ctx, ExpressionStatement *stmt) Free(ctx, stmt); } // delete_expr_statement -static Statement *new_switch_statement(Context *ctx, int attr, - Expression *expr, SwitchCases *cases) +static MOJOSHADER_astStatement *new_switch_statement(Context *ctx, + const int attr, + MOJOSHADER_astExpression *expr, + MOJOSHADER_astSwitchCases *cases) { - NEW_AST_NODE(retval, SwitchStatement, AST_STATEMENT_SWITCH); + NEW_AST_NODE(retval, MOJOSHADER_astSwitchStatement, + MOJOSHADER_AST_STATEMENT_SWITCH); retval->next = NULL; retval->attributes = attr; retval->expr = expr; retval->cases = cases; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_switch_statement -static void delete_switch_statement(Context *ctx, SwitchStatement *stmt) +static void delete_switch_statement(Context *ctx, + MOJOSHADER_astSwitchStatement *stmt) { DELETE_AST_NODE(stmt); delete_expr(ctx, stmt->expr); @@ -1504,15 +1098,18 @@ static void delete_switch_statement(Context *ctx, SwitchStatement *stmt) Free(ctx, stmt); } // delete_switch_statement -static Statement *new_struct_statement(Context *ctx, StructDeclaration *sd) +static MOJOSHADER_astStatement *new_struct_statement(Context *ctx, + MOJOSHADER_astStructDeclaration *sd) { - NEW_AST_NODE(retval, StructStatement, AST_STATEMENT_STRUCT); + NEW_AST_NODE(retval, MOJOSHADER_astStructStatement, + MOJOSHADER_AST_STATEMENT_STRUCT); retval->next = NULL; retval->struct_info = sd; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_struct_statement -static void delete_struct_statement(Context *ctx, StructStatement *stmt) +static void delete_struct_statement(Context *ctx, + MOJOSHADER_astStructStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); @@ -1520,15 +1117,18 @@ static void delete_struct_statement(Context *ctx, StructStatement *stmt) Free(ctx, stmt); } // delete_struct_statement -static Statement *new_vardecl_statement(Context *ctx, VariableDeclaration *vd) +static MOJOSHADER_astStatement *new_vardecl_statement(Context *ctx, + MOJOSHADER_astVariableDeclaration *vd) { - NEW_AST_NODE(retval, VarDeclStatement, AST_STATEMENT_VARDECL); + NEW_AST_NODE(retval, MOJOSHADER_astVarDeclStatement, + MOJOSHADER_AST_STATEMENT_VARDECL); retval->next = NULL; retval->declaration = vd; - return (Statement *) retval; + return (MOJOSHADER_astStatement *) retval; } // new_vardecl_statement -static void delete_vardecl_statement(Context *ctx, VarDeclStatement *stmt) +static void delete_vardecl_statement(Context *ctx, + MOJOSHADER_astVarDeclStatement *stmt) { DELETE_AST_NODE(stmt); delete_statement(ctx, stmt->next); @@ -1536,7 +1136,7 @@ static void delete_vardecl_statement(Context *ctx, VarDeclStatement *stmt) Free(ctx, stmt); } // delete_vardecl_statement -static void delete_statement(Context *ctx, Statement *stmt) +static void delete_statement(Context *ctx, MOJOSHADER_astStatement *stmt) { if (!stmt) return; @@ -1548,11 +1148,11 @@ static void delete_statement(Context *ctx, Statement *stmt) // Please note that everyone should _try_ to delete their "next" member, // just in case, but hopefully this cleaned it out. - Statement *i = stmt->next; + MOJOSHADER_astStatement *i = stmt->next; stmt->next = NULL; while (i) { - Statement *next = i->next; + MOJOSHADER_astStatement *next = i->next; i->next = NULL; delete_statement(ctx, i); i = next; @@ -1560,23 +1160,24 @@ static void delete_statement(Context *ctx, Statement *stmt) switch (stmt->ast.type) { - #define DELETE_STATEMENT(typ, cls, fn) case AST_STATEMENT_##typ: \ - delete_##fn##_statement(ctx, (cls *) stmt); break; - DELETE_STATEMENT(BLOCK, BlockStatement, block); - DELETE_STATEMENT(EMPTY, EmptyStatement, empty); - DELETE_STATEMENT(IF, IfStatement, if); - DELETE_STATEMENT(SWITCH, SwitchStatement, switch); - DELETE_STATEMENT(EXPRESSION, ExpressionStatement, expr); - DELETE_STATEMENT(FOR, ForStatement, for); - DELETE_STATEMENT(DO, DoStatement, do); - DELETE_STATEMENT(WHILE, WhileStatement, while); - DELETE_STATEMENT(RETURN, ReturnStatement, return); - DELETE_STATEMENT(BREAK, BreakStatement, break); - DELETE_STATEMENT(CONTINUE, ContinueStatement, continue); - DELETE_STATEMENT(DISCARD, DiscardStatement, discard); - DELETE_STATEMENT(TYPEDEF, TypedefStatement, typedef); - DELETE_STATEMENT(STRUCT, StructStatement, struct); - DELETE_STATEMENT(VARDECL, VarDeclStatement, vardecl); + #define DELETE_STATEMENT(typ, cls, fn) \ + case MOJOSHADER_AST_STATEMENT_##typ: \ + delete_##fn##_statement(ctx, (cls *) stmt); break; + DELETE_STATEMENT(BLOCK, MOJOSHADER_astBlockStatement, block); + DELETE_STATEMENT(EMPTY, MOJOSHADER_astEmptyStatement, empty); + DELETE_STATEMENT(IF, MOJOSHADER_astIfStatement, if); + DELETE_STATEMENT(SWITCH, MOJOSHADER_astSwitchStatement, switch); + DELETE_STATEMENT(EXPRESSION, MOJOSHADER_astExpressionStatement, expr); + DELETE_STATEMENT(FOR, MOJOSHADER_astForStatement, for); + DELETE_STATEMENT(DO, MOJOSHADER_astDoStatement, do); + DELETE_STATEMENT(WHILE, MOJOSHADER_astWhileStatement, while); + DELETE_STATEMENT(RETURN, MOJOSHADER_astReturnStatement, return); + DELETE_STATEMENT(BREAK, MOJOSHADER_astBreakStatement, break); + DELETE_STATEMENT(CONTINUE, MOJOSHADER_astContinueStatement, continue); + DELETE_STATEMENT(DISCARD, MOJOSHADER_astDiscardStatement, discard); + DELETE_STATEMENT(TYPEDEF, MOJOSHADER_astTypedefStatement, typedef); + DELETE_STATEMENT(STRUCT, MOJOSHADER_astStructStatement, struct); + DELETE_STATEMENT(VARDECL, MOJOSHADER_astVarDeclStatement, vardecl); #undef DELETE_STATEMENT default: assert(0 && "missing cleanup code"); break; } // switch @@ -1597,756 +1198,6 @@ static const char *get_usertype(const Context *ctx, const char *token) #include "mojoshader_parser_hlsl.h" -// !!! FIXME: this screws up on order of operations. -static void print_ast(const int substmt, void *ast) -{ - const char *nl = substmt ? "" : "\n"; - static int indent = 0; - int isblock = 0; - int i; - - if (!ast) return; - - #define DO_INDENT do { \ - if (!substmt) { for (i = 0; i < indent; i++) printf(" "); } \ - } while (0) - - switch ( ((ASTGeneric *) ast)->ast.type ) - { - case AST_OP_POSTINCREMENT: - print_ast(0, ((ExpressionUnary *) ast)->operand); - printf("++"); - break; - - case AST_OP_POSTDECREMENT: - print_ast(0, ((ExpressionUnary *) ast)->operand); - printf("--"); - break; - - case AST_OP_PREINCREMENT: - printf("++"); - print_ast(0, ((ExpressionUnary *) ast)->operand); - break; - - case AST_OP_PREDECREMENT: - printf("--"); - print_ast(0, ((ExpressionUnary *) ast)->operand); - break; - - case AST_OP_NEGATE: - printf("-"); - print_ast(0, ((ExpressionUnary *) ast)->operand); - break; - - case AST_OP_COMPLEMENT: - printf("~"); - print_ast(0, ((ExpressionUnary *) ast)->operand); - break; - - case AST_OP_NOT: - printf("!"); - print_ast(0, ((ExpressionUnary *) ast)->operand); - break; - - case AST_OP_DEREF_ARRAY: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf("["); - print_ast(0, ((ExpressionBinary *) ast)->right); - printf("]"); - break; - - case AST_OP_DEREF_STRUCT: - print_ast(0, ((ExpressionDerefStruct *) ast)->identifier); - printf("."); - printf("%s", ((ExpressionDerefStruct *) ast)->member); - break; - - case AST_OP_COMMA: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(", "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_MULTIPLY: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" * "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_DIVIDE: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" / "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_MODULO: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" %% "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_ADD: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" + "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_SUBTRACT: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" - "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_LSHIFT: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" << "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_RSHIFT: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" >> "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_LESSTHAN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" < "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_GREATERTHAN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" > "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_LESSTHANOREQUAL: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" <= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_GREATERTHANOREQUAL: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" >= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_EQUAL: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" == "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_NOTEQUAL: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" != "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_BINARYAND: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" & "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_BINARYXOR: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" ^ "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_BINARYOR: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" | "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_LOGICALAND: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" && "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_LOGICALOR: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" || "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_ASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" = "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_MULASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" *= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_DIVASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" /= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_MODASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" %%= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_ADDASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" += "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_SUBASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" -= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_LSHIFTASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" <<= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_RSHIFTASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" >>= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_ANDASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" &= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_XORASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" ^= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_ORASSIGN: - print_ast(0, ((ExpressionBinary *) ast)->left); - printf(" |= "); - print_ast(0, ((ExpressionBinary *) ast)->right); - break; - - case AST_OP_CONDITIONAL: - print_ast(0, ((ExpressionTernary *) ast)->left); - printf(" ? "); - print_ast(0, ((ExpressionTernary *) ast)->center); - printf(" : "); - print_ast(0, ((ExpressionTernary *) ast)->right); - break; - - case AST_OP_IDENTIFIER: - printf("%s", ((ExpressionIdentifier *) ast)->identifier); - break; - - case AST_OP_INT_LITERAL: - printf("%lld", (long long) ((ExpressionIntLiteral *) ast)->value); - break; - - case AST_OP_FLOAT_LITERAL: - { - const float f = ((ExpressionFloatLiteral *) ast)->value; - const long long flr = (long long) f; - if (((float) flr) == f) - printf("%lld.0", flr); - else - printf("%.16g", f); - break; - } // case - - case AST_OP_STRING_LITERAL: - printf("\"%s\"", ((ExpressionStringLiteral *) ast)->string); - break; - - case AST_OP_BOOLEAN_LITERAL: - printf("%s", ((ExpressionBooleanLiteral *) ast)->value ? "true" : "false"); - break; - - case AST_ARGUMENTS: - print_ast(0, ((Arguments *) ast)->argument); - if (((Arguments *) ast)->next != NULL) - { - printf(", "); - print_ast(0, ((Arguments *) ast)->next); - } // if - break; - - case AST_OP_CALLFUNC: - print_ast(0, ((ExpressionCallFunction *) ast)->identifier); - printf("("); - print_ast(0, ((ExpressionCallFunction *) ast)->args); - printf(")"); - break; - - case AST_OP_CONSTRUCTOR: - printf("%s(", ((ExpressionConstructor *) ast)->datatype); - print_ast(0, ((ExpressionConstructor *) ast)->args); - printf(")"); - break; - - case AST_OP_CAST: - printf("(%s) (", ((ExpressionCast *) ast)->datatype); - print_ast(0, ((ExpressionCast *) ast)->operand); - printf(")"); - break; - - case AST_STATEMENT_EMPTY: - DO_INDENT; - printf(";%s", nl); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_EXPRESSION: - DO_INDENT; - print_ast(0, ((ExpressionStatement *) ast)->expr); // !!! FIXME: This is named badly... - printf(";%s", nl); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_IF: - DO_INDENT; - printf("if ("); - print_ast(0, ((IfStatement *) ast)->expr); - printf(")\n"); - isblock = ((IfStatement *) ast)->statement->ast.type == AST_STATEMENT_BLOCK; - if (!isblock) indent++; - print_ast(0, ((IfStatement *) ast)->statement); - if (!isblock) indent--; - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_TYPEDEF: - DO_INDENT; - print_ast(1, ((TypedefStatement *) ast)->type_info); - printf("%s", nl); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_SWITCH: - DO_INDENT; - switch ( ((SwitchStatement *) ast)->attributes ) - { - case SWITCHATTR_NONE: break; - case SWITCHATTR_FLATTEN: printf("[flatten] "); break; - case SWITCHATTR_BRANCH: printf("[branch] "); break; - case SWITCHATTR_FORCECASE: printf("[forcecase] "); break; - case SWITCHATTR_CALL: printf("[call] "); break; - } // switch - - printf("switch ("); - print_ast(0, ((SwitchStatement *) ast)->expr); - printf(")\n"); - DO_INDENT; - printf("{\n"); - indent++; - print_ast(0, ((SwitchStatement *) ast)->cases); - indent--; - printf("\n"); - DO_INDENT; - printf("}\n"); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_SWITCH_CASE: - DO_INDENT; - printf("case "); - print_ast(0, ((SwitchCases *) ast)->expr); - printf(":\n"); - isblock = ((SwitchCases *) ast)->statement->ast.type == AST_STATEMENT_BLOCK; - if (!isblock) indent++; - print_ast(0, ((SwitchCases *) ast)->statement); - if (!isblock) indent--; - print_ast(0, ((SwitchCases *) ast)->next); - break; - - case AST_STATEMENT_STRUCT: - DO_INDENT; - print_ast(0, ((CompilationUnitStruct *) ast)->struct_info); - printf(";%s%s", nl, nl); // always space these out. - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_VARDECL: - DO_INDENT; - print_ast(1, ((VarDeclStatement *) ast)->declaration); - printf(";%s", nl); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_BLOCK: - DO_INDENT; - printf("{\n"); - indent++; - print_ast(0, ((BlockStatement *) ast)->statements); - indent--; - DO_INDENT; - printf("}\n"); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_FOR: - DO_INDENT; - if (((ForStatement *) ast)->unroll == 0) - printf("[loop] "); - else if (((ForStatement *) ast)->unroll == -1) - printf("[unroll] "); - else if (((ForStatement *) ast)->unroll > 0) - { - printf("[unroll(%lld)] ", - (long long) (((ForStatement *) ast)->unroll) ); - } // else if - - printf("for ("); - print_ast(1, ((ForStatement *) ast)->var_decl); - if (((ForStatement *) ast)->initializer != NULL) - { - printf(" = "); - print_ast(1, ((ForStatement *) ast)->initializer); - } // if - printf("; "); - print_ast(1, ((ForStatement *) ast)->looptest); - printf("; "); - print_ast(1, ((ForStatement *) ast)->counter); - - printf(")\n"); - isblock = ((ForStatement *) ast)->statement->ast.type == AST_STATEMENT_BLOCK; - if (!isblock) indent++; - print_ast(0, ((ForStatement *) ast)->statement); - if (!isblock) indent--; - - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_DO: - DO_INDENT; - if (((DoStatement *) ast)->unroll == 0) - printf("[loop] "); - else if (((DoStatement *) ast)->unroll == -1) - printf("[unroll] "); - else if (((DoStatement *) ast)->unroll > 0) - { - printf("[unroll(%lld)] ", - (long long) (((DoStatement *) ast)->unroll) ); - } // else if - - printf("do\n"); - - isblock = ((DoStatement *) ast)->statement->ast.type == AST_STATEMENT_BLOCK; - if (!isblock) indent++; - print_ast(0, ((DoStatement *) ast)->statement); - if (!isblock) indent--; - - DO_INDENT; - printf("while ("); - print_ast(0, ((DoStatement *) ast)->expr); - printf(");\n"); - - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_WHILE: - DO_INDENT; - if (((WhileStatement *) ast)->unroll == 0) - printf("[loop] "); - else if (((WhileStatement *) ast)->unroll == -1) - printf("[unroll] "); - else if (((WhileStatement *) ast)->unroll > 0) - { - printf("[unroll(%lld)] ", - (long long) (((WhileStatement *) ast)->unroll) ); - } // else if - - printf("while ("); - print_ast(0, ((WhileStatement *) ast)->expr); - printf(")\n"); - - isblock = ((WhileStatement *) ast)->statement->ast.type == AST_STATEMENT_BLOCK; - if (!isblock) indent++; - print_ast(0, ((WhileStatement *) ast)->statement); - if (!isblock) indent--; - - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_RETURN: - DO_INDENT; - printf("return"); - if (((ReturnStatement *) ast)->expr) - { - printf(" "); - print_ast(0, ((ReturnStatement *) ast)->expr); - } // if - printf(";%s", nl); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_BREAK: - DO_INDENT; - printf("break;%s", nl); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_CONTINUE: - DO_INDENT; - printf("continue;%s", nl); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_STATEMENT_DISCARD: - DO_INDENT; - printf("discard;%s", nl); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_COMPUNIT_FUNCTION: - DO_INDENT; - print_ast(0, ((CompilationUnitFunction *) ast)->declaration); - if (((CompilationUnitFunction *) ast)->definition == NULL) - printf(";%s", nl); - else - { - printf("%s", nl); - print_ast(0, ((CompilationUnitFunction *) ast)->definition); - printf("%s", nl); - } // else - print_ast(0, ((CompilationUnit *) ast)->next); - break; - - case AST_COMPUNIT_TYPEDEF: - DO_INDENT; - print_ast(0, ((CompilationUnitTypedef *) ast)->type_info); - printf("%s", nl); - print_ast(0, ((Statement *) ast)->next); - break; - - case AST_COMPUNIT_STRUCT: - DO_INDENT; - print_ast(0, ((CompilationUnitStruct *) ast)->struct_info); - printf(";%s%s", nl, nl); // always space these out. - print_ast(0, ((CompilationUnit *) ast)->next); - break; - - case AST_COMPUNIT_VARIABLE: - DO_INDENT; - print_ast(1, ((CompilationUnitVariable *) ast)->declaration); - printf(";%s", nl); - if (((CompilationUnit *) ast)->next && ((CompilationUnit *) ast)->next->ast.type != AST_COMPUNIT_VARIABLE) - printf("%s", nl); // group vars together, and space out other things. - print_ast(0, ((CompilationUnit *) ast)->next); - break; - - case AST_SCALAR_OR_ARRAY: - printf("%s", ((ScalarOrArray*) ast)->identifier); - if (((ScalarOrArray*) ast)->isarray) - { - printf("["); - print_ast(0, ((ScalarOrArray*) ast)->dimension); - printf("]"); - } // if - break; - - case AST_TYPEDEF: - DO_INDENT; - printf("typedef %s%s ", - (((Typedef *) ast)->isconst) ? "const " : "", - (((Typedef *) ast)->datatype)); - print_ast(0, ((Typedef *) ast)->details); - printf(";%s", nl); - break; - - case AST_FUNCTION_PARAMS: - switch (((FunctionParameters *) ast)->input_modifier) - { - case INPUTMOD_NONE: break; - case INPUTMOD_IN: printf("in "); break; - case INPUTMOD_OUT: printf("out "); break; - case INPUTMOD_INOUT: printf("in out "); break; - case INPUTMOD_UNIFORM: printf("uniform "); break; - } // switch - - printf("%s %s", (((FunctionParameters *) ast)->datatype), - (((FunctionParameters *) ast)->identifier)); - if (((FunctionParameters *) ast)->semantic) - printf(" : %s", ((FunctionParameters *) ast)->semantic); - - switch (((FunctionParameters *) ast)->interpolation_modifier) - { - case INTERPMOD_NONE: break; - case INTERPMOD_LINEAR: printf(" linear"); break; - case INTERPMOD_CENTROID: printf(" centroid"); break; - case INTERPMOD_NOINTERPOLATION: printf(" nointerpolation"); break; - case INTERPMOD_NOPERSPECTIVE: printf(" noperspective"); break; - case INTERPMOD_SAMPLE: printf(" sample"); break; - } // switch - - if (((FunctionParameters *) ast)->initializer) - { - printf(" = "); - print_ast(0, ((FunctionParameters *) ast)->initializer); - } // if - - if (((FunctionParameters *) ast)->next) - { - printf(", "); - print_ast(0, ((FunctionParameters *) ast)->next); - } // if - break; - - case AST_FUNCTION_SIGNATURE: - switch (((FunctionSignature *) ast)->storage_class) - { - case FNSTORECLS_NONE: break; - case FNSTORECLS_INLINE: printf("inline "); break; - } // switch - printf("%s %s(", - ((FunctionSignature *) ast)->datatype ? - ((FunctionSignature *) ast)->datatype : "void", - ((FunctionSignature *) ast)->identifier); - print_ast(0, ((FunctionSignature *) ast)->params); - printf(")"); - if (((FunctionSignature *) ast)->semantic) - printf(" : %s", ((FunctionSignature *) ast)->semantic); - break; - - case AST_STRUCT_DECLARATION: - printf("struct %s\n", ((StructDeclaration *) ast)->name); - DO_INDENT; - printf("{\n"); - indent++; - print_ast(0, ((StructDeclaration *) ast)->members); - indent--; - DO_INDENT; - printf("}"); - break; - - case AST_STRUCT_MEMBER: - DO_INDENT; - switch (((StructMembers *) ast)->interpolation_mod) - { - case INTERPMOD_NONE: break; - case INTERPMOD_LINEAR: printf("linear "); break; - case INTERPMOD_CENTROID: printf("centroid "); break; - case INTERPMOD_NOINTERPOLATION: printf("nointerpolation "); break; - case INTERPMOD_NOPERSPECTIVE: printf("noperspective "); break; - case INTERPMOD_SAMPLE: printf("sample "); break; - } // switch - printf("%s ", ((StructMembers *) ast)->datatype); - print_ast(0, ((StructMembers *) ast)->details); - if (((StructMembers *) ast)->semantic) - printf(" : %s", ((StructMembers *) ast)->semantic); - printf(";%s", nl); - print_ast(0, ((StructMembers *) ast)->next); - break; - - case AST_VARIABLE_DECLARATION: - DO_INDENT; - if (((VariableDeclaration *) ast)->attributes & VARATTR_EXTERN) - printf("extern "); - if (((VariableDeclaration *) ast)->attributes & VARATTR_NOINTERPOLATION) - printf("nointerpolation "); - if (((VariableDeclaration *) ast)->attributes & VARATTR_SHARED) - printf("shared"); - if (((VariableDeclaration *) ast)->attributes & VARATTR_STATIC) - printf("static "); - if (((VariableDeclaration *) ast)->attributes & VARATTR_UNIFORM) - printf("uniform "); - if (((VariableDeclaration *) ast)->attributes & VARATTR_VOLATILE) - printf("nointerpolation "); - if (((VariableDeclaration *) ast)->attributes & VARATTR_CONST) - printf("const "); - if (((VariableDeclaration *) ast)->attributes & VARATTR_ROWMAJOR) - printf("rowmajor "); - if (((VariableDeclaration *) ast)->attributes & VARATTR_COLUMNMAJOR) - printf("columnmajor "); - - if (((VariableDeclaration *) ast)->datatype) - printf("%s", ((VariableDeclaration *) ast)->datatype); - else - print_ast(0, ((VariableDeclaration *) ast)->anonymous_datatype); - printf(" "); - print_ast(0, ((VariableDeclaration *) ast)->details); - if (((VariableDeclaration *) ast)->semantic) - printf(" : %s", ((VariableDeclaration *) ast)->semantic); - if (((VariableDeclaration *) ast)->annotations) - { - printf(" "); - print_ast(0, ((VariableDeclaration *) ast)->annotations); - } // if - if (((VariableDeclaration *) ast)->initializer != NULL) - { - printf(" = "); - print_ast(0, ((VariableDeclaration *) ast)->initializer); - } // if - print_ast(0, ((VariableDeclaration *) ast)->lowlevel); - - if (((VariableDeclaration *) ast)->next == NULL) - printf("%s", nl); - else - { - int attr = (((VariableDeclaration *) ast)->next)->attributes; - printf(", "); - (((VariableDeclaration *) ast)->next)->attributes = 0; - print_ast(1, ((VariableDeclaration *) ast)->next); - (((VariableDeclaration *) ast)->next)->attributes = attr; - } // if - break; - - case AST_PACK_OFFSET: - printf(" : packoffset(%s%s%s)", - ((PackOffset *) ast)->ident1, - ((PackOffset *) ast)->ident2 ? "." : "", - ((PackOffset *) ast)->ident2 ? ((PackOffset *) ast)->ident2 : ""); - break; - - case AST_VARIABLE_LOWLEVEL: - print_ast(0, ((VariableLowLevel *) ast)->packoffset); - if (((VariableLowLevel *) ast)->register_name) - printf(" : register(%s)", ((VariableLowLevel *) ast)->register_name); - break; - - case AST_ANNOTATION: - { - const Annotations *a = (Annotations *) ast; - printf("<"); - while (a) - { - printf(" %s ", a->datatype); - if (a->initializer != NULL) - { - printf(" = "); - print_ast(0, a->initializer); - } // if - if (a->next) - printf(","); - a = a->next; - } // while - printf(" >"); - break; - } // case - - default: - assert(0 && "unexpected type"); - break; - } // switch - - #undef DO_INDENT -} // print_ast - - /* * datatype strings... * @@ -2472,8 +1323,10 @@ static const char *array_element_datatype(Context *ctx, const char *datatype) // Returns final datatype used once implicit casting is complete. // The datatypes must be pointers from the string cache. static const char *add_type_coercion(Context *ctx, - Expression **left, const char *ldatatype, - Expression **right, const char *rdatatype) + MOJOSHADER_astExpression **left, + const char *ldatatype, + MOJOSHADER_astExpression **right, + const char *rdatatype) { // !!! FIXME: this whole function is probably naive at best. @@ -2556,159 +1409,129 @@ static const char *add_type_coercion(Context *ctx, // continue (but code generation will be skipped due to errors). // This means further processing can assume the AST is sane and not have to // spend effort verifying it again. -static const char *type_check_ast(Context *ctx, void *ast) +static const char *type_check_ast(Context *ctx, void *_ast) { + MOJOSHADER_astNode *ast = (MOJOSHADER_astNode *) _ast; + const char *datatype; + const char *datatype2; + const char *datatype3; + if (!ast) return NULL; // upkeep so we report correct error locations... - ctx->sourcefile = ((ASTGeneric *) ast)->ast.filename; - ctx->sourceline = ((ASTGeneric *) ast)->ast.line; + ctx->sourcefile = ast->ast.filename; + ctx->sourceline = ast->ast.line; - switch ( ((ASTGeneric *) ast)->ast.type ) + switch (ast->ast.type) { - case AST_OP_POSTINCREMENT: - case AST_OP_POSTDECREMENT: - case AST_OP_PREINCREMENT: - case AST_OP_PREDECREMENT: - case AST_OP_COMPLEMENT: - case AST_OP_NEGATE: - { - ExpressionUnary *expr = (ExpressionUnary *) ast; - const char *datatype = type_check_ast(ctx, expr->operand); + case MOJOSHADER_AST_OP_POSTINCREMENT: + case MOJOSHADER_AST_OP_POSTDECREMENT: + case MOJOSHADER_AST_OP_PREINCREMENT: + case MOJOSHADER_AST_OP_PREDECREMENT: + case MOJOSHADER_AST_OP_COMPLEMENT: + case MOJOSHADER_AST_OP_NEGATE: + datatype = type_check_ast(ctx, ast->unary.operand); require_numeric_datatype(ctx, datatype); return datatype; - } // case - case AST_OP_NOT: - { - ExpressionUnary *expr = (ExpressionUnary *) ast; - const char *datatype = type_check_ast(ctx, expr->operand); + case MOJOSHADER_AST_OP_NOT: + datatype = type_check_ast(ctx, ast->unary.operand); require_boolean_datatype(ctx, datatype); return datatype; - } // case - case AST_OP_DEREF_ARRAY: - { - ExpressionBinary *expr = (ExpressionBinary *) ast; - const char *datatype = type_check_ast(ctx, expr->left); - const char *datatype2 = type_check_ast(ctx, expr->right); + case MOJOSHADER_AST_OP_DEREF_ARRAY: + datatype = type_check_ast(ctx, ast->binary.left); + datatype2 = type_check_ast(ctx, ast->binary.right); require_array_datatype(ctx, datatype); require_numeric_datatype(ctx, datatype2); - add_type_coercion(ctx, NULL, ctx->str_i, &expr->right, datatype2); + add_type_coercion(ctx, NULL, ctx->str_i, &ast->binary.right, datatype2); return array_element_datatype(ctx, datatype); - } // case - case AST_OP_DEREF_STRUCT: - { - ExpressionDerefStruct *expr = (ExpressionDerefStruct *) ast; - const char *datatype = type_check_ast(ctx, expr->identifier); + case MOJOSHADER_AST_OP_DEREF_STRUCT: + datatype = type_check_ast(ctx, ast->derefstruct.identifier); require_struct_datatype(ctx, datatype); // !!! FIXME: map member to datatype datatype = "!!! FIXME"; return datatype; - } // case - case AST_OP_COMMA: - { + case MOJOSHADER_AST_OP_COMMA: // evaluate and throw away left, return right. - ExpressionBinary *expr = (ExpressionBinary *) ast; - type_check_ast(ctx, expr->left); - return type_check_ast(ctx, expr->right); - } // case - - case AST_OP_MULTIPLY: - case AST_OP_DIVIDE: - case AST_OP_MODULO: - case AST_OP_ADD: - case AST_OP_SUBTRACT: - case AST_OP_LSHIFT: - case AST_OP_RSHIFT: - { - ExpressionBinary *expr = (ExpressionBinary *) ast; - const char *datatype = type_check_ast(ctx, expr->left); - const char *datatype2 = type_check_ast(ctx, expr->right); + type_check_ast(ctx, ast->binary.left); + return type_check_ast(ctx, ast->binary.right); + + case MOJOSHADER_AST_OP_MULTIPLY: + case MOJOSHADER_AST_OP_DIVIDE: + case MOJOSHADER_AST_OP_MODULO: + case MOJOSHADER_AST_OP_ADD: + case MOJOSHADER_AST_OP_SUBTRACT: + case MOJOSHADER_AST_OP_LSHIFT: + case MOJOSHADER_AST_OP_RSHIFT: + datatype = type_check_ast(ctx, ast->binary.left); + datatype2 = type_check_ast(ctx, ast->binary.right); require_numeric_datatype(ctx, datatype); require_numeric_datatype(ctx, datatype2); - return add_type_coercion(ctx, &expr->left, datatype, - &expr->right, datatype2); - } // case - - case AST_OP_LESSTHAN: - case AST_OP_GREATERTHAN: - case AST_OP_LESSTHANOREQUAL: - case AST_OP_GREATERTHANOREQUAL: - case AST_OP_NOTEQUAL: - case AST_OP_EQUAL: - { - ExpressionBinary *expr = (ExpressionBinary *) ast; - const char *datatype = type_check_ast(ctx, expr->left); - const char *datatype2 = type_check_ast(ctx, expr->right); - add_type_coercion(ctx, &expr->left, datatype, - &expr->right, datatype2); + return add_type_coercion(ctx, &ast->binary.left, datatype, + &ast->binary.right, datatype2); + + case MOJOSHADER_AST_OP_LESSTHAN: + case MOJOSHADER_AST_OP_GREATERTHAN: + case MOJOSHADER_AST_OP_LESSTHANOREQUAL: + case MOJOSHADER_AST_OP_GREATERTHANOREQUAL: + case MOJOSHADER_AST_OP_NOTEQUAL: + case MOJOSHADER_AST_OP_EQUAL: + datatype = type_check_ast(ctx, ast->binary.left); + datatype2 = type_check_ast(ctx, ast->binary.right); + add_type_coercion(ctx, &ast->binary.left, datatype, + &ast->binary.right, datatype2); return ctx->str_b; - } // case - case AST_OP_BINARYAND: - case AST_OP_BINARYXOR: - case AST_OP_BINARYOR: - { - ExpressionBinary *expr = (ExpressionBinary *) ast; - const char *datatype = type_check_ast(ctx, expr->left); - const char *datatype2 = type_check_ast(ctx, expr->right); + case MOJOSHADER_AST_OP_BINARYAND: + case MOJOSHADER_AST_OP_BINARYXOR: + case MOJOSHADER_AST_OP_BINARYOR: + datatype = type_check_ast(ctx, ast->binary.left); + datatype2 = type_check_ast(ctx, ast->binary.right); require_integer_datatype(ctx, datatype); require_integer_datatype(ctx, datatype2); - return add_type_coercion(ctx, &expr->left, datatype, - &expr->right, datatype2); - } // case + return add_type_coercion(ctx, &ast->binary.left, datatype, + &ast->binary.right, datatype2); - case AST_OP_LOGICALAND: - case AST_OP_LOGICALOR: - { - ExpressionBinary *expr = (ExpressionBinary *) ast; - const char *datatype = type_check_ast(ctx, expr->left); - const char *datatype2 = type_check_ast(ctx, expr->right); + case MOJOSHADER_AST_OP_LOGICALAND: + case MOJOSHADER_AST_OP_LOGICALOR: + datatype = type_check_ast(ctx, ast->binary.left); + datatype2 = type_check_ast(ctx, ast->binary.right); require_boolean_datatype(ctx, datatype); require_boolean_datatype(ctx, datatype2); - add_type_coercion(ctx, &expr->left, datatype, - &expr->right, datatype2); + add_type_coercion(ctx, &ast->binary.left, datatype, + &ast->binary.right, datatype2); return ctx->str_b; - } // case - case AST_OP_ASSIGN: - case AST_OP_MULASSIGN: - case AST_OP_DIVASSIGN: - case AST_OP_MODASSIGN: - case AST_OP_ADDASSIGN: - case AST_OP_SUBASSIGN: - case AST_OP_LSHIFTASSIGN: - case AST_OP_RSHIFTASSIGN: - case AST_OP_ANDASSIGN: - case AST_OP_XORASSIGN: - case AST_OP_ORASSIGN: - { - ExpressionBinary *expr = (ExpressionBinary *) ast; - const char *datatype = type_check_ast(ctx, expr->left); - const char *datatype2 = type_check_ast(ctx, expr->right); - add_type_coercion(ctx, NULL, datatype, &expr->right, datatype2); + case MOJOSHADER_AST_OP_ASSIGN: + case MOJOSHADER_AST_OP_MULASSIGN: + case MOJOSHADER_AST_OP_DIVASSIGN: + case MOJOSHADER_AST_OP_MODASSIGN: + case MOJOSHADER_AST_OP_ADDASSIGN: + case MOJOSHADER_AST_OP_SUBASSIGN: + case MOJOSHADER_AST_OP_LSHIFTASSIGN: + case MOJOSHADER_AST_OP_RSHIFTASSIGN: + case MOJOSHADER_AST_OP_ANDASSIGN: + case MOJOSHADER_AST_OP_XORASSIGN: + case MOJOSHADER_AST_OP_ORASSIGN: + datatype = type_check_ast(ctx, ast->binary.left); + datatype2 = type_check_ast(ctx, ast->binary.right); + add_type_coercion(ctx, NULL, datatype, &ast->binary.right, datatype2); return datatype; - } // case - case AST_OP_CONDITIONAL: - { - ExpressionTernary *tern = (ExpressionTernary *) ast; - const char *datatype = type_check_ast(ctx, tern->left); - const char *datatype2 = type_check_ast(ctx, tern->center); - const char *datatype3 = type_check_ast(ctx, tern->right); + case MOJOSHADER_AST_OP_CONDITIONAL: + type_check_ast(ctx, ast->ternary.left); + type_check_ast(ctx, ast->ternary.center); + type_check_ast(ctx, ast->ternary.right); require_boolean_datatype(ctx, datatype); - return add_type_coercion(ctx, &tern->center, datatype2, - &tern->right, datatype3); - } // case + return add_type_coercion(ctx, &ast->ternary.center, datatype2, + &ast->ternary.right, datatype3); - case AST_OP_IDENTIFIER: - { - ExpressionIdentifier *expr = (ExpressionIdentifier *) ast; - const char *datatype = find_variable(ctx, expr->identifier); + case MOJOSHADER_AST_OP_IDENTIFIER: + datatype = find_variable(ctx, ast->identifier.identifier); if (datatype == NULL) { fail(ctx, "Unknown identifier"); @@ -2716,107 +1539,82 @@ datatype = "!!! FIXME"; datatype = ctx->str_i; } // if return datatype; - } // case - case AST_OP_INT_LITERAL: + case MOJOSHADER_AST_OP_INT_LITERAL: return ctx->str_i; - case AST_OP_FLOAT_LITERAL: + case MOJOSHADER_AST_OP_FLOAT_LITERAL: return ctx->str_f; - case AST_OP_STRING_LITERAL: + case MOJOSHADER_AST_OP_STRING_LITERAL: return ctx->str_S; - case AST_OP_BOOLEAN_LITERAL: + case MOJOSHADER_AST_OP_BOOLEAN_LITERAL: return ctx->str_b; - case AST_ARGUMENTS: - { - Arguments *arguments = (Arguments *) ast; - const char *datatype = type_check_ast(ctx, arguments->argument); - if (arguments->next != NULL) + case MOJOSHADER_AST_ARGUMENTS: + datatype = type_check_ast(ctx, ast->arguments.argument); + if (ast->arguments.next != NULL) { - const char *datatype2 = type_check_ast(ctx, arguments->next); + datatype2 = type_check_ast(ctx, ast->arguments.next); datatype = stringcache_fmt(ctx->strcache, "%s%s", datatype, datatype2); } // if return datatype; - } // case - case AST_OP_CALLFUNC: - { - ExpressionCallFunction *expr = (ExpressionCallFunction *) ast; - const char *datatype = type_check_ast(ctx, expr->identifier); - /*const char *datatype2 =*/ type_check_ast(ctx, expr->args); - const char *retval = require_function_datatype(ctx, datatype); + case MOJOSHADER_AST_OP_CALLFUNC: + datatype = type_check_ast(ctx, ast->callfunc.identifier); + datatype2 = type_check_ast(ctx, ast->callfunc.args); + return require_function_datatype(ctx, datatype); // !!! FIXME: test each arg against function datatype. - return retval; // this is the datatype of the func's return value. - } // case + //return retval; // this is the datatype of the func's return value. - case AST_OP_CONSTRUCTOR: - { - ExpressionConstructor *expr = (ExpressionConstructor *) ast; + case MOJOSHADER_AST_OP_CONSTRUCTOR: // !!! FIXME: test each arg against constructor datatype. - type_check_ast(ctx, expr->args); - return expr->datatype; - } // case + type_check_ast(ctx, ast->constructor.args); + return ast->constructor.datatype; - case AST_OP_CAST: - { - ExpressionCast *expr = (ExpressionCast *) ast; - const char *datatype = expr->datatype; - const char *datatype2 = type_check_ast(ctx, expr->operand); + case MOJOSHADER_AST_OP_CAST: + datatype = ast->cast.datatype; + datatype2 = type_check_ast(ctx, ast->cast.operand); // you still need type coercion, since you could do a wrong cast, // like "int x = (short) mychar;" - add_type_coercion(ctx, NULL, datatype, &expr->operand, datatype2); + add_type_coercion(ctx, NULL, datatype, &ast->cast.operand, datatype2); return datatype; - } // case - case AST_STATEMENT_BREAK: - case AST_STATEMENT_CONTINUE: - case AST_STATEMENT_DISCARD: - case AST_STATEMENT_EMPTY: - { - type_check_ast(ctx, ((Statement *) ast)->next); + case MOJOSHADER_AST_STATEMENT_BREAK: + case MOJOSHADER_AST_STATEMENT_CONTINUE: + case MOJOSHADER_AST_STATEMENT_DISCARD: + case MOJOSHADER_AST_STATEMENT_EMPTY: + type_check_ast(ctx, ast->stmt.next); return NULL; - } // case - case AST_STATEMENT_EXPRESSION: - { - ExpressionStatement *stmt = (ExpressionStatement *) ast; + case MOJOSHADER_AST_STATEMENT_EXPRESSION: // !!! FIXME: warn about expressions without a side-effect here? - type_check_ast(ctx, stmt->expr); // !!! FIXME: This is named badly... - type_check_ast(ctx, stmt->next); + type_check_ast(ctx, ast->exprstmt.expr); // !!! FIXME: This is named badly... + type_check_ast(ctx, ast->exprstmt.next); return NULL; - } // case - case AST_STATEMENT_IF: - { - IfStatement *stmt = (IfStatement *) ast; + case MOJOSHADER_AST_STATEMENT_IF: push_scope(ctx); // new scope for "if ((int x = blah()) != 0)" - type_check_ast(ctx, stmt->expr); - type_check_ast(ctx, stmt->statement); + type_check_ast(ctx, ast->ifstmt.expr); + type_check_ast(ctx, ast->ifstmt.statement); pop_scope(ctx); - type_check_ast(ctx, stmt->next); + type_check_ast(ctx, ast->ifstmt.next); return NULL; - } // case - case AST_STATEMENT_TYPEDEF: - { - TypedefStatement *stmt = (TypedefStatement *) ast; - type_check_ast(ctx, stmt->type_info); - type_check_ast(ctx, stmt->next); + case MOJOSHADER_AST_STATEMENT_TYPEDEF: + type_check_ast(ctx, ast->typedefstmt.type_info); + type_check_ast(ctx, ast->typedefstmt.next); return NULL; - } // case - case AST_STATEMENT_SWITCH: + case MOJOSHADER_AST_STATEMENT_SWITCH: { - SwitchStatement *stmt = (SwitchStatement *) ast; - SwitchCases *cases = stmt->cases; - const char *datatype = type_check_ast(ctx, stmt->expr); + MOJOSHADER_astSwitchCases *cases = ast->switchstmt.cases; + datatype = type_check_ast(ctx, ast->switchstmt.expr); while (cases) { - const char *datatype2 = type_check_ast(ctx, cases->expr); + datatype2 = type_check_ast(ctx, cases->expr); add_type_coercion(ctx, NULL, datatype, &cases->expr, datatype2); type_check_ast(ctx, cases->statement); @@ -2825,161 +1623,122 @@ datatype = "!!! FIXME"; return NULL; } // case - case AST_SWITCH_CASE: - { - assert(0 && "Should have been handled by AST_STATEMENT_SWITCH."); + case MOJOSHADER_AST_SWITCH_CASE: + assert(0 && "Should be done by MOJOSHADER_AST_STATEMENT_SWITCH."); return NULL; - } // case - case AST_STATEMENT_STRUCT: - { - StructStatement *stmt = (StructStatement *) ast; - type_check_ast(ctx, stmt->struct_info); - type_check_ast(ctx, stmt->next); + case MOJOSHADER_AST_STATEMENT_STRUCT: + type_check_ast(ctx, ast->structstmt.struct_info); + type_check_ast(ctx, ast->structstmt.next); return NULL; - } // case - case AST_STATEMENT_VARDECL: - { - VarDeclStatement *stmt = (VarDeclStatement *) ast; - type_check_ast(ctx, stmt->declaration); - type_check_ast(ctx, stmt->next); + case MOJOSHADER_AST_STATEMENT_VARDECL: + type_check_ast(ctx, ast->vardeclstmt.declaration); + type_check_ast(ctx, ast->vardeclstmt.next); return NULL; - } // case - case AST_STATEMENT_BLOCK: - { - BlockStatement *bs = (BlockStatement *) ast; + case MOJOSHADER_AST_STATEMENT_BLOCK: push_scope(ctx); // new vars declared here live until '}'. - type_check_ast(ctx, bs->statements); + type_check_ast(ctx, ast->blockstmt.statements); pop_scope(ctx); - type_check_ast(ctx, bs->next); + type_check_ast(ctx, ast->blockstmt.next); return NULL; - } // case - case AST_STATEMENT_FOR: - { - ForStatement *fs = (ForStatement *) ast; + case MOJOSHADER_AST_STATEMENT_FOR: push_scope(ctx); // new scope for "for (int x = 0; ...)" - type_check_ast(ctx, fs->var_decl); - type_check_ast(ctx, fs->initializer); - type_check_ast(ctx, fs->looptest); - type_check_ast(ctx, fs->counter); - type_check_ast(ctx, fs->statement); + type_check_ast(ctx, ast->forstmt.var_decl); + type_check_ast(ctx, ast->forstmt.initializer); + type_check_ast(ctx, ast->forstmt.looptest); + type_check_ast(ctx, ast->forstmt.counter); + type_check_ast(ctx, ast->forstmt.statement); pop_scope(ctx); - type_check_ast(ctx, fs->next); + type_check_ast(ctx, ast->forstmt.next); return NULL; - } // case - case AST_STATEMENT_DO: - { - DoStatement *ds = (DoStatement *) ast; - type_check_ast(ctx, ds->statement); + case MOJOSHADER_AST_STATEMENT_DO: + type_check_ast(ctx, ast->dostmt.statement); push_scope(ctx); // new scope for "while ((int x = blah()) != 0)" - type_check_ast(ctx, ds->expr); + type_check_ast(ctx, ast->dostmt.expr); pop_scope(ctx); - type_check_ast(ctx, ds->next); + type_check_ast(ctx, ast->dostmt.next); return NULL; - } // case - case AST_STATEMENT_WHILE: - { - WhileStatement *ws = (WhileStatement *) ast; + case MOJOSHADER_AST_STATEMENT_WHILE: push_scope(ctx); // new scope for "while ((int x = blah()) != 0)" - type_check_ast(ctx, ws->expr); - type_check_ast(ctx, ws->statement); + type_check_ast(ctx, ast->whilestmt.expr); + type_check_ast(ctx, ast->whilestmt.statement); pop_scope(ctx); - type_check_ast(ctx, ws->next); + type_check_ast(ctx, ast->whilestmt.next); return NULL; - } // case - case AST_STATEMENT_RETURN: - { - ReturnStatement *stmt = (ReturnStatement *) ast; - type_check_ast(ctx, stmt->expr); - type_check_ast(ctx, stmt->next); - return NULL; - } // case + case MOJOSHADER_AST_STATEMENT_RETURN: + type_check_ast(ctx, ast->returnstmt.expr); + type_check_ast(ctx, ast->returnstmt.next); - case AST_COMPUNIT_FUNCTION: - { - CompilationUnitFunction *unit = (CompilationUnitFunction *) ast; - const char *sig = get_usertype(ctx, unit->declaration->identifier); - if (sig == NULL) + case MOJOSHADER_AST_COMPUNIT_FUNCTION: + datatype = get_usertype(ctx, ast->funcunit.declaration->identifier); + if (datatype == NULL) { // add function declaration if we've not seen it. - sig = unit->declaration->datatype; - push_usertype(ctx, unit->declaration->identifier, sig); + datatype = ast->funcunit.declaration->datatype; + push_usertype(ctx, ast->funcunit.declaration->identifier, datatype); } // if // declarations can be done multiple times if they match. - else if (sig != unit->declaration->datatype) + else if (datatype != ast->funcunit.declaration->datatype) { // !!! FIXME: function overloading is legal. fail(ctx, "function sigs don't match"); } // else push_scope(ctx); // so function params are in function scope. - type_check_ast(ctx, unit->declaration); - if (unit->definition == NULL) + type_check_ast(ctx, ast->funcunit.declaration); + if (ast->funcunit.definition == NULL) pop_scope(ctx); else { - type_check_ast(ctx, unit->definition); + type_check_ast(ctx, ast->funcunit.definition); pop_scope(ctx); - push_variable(ctx, unit->declaration->identifier, sig); + push_variable(ctx, ast->funcunit.declaration->identifier, datatype); } // else - type_check_ast(ctx, unit->next); + type_check_ast(ctx, ast->funcunit.next); return NULL; - } // case - case AST_COMPUNIT_TYPEDEF: - { - CompilationUnitTypedef *unit = (CompilationUnitTypedef *) ast; - type_check_ast(ctx, unit->type_info); - type_check_ast(ctx, unit->next); + case MOJOSHADER_AST_COMPUNIT_TYPEDEF: + type_check_ast(ctx, ast->typedefunit.type_info); + type_check_ast(ctx, ast->typedefunit.next); return NULL; - } // case - case AST_COMPUNIT_STRUCT: - { - CompilationUnitStruct *unit = (CompilationUnitStruct *) ast; - type_check_ast(ctx, unit->struct_info); - type_check_ast(ctx, unit->next); + case MOJOSHADER_AST_COMPUNIT_STRUCT: + type_check_ast(ctx, ast->structunit.struct_info); + type_check_ast(ctx, ast->structunit.next); return NULL; - } // case - case AST_COMPUNIT_VARIABLE: - { - CompilationUnitVariable *unit = (CompilationUnitVariable *) ast; - type_check_ast(ctx, unit->declaration); - type_check_ast(ctx, unit->next); + case MOJOSHADER_AST_COMPUNIT_VARIABLE: + type_check_ast(ctx, ast->varunit.declaration); + type_check_ast(ctx, ast->varunit.next); return NULL; - } // case - case AST_SCALAR_OR_ARRAY: - { - ScalarOrArray *soa = (ScalarOrArray *) ast; - const char *datatype = type_check_ast(ctx, soa->dimension); + case MOJOSHADER_AST_SCALAR_OR_ARRAY: + datatype = type_check_ast(ctx, ast->soa.dimension); require_integer_datatype(ctx, datatype); - assert(0); // !!! FIXME: figure out datatype of identifier. +assert(0); // !!! FIXME: figure out datatype of identifier. return NULL; - } // case - case AST_TYPEDEF: + case MOJOSHADER_AST_TYPEDEF: { - ScalarOrArray *soa = ((Typedef *) ast)->details; - const char *datatype = get_usertype(ctx, soa->identifier); + MOJOSHADER_astScalarOrArray *soa = ast->typdef.details; + datatype = get_usertype(ctx, soa->identifier); if (datatype != NULL) { fail(ctx, "typedef already defined"); return datatype; } // if - datatype = ((Typedef *) ast)->datatype; + datatype = ast->typdef.datatype; - // don't walk into AST_SCALAR_OR_ARRAY here, since it can't resolve the identifier. + // don't walk into MOJOSHADER_AST_SCALAR_OR_ARRAY here, since it can't resolve the identifier. // !!! FIXME: SCALAR_OR_ARRAY is sort of a mess. // !!! FIXME: this part is cut and paste. assert( (soa->isarray && soa->dimension) || @@ -2987,110 +1746,97 @@ datatype = "!!! FIXME"; if (soa->isarray) { - if (soa->dimension->ast.type != AST_OP_INT_LITERAL) + if (soa->dimension->ast.type != MOJOSHADER_AST_OP_INT_LITERAL) { fail(ctx, "Expected integer"); delete_expr(ctx, soa->dimension); // make sane. soa->dimension = new_literal_int_expr(ctx, 1); } // if - int64 dim = ((ExpressionIntLiteral *) soa->dimension)->value; - datatype = stringcache_fmt(ctx->strcache, "a{%lld,%s}", - (long long) dim, datatype); + const int dim = ((MOJOSHADER_astExpressionIntLiteral *) soa->dimension)->value; + datatype = stringcache_fmt(ctx->strcache, "a{%d,%s}", + dim, datatype); } // if - ((Typedef *) ast)->datatype = datatype; // make sane. + ast->typdef.datatype = datatype; // make sane. push_usertype(ctx, soa->identifier, datatype); return datatype; } // case - case AST_FUNCTION_PARAMS: - { - FunctionParameters *params = (FunctionParameters *) ast; - push_variable(ctx, params->identifier, params->datatype); - type_check_ast(ctx, params->initializer); - type_check_ast(ctx, params->next); + case MOJOSHADER_AST_FUNCTION_PARAMS: + push_variable(ctx, ast->params.identifier, ast->params.datatype); + type_check_ast(ctx, ast->params.initializer); + type_check_ast(ctx, ast->params.next); return NULL; - } // case - case AST_FUNCTION_SIGNATURE: - { - FunctionSignature *sig = (FunctionSignature *) ast; - type_check_ast(ctx, sig->params); - return sig->datatype; - } // case + case MOJOSHADER_AST_FUNCTION_SIGNATURE: + type_check_ast(ctx, ast->funcsig.params); + return ast->funcsig.datatype; - case AST_STRUCT_DECLARATION: - { - StructDeclaration *decl = (StructDeclaration *) ast; - const char *datatype = type_check_ast(ctx, decl->members); + case MOJOSHADER_AST_STRUCT_DECLARATION: + datatype = type_check_ast(ctx, ast->structdecl.members); datatype = stringcache_fmt(ctx->strcache, "X{%s}", datatype); - push_usertype(ctx, decl->name, datatype); - return stringcache_fmt(ctx->strcache, "U{%s}", decl->name); - } // case - - case AST_STRUCT_MEMBER: - { - StructMembers *members = (StructMembers *) ast; - const char *dtype = type_check_ast(ctx, members->details); - const char *dtype2 = type_check_ast(ctx, members->next); - if (dtype2) - return stringcache_fmt(ctx->strcache, "%s%s", dtype, dtype2); - return dtype; - } // case + push_usertype(ctx, ast->structdecl.name, datatype); + return stringcache_fmt(ctx->strcache, "U{%s}", ast->structdecl.name); - case AST_VARIABLE_DECLARATION: - { - VariableDeclaration *decl = (VariableDeclaration *) ast; - ScalarOrArray *soa = decl->details; - const char *datatype; - const char *datatype2; + case MOJOSHADER_AST_STRUCT_MEMBER: + datatype = type_check_ast(ctx, ast->structmembers.details); + datatype2 = type_check_ast(ctx, ast->structmembers.next); + if (datatype2) + { + return stringcache_fmt(ctx->strcache, "%s%s", + datatype, datatype2); + } // if + return datatype; + case MOJOSHADER_AST_VARIABLE_DECLARATION: // this is true now, but we'll fill in ->datatype no matter what. - assert( (decl->datatype && !decl->anonymous_datatype) || - (!decl->datatype && decl->anonymous_datatype) ); + assert((ast->vardecl.datatype && !ast->vardecl.anonymous_datatype) || + (!ast->vardecl.datatype && ast->vardecl.anonymous_datatype)); // fix up if necessary. - if (decl->anonymous_datatype != NULL) - decl->datatype = type_check_ast(ctx, decl->anonymous_datatype); - datatype = decl->datatype; + if (ast->vardecl.anonymous_datatype != NULL) + ast->vardecl.datatype = type_check_ast(ctx, ast->vardecl.anonymous_datatype); + datatype = ast->vardecl.datatype; - // don't walk into AST_SCALAR_OR_ARRAY here, since it can't resolve the identifier. + // don't walk into MOJOSHADER_AST_SCALAR_OR_ARRAY here, since it can't resolve the identifier. // !!! FIXME: SCALAR_OR_ARRAY is sort of a mess. // !!! FIXME: this part is cut and paste. - assert( (soa->isarray && soa->dimension) || - (!soa->isarray && !soa->dimension) ); + assert( (ast->vardecl.details->isarray && + ast->vardecl.details->dimension) || + (!ast->vardecl.details->isarray && + !ast->vardecl.details->dimension) ); - if (soa->isarray) + if (ast->vardecl.details->isarray) { - if (soa->dimension->ast.type != AST_OP_INT_LITERAL) + MOJOSHADER_astScalarOrArray *soa = ast->vardecl.details; + if (soa->dimension->ast.type != MOJOSHADER_AST_OP_INT_LITERAL) { fail(ctx, "Expected integer"); delete_expr(ctx, soa->dimension); // make sane. soa->dimension = new_literal_int_expr(ctx, 1); } // if - int64 dim = ((ExpressionIntLiteral *) soa->dimension)->value; - datatype = stringcache_fmt(ctx->strcache, "a{%lld,%s}", - (long long) dim, datatype); + const int dim = ((MOJOSHADER_astExpressionIntLiteral *) soa->dimension)->value; + datatype = stringcache_fmt(ctx->strcache, "a{%d,%s}", + dim, datatype); } // if - decl->datatype = datatype; // make sane. - push_variable(ctx, soa->identifier, datatype); - datatype2 = type_check_ast(ctx, decl->initializer); - add_type_coercion(ctx, NULL, datatype, &decl->initializer, datatype2); + ast->vardecl.datatype = datatype; // make sane. + push_variable(ctx, ast->vardecl.details->identifier, datatype); + datatype2 = type_check_ast(ctx, ast->vardecl.initializer); + add_type_coercion(ctx, NULL, datatype, &ast->vardecl.initializer, datatype2); - type_check_ast(ctx, decl->annotations); - type_check_ast(ctx, decl->lowlevel); + type_check_ast(ctx, ast->vardecl.annotations); + type_check_ast(ctx, ast->vardecl.lowlevel); - datatype2 = type_check_ast(ctx, decl->next); + datatype2 = type_check_ast(ctx, ast->vardecl.next); assert(datatype == datatype2); return datatype; - } // case - case AST_ANNOTATION: + case MOJOSHADER_AST_ANNOTATION: { - Annotations *anno = (Annotations *) ast; + MOJOSHADER_astAnnotations *anno = &ast->annotations; while (anno) { type_check_ast(ctx, anno->initializer); @@ -3099,8 +1845,8 @@ datatype = "!!! FIXME"; return NULL; } // case - case AST_PACK_OFFSET: - case AST_VARIABLE_LOWLEVEL: + case MOJOSHADER_AST_PACK_OFFSET: + case MOJOSHADER_AST_VARIABLE_LOWLEVEL: return NULL; // no-op (for now, at least). default: @@ -3115,9 +1861,13 @@ datatype = "!!! FIXME"; static inline void semantic_analysis(Context *ctx) { type_check_ast(ctx, ctx->ast); + // !!! FIXME: build an IR here. - delete_compilation_unit(ctx, ctx->ast); // done with the AST, nuke it. + + // done with the AST, nuke it. + delete_compilation_unit(ctx, (MOJOSHADER_astCompilationUnit *) ctx->ast); ctx->ast = NULL; + // !!! FIXME: do everything else. :) } // semantic_analysis @@ -3355,7 +2105,7 @@ static void destroy_context(Context *ctx) void *d = ctx->malloc_data; // !!! FIXME: free ctx->errors - delete_compilation_unit(ctx, ctx->ast); + delete_compilation_unit(ctx, (MOJOSHADER_astCompilationUnit*)ctx->ast); destroy_symbolmap(ctx, &ctx->usertypes); destroy_symbolmap(ctx, &ctx->variables); @@ -3552,30 +2302,115 @@ static void parse_source(Context *ctx, const char *filename, } // parse_source -void MOJOSHADER_compile(const char *filename, - const char *source, unsigned int sourcelen, - const MOJOSHADER_preprocessorDefine *defines, - unsigned int define_count, - MOJOSHADER_includeOpen include_open, - MOJOSHADER_includeClose include_close, - MOJOSHADER_malloc m, MOJOSHADER_free f, void *d) +#if 0 +/* !!! FIXME: most of these ints should be unsigned. */ +typedef struct MOJOSHADER_astData +{ + /* + * The number of elements pointed to by (errors). + */ + int error_count; + + /* + * (error_count) elements of data that specify errors that were generated + * by parsing this shader. + * This can be NULL if there were no errors or if (error_count) is zero. + * Note that this will only produce errors for syntax problems. Most of + * the things we expect a compiler to produce errors for--incompatible + * types, unknown identifiers, etc--are not checked at all during + * initial generation of the syntax tree...bogus programs that would + * fail to compile will pass here without error, if they are syntactically + * correct! + */ + MOJOSHADER_error *errors; + + /* + * The name of the source profile used to parse the shader. Will be NULL + * on error. + */ + const char *source_profile; + + /* + * The actual syntax tree. You are responsible for walking it yourself. + * CompilationUnits are always the top of the tree (functions, typedefs, + * global variables, etc). + */ + const MOJOSHADER_astNode *ast; + + /* + * This is the malloc implementation you passed to MOJOSHADER_parse(). + */ + MOJOSHADER_malloc malloc; + + /* + * This is the free implementation you passed to MOJOSHADER_parse(). + */ + MOJOSHADER_free free; + + /* + * This is the pointer you passed as opaque data for your allocator. + */ + void *malloc_data; +} MOJOSHADER_astData; +#endif + + +// !!! FIXME: move this (and a lot of other things) to mojoshader_ast.c. +const MOJOSHADER_astData *MOJOSHADER_parseAst(const char *srcprofile, + const char *filename, const char *source, + unsigned int sourcelen, + const MOJOSHADER_preprocessorDefine *defs, + unsigned int define_count, + MOJOSHADER_includeOpen include_open, + MOJOSHADER_includeClose include_close, + MOJOSHADER_malloc m, MOJOSHADER_free f, + void *d) { Context *ctx = build_context(m, f, d); if (!ctx) - return; // !!! FIXME: report error. + return NULL; // !!! FIXME: report error. - parse_source(ctx, filename, source, sourcelen, defines, define_count, + parse_source(ctx, filename, source, sourcelen, defs, define_count, include_open, include_close); - // !!! FIXME: check (ctx->ast != NULL), and maybe isfail(). + destroy_context(ctx); + + // !!! FIXME: report success/error. + return NULL; +} // MOJOSHADER_ast + + +void MOJOSHADER_freeAstData(const MOJOSHADER_astData *data) +{ +} // MOJOSHADER_freeAstData + + + +const MOJOSHADER_compileData *MOJOSHADER_compile(const char *srcprofile, + const char *filename, const char *source, + unsigned int sourcelen, + const MOJOSHADER_preprocessorDefine *defs, + unsigned int define_count, + MOJOSHADER_includeOpen include_open, + MOJOSHADER_includeClose include_close, + MOJOSHADER_malloc m, MOJOSHADER_free f, + void *d) +{ + Context *ctx = build_context(m, f, d); + if (!ctx) + return NULL; // !!! FIXME: report error. - print_ast(0, ctx->ast); + parse_source(ctx, filename, source, sourcelen, defs, define_count, + include_open, include_close); + + // !!! FIXME: check (ctx->ast != NULL), and maybe isfail(). semantic_analysis(ctx); destroy_context(ctx); // !!! FIXME: report success/error. + return NULL; } // MOJOSHADER_compile // end of mojoshader_compiler.c ... diff --git a/mojoshader_parser_hlsl.lemon b/mojoshader_parser_hlsl.lemon index 5e23b848..d31445f9 100644 --- a/mojoshader_parser_hlsl.lemon +++ b/mojoshader_parser_hlsl.lemon @@ -75,14 +75,14 @@ // The rules... -shader ::= compilation_units(B). { assert(ctx->ast == NULL); REVERSE_LINKED_LIST(CompilationUnit, B); ctx->ast = B; } +shader ::= compilation_units(B). { assert(ctx->ast == NULL); REVERSE_LINKED_LIST(MOJOSHADER_astCompilationUnit, B); ctx->ast = (MOJOSHADER_astNode *) B; } -%type compilation_units { CompilationUnit * } +%type compilation_units { MOJOSHADER_astCompilationUnit * } %destructor compilation_units { delete_compilation_unit(ctx, $$); } compilation_units(A) ::= compilation_unit(B). { A = B; } compilation_units(A) ::= compilation_units(B) compilation_unit(C). { if (C) { C->next = B; A = C; } } -%type compilation_unit { CompilationUnit * } +%type compilation_unit { MOJOSHADER_astCompilationUnit * } %destructor compilation_unit { delete_compilation_unit(ctx, $$); } //compilation_unit(A) ::= PRAGMA . { A = NULL; } // !!! FIXME: deal with pragmas. compilation_unit(A) ::= variable_declaration(B). { A = new_global_variable(ctx, B); } @@ -92,20 +92,20 @@ compilation_unit(A) ::= typedef(B). { A = new_global_typedef(ctx, B); } compilation_unit(A) ::= struct_declaration(B) SEMICOLON. { A = new_global_struct(ctx, B); } //compilation_unit(A) ::= error SEMICOLON. { A = NULL; } // !!! FIXME: research using the error nonterminal -%type typedef { Typedef * } +%type typedef { MOJOSHADER_astTypedef * } %destructor typedef { delete_typedef(ctx, $$); } // !!! FIXME: should CONST be here, or in datatype? typedef(A) ::= TYPEDEF CONST datatype(B) scalar_or_array(C). { A = new_typedef(ctx, 1, B, C); push_usertype(ctx, C->identifier, NULL); } typedef(A) ::= TYPEDEF datatype(B) scalar_or_array(C). { A = new_typedef(ctx, 0, B, C); push_usertype(ctx, C->identifier, NULL); } -%type function_signature { FunctionSignature * } +%type function_signature { MOJOSHADER_astFunctionSignature * } %destructor function_signature { delete_function_signature(ctx, $$); } function_signature(A) ::= function_storageclass(B) function_details(C) semantic(D). { A = C; A->storage_class = B; A->semantic = D; } function_signature(A) ::= function_storageclass(B) function_details(C). { A = C; A->storage_class = B; } function_signature(A) ::= function_details(B) semantic(C). { A = B; A->semantic = C; } function_signature(A) ::= function_details(B). { A = B; } -%type function_details { FunctionSignature * } +%type function_details { MOJOSHADER_astFunctionSignature * } %destructor function_details { delete_function_signature(ctx, $$); } function_details(A) ::= datatype(B) IDENTIFIER(C) LPAREN function_parameters(D) RPAREN. { A = new_function_signature(ctx, B, C.string, D); } function_details(A) ::= VOID IDENTIFIER(B) LPAREN function_parameters(C) RPAREN. { A = new_function_signature(ctx, NULL, B.string, C); } @@ -116,87 +116,87 @@ function_details(A) ::= VOID IDENTIFIER(B) LPAREN function_parameters(C) RPAREN. // !!! FIXME: Also, the docs say "one of" inline or target, but I bet you can // !!! FIXME: specify both. -%type function_storageclass { FunctionStorageClass } +%type function_storageclass { MOJOSHADER_astFunctionStorageClass } //function_storageclass(A) ::= target(B). { A = B; } -function_storageclass(A) ::= INLINE. { A = FNSTORECLS_INLINE; } +function_storageclass(A) ::= INLINE. { A = MOJOSHADER_AST_FNSTORECLS_INLINE; } -%type function_parameters { FunctionParameters * } +%type function_parameters { MOJOSHADER_astFunctionParameters * } %destructor function_parameters { delete_function_params(ctx, $$); } function_parameters(A) ::= VOID. { A = NULL; } -function_parameters(A) ::= function_parameter_list(B). { REVERSE_LINKED_LIST(FunctionParameters, B); A = B; } +function_parameters(A) ::= function_parameter_list(B). { REVERSE_LINKED_LIST(MOJOSHADER_astFunctionParameters, B); A = B; } function_parameters(A) ::= . { A = NULL; } -%type function_parameter_list { FunctionParameters * } +%type function_parameter_list { MOJOSHADER_astFunctionParameters * } %destructor function_parameter_list { delete_function_params(ctx, $$); } function_parameter_list(A) ::= function_parameter(B). { A = B; } function_parameter_list(A) ::= function_parameter_list(B) COMMA function_parameter(C). { C->next = B; A = C; } // !!! FIXME: this is pretty unreadable. -%type function_parameter { FunctionParameters * } +%type function_parameter { MOJOSHADER_astFunctionParameters * } %destructor function_parameter { delete_function_params(ctx, $$); } function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) semantic(E) interpolation_mod(F) initializer(G). { A = new_function_param(ctx, B, C, D.string, E, F, G); } function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) semantic(E) interpolation_mod(F). { A = new_function_param(ctx, B, C, D.string, E, F, NULL); } -function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) semantic(E) initializer(F). { A = new_function_param(ctx, B, C, D.string, E, INTERPMOD_NONE, F); } -function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) semantic(E). { A = new_function_param(ctx, B, C, D.string, E, INTERPMOD_NONE, NULL); } +function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) semantic(E) initializer(F). { A = new_function_param(ctx, B, C, D.string, E, MOJOSHADER_AST_INTERPMOD_NONE, F); } +function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) semantic(E). { A = new_function_param(ctx, B, C, D.string, E, MOJOSHADER_AST_INTERPMOD_NONE, NULL); } function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) interpolation_mod(E) initializer(F). { A = new_function_param(ctx, B, C, D.string, NULL, E, F); } function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) interpolation_mod(E). { A = new_function_param(ctx, B, C, D.string, NULL, E, NULL); } -function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) initializer(E). { A = new_function_param(ctx, B, C, D.string, NULL, INTERPMOD_NONE, E); } -function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D). { A = new_function_param(ctx, B, C, D.string, NULL, INTERPMOD_NONE, NULL); } -function_parameter(A) ::= datatype(B) IDENTIFIER(C) semantic(D) interpolation_mod(E) initializer(F). { A = new_function_param(ctx, INPUTMOD_NONE, B, C.string, D, E, F); } -function_parameter(A) ::= datatype(B) IDENTIFIER(C) semantic(D) interpolation_mod(E). { A = new_function_param(ctx, INPUTMOD_NONE, B, C.string, D, E, NULL); } -function_parameter(A) ::= datatype(B) IDENTIFIER(C) semantic(D) initializer(E). { A = new_function_param(ctx, INPUTMOD_NONE, B, C.string, D, INTERPMOD_NONE, E); } -function_parameter(A) ::= datatype(B) IDENTIFIER(C) semantic(D). { A = new_function_param(ctx, INPUTMOD_NONE, B, C.string, D, INTERPMOD_NONE, NULL); } -function_parameter(A) ::= datatype(B) IDENTIFIER(C) interpolation_mod(D) initializer(E). { A = new_function_param(ctx, INPUTMOD_NONE, B, C.string, NULL, D, E); } -function_parameter(A) ::= datatype(B) IDENTIFIER(C) interpolation_mod(D). { A = new_function_param(ctx, INPUTMOD_NONE, B, C.string, NULL, D, NULL); } -function_parameter(A) ::= datatype(B) IDENTIFIER(C) initializer(D). { A = new_function_param(ctx, INPUTMOD_NONE, B, C.string, NULL, INTERPMOD_NONE, D); } -function_parameter(A) ::= datatype(B) IDENTIFIER(C). { A = new_function_param(ctx, INPUTMOD_NONE, B, C.string, NULL, INTERPMOD_NONE, NULL); } - -%type input_modifier { InputModifier } -input_modifier(A) ::= IN. { A = INPUTMOD_IN; } -input_modifier(A) ::= INOUT. { A = INPUTMOD_INOUT; } -input_modifier(A) ::= OUT. { A = INPUTMOD_OUT; } -input_modifier(A) ::= IN OUT. { A = INPUTMOD_INOUT; } -input_modifier(A) ::= OUT IN. { A = INPUTMOD_INOUT; } -input_modifier(A) ::= UNIFORM. { A = INPUTMOD_UNIFORM; } +function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D) initializer(E). { A = new_function_param(ctx, B, C, D.string, NULL, MOJOSHADER_AST_INTERPMOD_NONE, E); } +function_parameter(A) ::= input_modifier(B) datatype(C) IDENTIFIER(D). { A = new_function_param(ctx, B, C, D.string, NULL, MOJOSHADER_AST_INTERPMOD_NONE, NULL); } +function_parameter(A) ::= datatype(B) IDENTIFIER(C) semantic(D) interpolation_mod(E) initializer(F). { A = new_function_param(ctx, MOJOSHADER_AST_INPUTMOD_NONE, B, C.string, D, E, F); } +function_parameter(A) ::= datatype(B) IDENTIFIER(C) semantic(D) interpolation_mod(E). { A = new_function_param(ctx, MOJOSHADER_AST_INPUTMOD_NONE, B, C.string, D, E, NULL); } +function_parameter(A) ::= datatype(B) IDENTIFIER(C) semantic(D) initializer(E). { A = new_function_param(ctx, MOJOSHADER_AST_INPUTMOD_NONE, B, C.string, D, MOJOSHADER_AST_INTERPMOD_NONE, E); } +function_parameter(A) ::= datatype(B) IDENTIFIER(C) semantic(D). { A = new_function_param(ctx, MOJOSHADER_AST_INPUTMOD_NONE, B, C.string, D, MOJOSHADER_AST_INTERPMOD_NONE, NULL); } +function_parameter(A) ::= datatype(B) IDENTIFIER(C) interpolation_mod(D) initializer(E). { A = new_function_param(ctx, MOJOSHADER_AST_INPUTMOD_NONE, B, C.string, NULL, D, E); } +function_parameter(A) ::= datatype(B) IDENTIFIER(C) interpolation_mod(D). { A = new_function_param(ctx, MOJOSHADER_AST_INPUTMOD_NONE, B, C.string, NULL, D, NULL); } +function_parameter(A) ::= datatype(B) IDENTIFIER(C) initializer(D). { A = new_function_param(ctx, MOJOSHADER_AST_INPUTMOD_NONE, B, C.string, NULL, MOJOSHADER_AST_INTERPMOD_NONE, D); } +function_parameter(A) ::= datatype(B) IDENTIFIER(C). { A = new_function_param(ctx, MOJOSHADER_AST_INPUTMOD_NONE, B, C.string, NULL, MOJOSHADER_AST_INTERPMOD_NONE, NULL); } + +%type input_modifier { MOJOSHADER_astInputModifier } +input_modifier(A) ::= IN. { A = MOJOSHADER_AST_INPUTMOD_IN; } +input_modifier(A) ::= INOUT. { A = MOJOSHADER_AST_INPUTMOD_INOUT; } +input_modifier(A) ::= OUT. { A = MOJOSHADER_AST_INPUTMOD_OUT; } +input_modifier(A) ::= IN OUT. { A = MOJOSHADER_AST_INPUTMOD_INOUT; } +input_modifier(A) ::= OUT IN. { A = MOJOSHADER_AST_INPUTMOD_INOUT; } +input_modifier(A) ::= UNIFORM. { A = MOJOSHADER_AST_INPUTMOD_UNIFORM; } %type semantic { const char * } semantic(A) ::= COLON IDENTIFIER(B). { A = B.string; } // DX10 only? -%type interpolation_mod { InterpolationModifier } -interpolation_mod(A) ::= LINEAR. { A = INTERPMOD_LINEAR; } -interpolation_mod(A) ::= CENTROID. { A = INTERPMOD_CENTROID; } -interpolation_mod(A) ::= NOINTERPOLATION. { A = INTERPMOD_NOINTERPOLATION; } -interpolation_mod(A) ::= NOPERSPECTIVE. { A = INTERPMOD_NOPERSPECTIVE; } -interpolation_mod(A) ::= SAMPLE. { A = INTERPMOD_SAMPLE; } - -%type variable_declaration { VariableDeclaration * } +%type interpolation_mod { MOJOSHADER_astInterpolationModifier } +interpolation_mod(A) ::= LINEAR. { A = MOJOSHADER_AST_INTERPMOD_LINEAR; } +interpolation_mod(A) ::= CENTROID. { A = MOJOSHADER_AST_INTERPMOD_CENTROID; } +interpolation_mod(A) ::= NOINTERPOLATION. { A = MOJOSHADER_AST_INTERPMOD_NOINTERPOLATION; } +interpolation_mod(A) ::= NOPERSPECTIVE. { A = MOJOSHADER_AST_INTERPMOD_NOPERSPECTIVE; } +interpolation_mod(A) ::= SAMPLE. { A = MOJOSHADER_AST_INTERPMOD_SAMPLE; } + +%type variable_declaration { MOJOSHADER_astVariableDeclaration * } %destructor variable_declaration { delete_variable_declaration(ctx, $$); } -variable_declaration(A) ::= variable_attribute_list(B) datatype(C) variable_declaration_details_list(D) SEMICOLON. { REVERSE_LINKED_LIST(VariableDeclaration, D); A = D; A->attributes = B; A->datatype = C; } -variable_declaration(A) ::= datatype(B) variable_declaration_details_list(C) SEMICOLON. { REVERSE_LINKED_LIST(VariableDeclaration, C); A = C; A->datatype = B; } -variable_declaration(A) ::= struct_declaration(B) variable_declaration_details_list(C) SEMICOLON. { REVERSE_LINKED_LIST(VariableDeclaration, C); A = C; A->anonymous_datatype = B; } +variable_declaration(A) ::= variable_attribute_list(B) datatype(C) variable_declaration_details_list(D) SEMICOLON. { REVERSE_LINKED_LIST(MOJOSHADER_astVariableDeclaration, D); A = D; A->attributes = B; A->datatype = C; } +variable_declaration(A) ::= datatype(B) variable_declaration_details_list(C) SEMICOLON. { REVERSE_LINKED_LIST(MOJOSHADER_astVariableDeclaration, C); A = C; A->datatype = B; } +variable_declaration(A) ::= struct_declaration(B) variable_declaration_details_list(C) SEMICOLON. { REVERSE_LINKED_LIST(MOJOSHADER_astVariableDeclaration, C); A = C; A->anonymous_datatype = B; } %type variable_attribute_list { int } variable_attribute_list(A) ::= variable_attribute(B). { A = B; } variable_attribute_list(A) ::= variable_attribute_list(B) variable_attribute(C). { A = B | C; } %type variable_attribute { int } -variable_attribute(A) ::= EXTERN. { A = VARATTR_EXTERN; } -variable_attribute(A) ::= NOINTERPOLATION. { A = VARATTR_NOINTERPOLATION; } -variable_attribute(A) ::= SHARED. { A = VARATTR_SHARED; } -variable_attribute(A) ::= STATIC. { A = VARATTR_STATIC; } -variable_attribute(A) ::= UNIFORM. { A = VARATTR_UNIFORM; } -variable_attribute(A) ::= VOLATILE. { A = VARATTR_VOLATILE; } -variable_attribute(A) ::= CONST. { A = VARATTR_CONST; } -variable_attribute(A) ::= ROWMAJOR. { A = VARATTR_ROWMAJOR; } -variable_attribute(A) ::= COLUMNMAJOR. { A = VARATTR_COLUMNMAJOR; } - -%type variable_declaration_details_list { VariableDeclaration * } +variable_attribute(A) ::= EXTERN. { A = MOJOSHADER_AST_VARATTR_EXTERN; } +variable_attribute(A) ::= NOINTERPOLATION. { A = MOJOSHADER_AST_VARATTR_NOINTERPOLATION; } +variable_attribute(A) ::= SHARED. { A = MOJOSHADER_AST_VARATTR_SHARED; } +variable_attribute(A) ::= STATIC. { A = MOJOSHADER_AST_VARATTR_STATIC; } +variable_attribute(A) ::= UNIFORM. { A = MOJOSHADER_AST_VARATTR_UNIFORM; } +variable_attribute(A) ::= VOLATILE. { A = MOJOSHADER_AST_VARATTR_VOLATILE; } +variable_attribute(A) ::= CONST. { A = MOJOSHADER_AST_VARATTR_CONST; } +variable_attribute(A) ::= ROWMAJOR. { A = MOJOSHADER_AST_VARATTR_ROWMAJOR; } +variable_attribute(A) ::= COLUMNMAJOR. { A = MOJOSHADER_AST_VARATTR_COLUMNMAJOR; } + +%type variable_declaration_details_list { MOJOSHADER_astVariableDeclaration * } %destructor variable_declaration_details_list { delete_variable_declaration(ctx, $$); } variable_declaration_details_list(A) ::= variable_declaration_details(B). { A = B; } variable_declaration_details_list(A) ::= variable_declaration_details_list(B) COMMA variable_declaration_details(C). { A = C; A->next = B; } -%type variable_declaration_details { VariableDeclaration * } +%type variable_declaration_details { MOJOSHADER_astVariableDeclaration * } %destructor variable_declaration_details { delete_variable_declaration(ctx, $$); } variable_declaration_details(A) ::= scalar_or_array(B) semantic(C) annotations(D) initializer(E) variable_lowlevel(F). { A = new_variable_declaration(ctx, B, C, D, E, F); } variable_declaration_details(A) ::= scalar_or_array(B) semantic(C) annotations(D) initializer(E). { A = new_variable_declaration(ctx, B, C, D, E, NULL); } @@ -218,35 +218,35 @@ variable_declaration_details(A) ::= scalar_or_array(B). { A = new_variable_decla // !!! FIXME: we don't handle full sampler declarations at the moment. -%type struct_declaration { StructDeclaration * } +%type struct_declaration { MOJOSHADER_astStructDeclaration * } %destructor struct_declaration { delete_struct_declaration(ctx, $$); } -struct_declaration(A) ::= struct_intro(B) LBRACE struct_member_list(C) RBRACE. { REVERSE_LINKED_LIST(StructMembers, C); A = new_struct_declaration(ctx, B, C); } +struct_declaration(A) ::= struct_intro(B) LBRACE struct_member_list(C) RBRACE. { REVERSE_LINKED_LIST(MOJOSHADER_astStructMembers, C); A = new_struct_declaration(ctx, B, C); } // This has to be separate from struct_declaration so that the struct is in the usertypemap when parsing its members. %type struct_intro { const char * } struct_intro(A) ::= STRUCT IDENTIFIER(B). { A = B.string; push_usertype(ctx, A, NULL); } -%type struct_member_list { StructMembers * } +%type struct_member_list { MOJOSHADER_astStructMembers * } %destructor struct_member_list { delete_struct_member(ctx, $$); } struct_member_list(A) ::= struct_member(B). { A = B; } struct_member_list(A) ::= struct_member_list(B) struct_member(C). { A = C; A->next = B; } -%type struct_member { StructMembers * } +%type struct_member { MOJOSHADER_astStructMembers * } %destructor struct_member { delete_struct_member(ctx, $$); } -struct_member(A) ::= interpolation_mod(B) struct_member_details(C). { StructMembers *i = C; A = C; while (i) { i->interpolation_mod = B; i = i->next; } } +struct_member(A) ::= interpolation_mod(B) struct_member_details(C). { MOJOSHADER_astStructMembers *i = C; A = C; while (i) { i->interpolation_mod = B; i = i->next; } } struct_member(A) ::= struct_member_details(B). { A = B; } -%type struct_member_details { StructMembers * } +%type struct_member_details { MOJOSHADER_astStructMembers * } %destructor struct_member_details { delete_struct_member(ctx, $$); } -struct_member_details(A) ::= datatype(B) struct_member_item_list(C) SEMICOLON. { StructMembers *i = C; A = C; while (i) { i->datatype = B; i = i->next; } } +struct_member_details(A) ::= datatype(B) struct_member_item_list(C) SEMICOLON. { MOJOSHADER_astStructMembers *i = C; A = C; while (i) { i->datatype = B; i = i->next; } } -%type struct_member_item_list { StructMembers * } +%type struct_member_item_list { MOJOSHADER_astStructMembers * } %destructor struct_member_item_list { delete_struct_member(ctx, $$); } struct_member_item_list(A) ::= scalar_or_array(B). { A = new_struct_member(ctx, B, NULL); } struct_member_item_list(A) ::= scalar_or_array(B) semantic(C). { A = new_struct_member(ctx, B, C); } struct_member_item_list(A) ::= struct_member_item_list(B) COMMA IDENTIFIER(C). { A = new_struct_member(ctx, new_scalar_or_array(ctx, C.string, 0, NULL), NULL); A->next = B; A->semantic = B->semantic; } -%type variable_lowlevel { VariableLowLevel * } +%type variable_lowlevel { MOJOSHADER_astVariableLowLevel * } %destructor variable_lowlevel { delete_variable_lowlevel(ctx, $$); } variable_lowlevel(A) ::= packoffset(B) register(C). { A = new_variable_lowlevel(ctx, B, C); } variable_lowlevel(A) ::= register(B) packoffset(C). { A = new_variable_lowlevel(ctx, C, B); } @@ -254,13 +254,13 @@ variable_lowlevel(A) ::= packoffset(B). { A = new_variable_lowlevel(ctx, B, NULL variable_lowlevel(A) ::= register(B). { A = new_variable_lowlevel(ctx, NULL, B); } // !!! FIXME: I sort of hate this type name. -%type scalar_or_array { ScalarOrArray * } +%type scalar_or_array { MOJOSHADER_astScalarOrArray * } %destructor scalar_or_array { delete_scalar_or_array(ctx, $$); } scalar_or_array(A) ::= IDENTIFIER(B) LBRACKET RBRACKET. { A = new_scalar_or_array(ctx, B.string, 1, NULL); } scalar_or_array(A) ::= IDENTIFIER(B) LBRACKET expression(C) RBRACKET. { A = new_scalar_or_array(ctx, B.string, 1, C); } scalar_or_array(A) ::= IDENTIFIER(B). { A = new_scalar_or_array(ctx, B.string, 0, NULL); } -%type packoffset { PackOffset * } +%type packoffset { MOJOSHADER_astPackOffset * } %destructor packoffset { delete_pack_offset(ctx, $$); } packoffset(A) ::= COLON PACKOFFSET LPAREN IDENTIFIER(B) DOT IDENTIFIER(C) RPAREN. { A = new_pack_offset(ctx, B.string, C.string); } packoffset(A) ::= COLON PACKOFFSET LPAREN IDENTIFIER(B) RPAREN. { A = new_pack_offset(ctx, B.string, NULL); } @@ -271,31 +271,31 @@ packoffset(A) ::= COLON PACKOFFSET LPAREN IDENTIFIER(B) RPAREN. { A = new_pack_o %type register { const char * } register(A) ::= COLON REGISTER LPAREN IDENTIFIER(B) RPAREN. { A = B.string; } -%type annotations { Annotations * } +%type annotations { MOJOSHADER_astAnnotations * } %destructor annotations { delete_annotation(ctx, $$); } -annotations(A) ::= LT annotation_list(B) GT. { REVERSE_LINKED_LIST(Annotations, B); A = B; } +annotations(A) ::= LT annotation_list(B) GT. { REVERSE_LINKED_LIST(MOJOSHADER_astAnnotations, B); A = B; } -%type annotation_list { Annotations * } +%type annotation_list { MOJOSHADER_astAnnotations * } %destructor annotation_list { delete_annotation(ctx, $$); } annotation_list(A) ::= annotation(B). { A = B; } annotation_list(A) ::= annotation_list(B) annotation(C). { A = C; A->next = B; } // !!! FIXME: can this take a USERTYPE if we typedef'd a scalar type? -%type annotation { Annotations * } +%type annotation { MOJOSHADER_astAnnotations * } %destructor annotation { delete_annotation(ctx, $$); } annotation(A) ::= datatype_scalar(B) initializer(C) SEMICOLON. { A = new_annotation(ctx, B, C); } -%type initializer_block_list { Expression * } +%type initializer_block_list { MOJOSHADER_astExpression * } %destructor initializer_block_list { delete_expr(ctx, $$); } initializer_block_list(A) ::= expression(B). { A = B; } initializer_block_list(A) ::= LBRACE initializer_block_list(B) RBRACE. { A = B; } -initializer_block_list(A) ::= initializer_block_list(B) COMMA initializer_block_list(C). { A = new_binary_expr(ctx, AST_OP_COMMA, B, C); } +initializer_block_list(A) ::= initializer_block_list(B) COMMA initializer_block_list(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_COMMA, B, C); } -%type initializer_block { Expression * } +%type initializer_block { MOJOSHADER_astExpression * } %destructor initializer_block { delete_expr(ctx, $$); } initializer_block(A) ::= LBRACE initializer_block_list(B) RBRACE. { A = B; } -%type initializer { Expression * } +%type initializer { MOJOSHADER_astExpression * } %destructor initializer { delete_expr(ctx, $$); } initializer(A) ::= ASSIGN initializer_block(B). { A = B; } initializer(A) ::= ASSIGN expression(B). { A = B; } @@ -343,12 +343,12 @@ datatype_vector(A) ::= VECTOR LT datatype_scalar(B) COMMA INT_CONSTANT(C) GT. { %type datatype_matrix { const char * } datatype_matrix(A) ::= MATRIX LT datatype_scalar(B) COMMA INT_CONSTANT(C) COMMA INT_CONSTANT(D) GT. { A = stringcache_fmt(ctx->strcache, "M{%d,%d,%s}", (int) C.i64, (int) D.i64, B); } -%type statement_block { Statement * } +%type statement_block { MOJOSHADER_astStatement * } %destructor statement_block { delete_statement(ctx, $$); } statement_block(A) ::= LBRACE RBRACE. { A = new_block_statement(ctx, NULL); } -statement_block(A) ::= LBRACE statement_list(B) RBRACE. { REVERSE_LINKED_LIST(Statement, B); A = new_block_statement(ctx, B); } +statement_block(A) ::= LBRACE statement_list(B) RBRACE. { REVERSE_LINKED_LIST(MOJOSHADER_astStatement, B); A = new_block_statement(ctx, B); } -%type statement_list { Statement * } +%type statement_list { MOJOSHADER_astStatement * } %destructor statement_list { delete_statement(ctx, $$); } statement_list(A) ::= statement(B). { A = B; } statement_list(A) ::= statement_list(B) statement(C). { A = C; A->next = B; } @@ -364,7 +364,7 @@ statement_attribute(A) ::= REMOVEUNUSEDINPUTS. { A = 0; } // !!! FIXME statement_attribute(A) ::= UNUSED. { A = 0; } // !!! FIXME statement_attribute(A) ::= XPS. { A = 0; } // !!! FIXME -%type statement { Statement * } +%type statement { MOJOSHADER_astStatement * } %destructor statement { delete_statement(ctx, $$); } statement(A) ::= BREAK SEMICOLON. { A = new_break_statement(ctx); } statement(A) ::= CONTINUE SEMICOLON. { A = new_continue_statement(ctx); } @@ -376,7 +376,7 @@ statement(A) ::= do_intro(B) DO statement(C) WHILE LPAREN expression(D) RPAREN S statement(A) ::= while_intro(B) LPAREN expression(C) RPAREN statement(D). { A = new_while_statement(ctx, B, C, D); } statement(A) ::= if_intro(B) LPAREN expression(C) RPAREN statement(D). { A = new_if_statement(ctx, B, C, D, NULL); } statement(A) ::= if_intro(B) LPAREN expression(C) RPAREN statement(D) ELSE statement(E). { A = new_if_statement(ctx, B, C, D, E); } -statement(A) ::= switch_intro(B) LPAREN expression(C) RPAREN LBRACE switch_case_list(D) RBRACE. { REVERSE_LINKED_LIST(SwitchCases, D); A = new_switch_statement(ctx, B, C, D); } +statement(A) ::= switch_intro(B) LPAREN expression(C) RPAREN LBRACE switch_case_list(D) RBRACE. { REVERSE_LINKED_LIST(MOJOSHADER_astSwitchCases, D); A = new_switch_statement(ctx, B, C, D); } statement(A) ::= typedef(B). { A = new_typedef_statement(ctx, B); } statement(A) ::= SEMICOLON. { A = new_empty_statement(ctx); } statement(A) ::= expression(B) SEMICOLON. { A = new_expr_statement(ctx, B); } @@ -386,23 +386,23 @@ statement(A) ::= statement_block(B). { A = B; } statement(A) ::= for_statement(B). { A = B; } //statement(A) ::= error SEMICOLON. { A = NULL; } // !!! FIXME: research using the error nonterminal -%type while_intro { int64 } +%type while_intro { int } while_intro(A) ::= LBRACKET UNROLL LPAREN INT_CONSTANT(B) RPAREN RBRACKET WHILE. { A = (B.i64 < 0) ? 0 : B.i64; } while_intro(A) ::= LBRACKET UNROLL RBRACKET WHILE. { A = -1; } while_intro(A) ::= LBRACKET LOOP RBRACKET WHILE. { A = 0; } while_intro(A) ::= WHILE. { A = -2; } -%type for_statement { Statement * } +%type for_statement { MOJOSHADER_astStatement * } %destructor for_statement { delete_statement(ctx, $$); } -for_statement(A) ::= for_intro(B) for_details(C). { A = C; ((ForStatement *) A)->unroll = B; } +for_statement(A) ::= for_intro(B) for_details(C). { A = C; ((MOJOSHADER_astForStatement *) A)->unroll = B; } -%type for_intro { int64 } +%type for_intro { int } for_intro(A) ::= LBRACKET UNROLL LPAREN INT_CONSTANT(B) RPAREN RBRACKET FOR. { A = (B.i64 < 0) ? 0 : B.i64; } for_intro(A) ::= LBRACKET UNROLL RBRACKET FOR. { A = -1; } for_intro(A) ::= LBRACKET LOOP RBRACKET FOR. { A = 0; } for_intro(A) ::= FOR. { A = -2; } -%type for_details { Statement * } +%type for_details { MOJOSHADER_astStatement * } %destructor for_details { delete_statement(ctx, $$); } for_details(A) ::= LPAREN expression(B) SEMICOLON expression(C) SEMICOLON expression(D) RPAREN statement(E). { A = new_for_statement(ctx, NULL, B, C, D, E); } for_details(A) ::= LPAREN SEMICOLON SEMICOLON RPAREN statement(B). { A = new_for_statement(ctx, NULL, NULL, NULL, NULL, B); } @@ -417,44 +417,44 @@ for_details(A) ::= LPAREN variable_declaration(B) SEMICOLON RPAREN statement(C). for_details(A) ::= LPAREN variable_declaration(B) SEMICOLON expression(C) RPAREN statement(D). { A = new_for_statement(ctx, B, NULL, C, NULL, D); } for_details(A) ::= LPAREN variable_declaration(B) expression(C) SEMICOLON RPAREN statement(D). { A = new_for_statement(ctx, B, NULL, C, NULL, D); } -%type do_intro { int64 } +%type do_intro { int } do_intro(A) ::= LBRACKET UNROLL LPAREN INT_CONSTANT(B) RPAREN RBRACKET DO. { A = (B.i64 < 0) ? 0 : (int) B.i64; } do_intro(A) ::= LBRACKET UNROLL RBRACKET DO. { A = -1; } do_intro(A) ::= LBRACKET LOOP RBRACKET DO. { A = 0; } do_intro(A) ::= DO. { A = -2; } %type if_intro { int } -if_intro(A) ::= LBRACKET BRANCH RBRACKET IF. { A = IFATTR_BRANCH; } -if_intro(A) ::= LBRACKET FLATTEN RBRACKET IF. { A = IFATTR_FLATTEN; } -if_intro(A) ::= LBRACKET IFALL RBRACKET IF. { A = IFATTR_IFALL; } -if_intro(A) ::= LBRACKET IFANY RBRACKET IF. { A = IFATTR_IFANY; } -if_intro(A) ::= LBRACKET PREDICATE RBRACKET IF. { A = IFATTR_PREDICATE; } -if_intro(A) ::= LBRACKET PREDICATEBLOCK RBRACKET IF. { A = IFATTR_PREDICATEBLOCK; } -if_intro(A) ::= IF. { A = IFATTR_NONE; } +if_intro(A) ::= LBRACKET BRANCH RBRACKET IF. { A = MOJOSHADER_AST_IFATTR_BRANCH; } +if_intro(A) ::= LBRACKET FLATTEN RBRACKET IF. { A = MOJOSHADER_AST_IFATTR_FLATTEN; } +if_intro(A) ::= LBRACKET IFALL RBRACKET IF. { A = MOJOSHADER_AST_IFATTR_IFALL; } +if_intro(A) ::= LBRACKET IFANY RBRACKET IF. { A = MOJOSHADER_AST_IFATTR_IFANY; } +if_intro(A) ::= LBRACKET PREDICATE RBRACKET IF. { A = MOJOSHADER_AST_IFATTR_PREDICATE; } +if_intro(A) ::= LBRACKET PREDICATEBLOCK RBRACKET IF. { A = MOJOSHADER_AST_IFATTR_PREDICATEBLOCK; } +if_intro(A) ::= IF. { A = MOJOSHADER_AST_IFATTR_NONE; } %type switch_intro { int } -switch_intro(A) ::= LBRACKET FLATTEN RBRACKET SWITCH. { A = SWITCHATTR_FLATTEN; } -switch_intro(A) ::= LBRACKET BRANCH RBRACKET SWITCH. { A = SWITCHATTR_BRANCH; } -switch_intro(A) ::= LBRACKET FORCECASE RBRACKET SWITCH. { A = SWITCHATTR_FORCECASE; } -switch_intro(A) ::= LBRACKET CALL RBRACKET SWITCH. { A = SWITCHATTR_CALL; } -switch_intro(A) ::= SWITCH. { A = SWITCHATTR_NONE; } +switch_intro(A) ::= LBRACKET FLATTEN RBRACKET SWITCH. { A = MOJOSHADER_AST_SWITCHATTR_FLATTEN; } +switch_intro(A) ::= LBRACKET BRANCH RBRACKET SWITCH. { A = MOJOSHADER_AST_SWITCHATTR_BRANCH; } +switch_intro(A) ::= LBRACKET FORCECASE RBRACKET SWITCH. { A = MOJOSHADER_AST_SWITCHATTR_FORCECASE; } +switch_intro(A) ::= LBRACKET CALL RBRACKET SWITCH. { A = MOJOSHADER_AST_SWITCHATTR_CALL; } +switch_intro(A) ::= SWITCH. { A = MOJOSHADER_AST_SWITCHATTR_NONE; } -%type switch_case_list { SwitchCases * } +%type switch_case_list { MOJOSHADER_astSwitchCases * } %destructor switch_case_list { delete_switch_case(ctx, $$); } switch_case_list(A) ::= switch_case(B). { A = B; } switch_case_list(A) ::= switch_case_list(B) switch_case(C). { A = C; A->next = B; } // You can do math here, apparently, as long as it produces an int constant. // ...so "case 3+2:" works. -%type switch_case { SwitchCases * } +%type switch_case { MOJOSHADER_astSwitchCases * } %destructor switch_case { delete_switch_case(ctx, $$); } -switch_case(A) ::= CASE expression(B) COLON statement_list(C). { REVERSE_LINKED_LIST(Statement, C); A = new_switch_case(ctx, B, C); } +switch_case(A) ::= CASE expression(B) COLON statement_list(C). { REVERSE_LINKED_LIST(MOJOSHADER_astStatement, C); A = new_switch_case(ctx, B, C); } switch_case(A) ::= CASE expression(B) COLON. { A = new_switch_case(ctx, B, NULL); } -switch_case(A) ::= DEFAULT COLON statement_list(B). { REVERSE_LINKED_LIST(Statement, B); A = new_switch_case(ctx, NULL, B); } +switch_case(A) ::= DEFAULT COLON statement_list(B). { REVERSE_LINKED_LIST(MOJOSHADER_astStatement, B); A = new_switch_case(ctx, NULL, B); } switch_case(A) ::= DEFAULT COLON. { A = new_switch_case(ctx, NULL, NULL); } // the expression stuff is based on Jeff Lee's ANSI C grammar. -%type primary_expr { Expression * } +%type primary_expr { MOJOSHADER_astExpression * } %destructor primary_expr { delete_expr(ctx, $$); } primary_expr(A) ::= IDENTIFIER(B). { A = new_identifier_expr(ctx, B.string); } primary_expr(A) ::= INT_CONSTANT(B). { A = new_literal_int_expr(ctx, B.i64); } @@ -464,123 +464,123 @@ primary_expr(A) ::= TRUE. { A = new_literal_boolean_expr(ctx, 1); } primary_expr(A) ::= FALSE. { A = new_literal_boolean_expr(ctx, 0); } primary_expr(A) ::= LPAREN expression(B) RPAREN. { A = B; } -%type postfix_expr { Expression * } +%type postfix_expr { MOJOSHADER_astExpression * } %destructor postfix_expr { delete_expr(ctx, $$); } postfix_expr(A) ::= primary_expr(B). { A = B; } -postfix_expr(A) ::= postfix_expr(B) LBRACKET expression(C) RBRACKET. { A = new_binary_expr(ctx, AST_OP_DEREF_ARRAY, B, C); } +postfix_expr(A) ::= postfix_expr(B) LBRACKET expression(C) RBRACKET. { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_DEREF_ARRAY, B, C); } postfix_expr(A) ::= postfix_expr(B) arguments(C). { A = new_callfunc_expr(ctx, B, C); } postfix_expr(A) ::= datatype(B) arguments(C). { A = new_constructor_expr(ctx, B, C); } // HLSL constructor postfix_expr(A) ::= postfix_expr(B) DOT IDENTIFIER(C). { A = new_deref_struct_expr(ctx, B, C.string); } -postfix_expr(A) ::= postfix_expr(B) PLUSPLUS. { A = new_unary_expr(ctx, AST_OP_POSTINCREMENT, B); } -postfix_expr(A) ::= postfix_expr(B) MINUSMINUS. { A = new_unary_expr(ctx, AST_OP_POSTDECREMENT, B); } +postfix_expr(A) ::= postfix_expr(B) PLUSPLUS. { A = new_unary_expr(ctx, MOJOSHADER_AST_OP_POSTINCREMENT, B); } +postfix_expr(A) ::= postfix_expr(B) MINUSMINUS. { A = new_unary_expr(ctx, MOJOSHADER_AST_OP_POSTDECREMENT, B); } -%type arguments { Arguments * } +%type arguments { MOJOSHADER_astArguments * } %destructor arguments { delete_arguments(ctx, $$); } arguments(A) ::= LPAREN RPAREN. { A = NULL; } -arguments(A) ::= LPAREN argument_list(B) RPAREN. { REVERSE_LINKED_LIST(Arguments, B); A = B; } +arguments(A) ::= LPAREN argument_list(B) RPAREN. { REVERSE_LINKED_LIST(MOJOSHADER_astArguments, B); A = B; } -%type argument_list { Arguments * } +%type argument_list { MOJOSHADER_astArguments * } %destructor argument_list { delete_arguments(ctx, $$); } argument_list(A) ::= assignment_expr(B). { A = new_argument(ctx, B); } argument_list(A) ::= argument_list(B) COMMA assignment_expr(C). { A = new_argument(ctx, C); A->next = B; } -%type unary_expr { Expression * } +%type unary_expr { MOJOSHADER_astExpression * } %destructor unary_expr { delete_expr(ctx, $$); } unary_expr(A) ::= postfix_expr(B). { A = B; } -unary_expr(A) ::= PLUSPLUS unary_expr(B). { A = new_unary_expr(ctx, AST_OP_PREINCREMENT, B); } -unary_expr(A) ::= MINUSMINUS unary_expr(B). { A = new_unary_expr(ctx, AST_OP_PREDECREMENT, B); } +unary_expr(A) ::= PLUSPLUS unary_expr(B). { A = new_unary_expr(ctx, MOJOSHADER_AST_OP_PREINCREMENT, B); } +unary_expr(A) ::= MINUSMINUS unary_expr(B). { A = new_unary_expr(ctx, MOJOSHADER_AST_OP_PREDECREMENT, B); } unary_expr(A) ::= PLUS cast_expr(B). { A = B; } // unary "+x" is always a no-op, so throw it away here. -unary_expr(A) ::= MINUS cast_expr(B). { A = new_unary_expr(ctx, AST_OP_NEGATE, B); } -unary_expr(A) ::= COMPLEMENT cast_expr(B). { A = new_unary_expr(ctx, AST_OP_COMPLEMENT, B); } -unary_expr(A) ::= EXCLAMATION cast_expr(B). { A = new_unary_expr(ctx, AST_OP_NOT, B); } +unary_expr(A) ::= MINUS cast_expr(B). { A = new_unary_expr(ctx, MOJOSHADER_AST_OP_NEGATE, B); } +unary_expr(A) ::= COMPLEMENT cast_expr(B). { A = new_unary_expr(ctx, MOJOSHADER_AST_OP_COMPLEMENT, B); } +unary_expr(A) ::= EXCLAMATION cast_expr(B). { A = new_unary_expr(ctx, MOJOSHADER_AST_OP_NOT, B); } -%type cast_expr { Expression * } +%type cast_expr { MOJOSHADER_astExpression * } %destructor cast_expr { delete_expr(ctx, $$); } cast_expr(A) ::= unary_expr(B). { A = B; } cast_expr(A) ::= LPAREN datatype(B) RPAREN cast_expr(C). { A = new_cast_expr(ctx, B, C); } -%type multiplicative_expr { Expression * } +%type multiplicative_expr { MOJOSHADER_astExpression * } %destructor multiplicative_expr { delete_expr(ctx, $$); } multiplicative_expr(A) ::= cast_expr(B). { A = B; } -multiplicative_expr(A) ::= multiplicative_expr(B) STAR cast_expr(C). { A = new_binary_expr(ctx, AST_OP_MULTIPLY, B, C); } -multiplicative_expr(A) ::= multiplicative_expr(B) SLASH cast_expr(C). { A = new_binary_expr(ctx, AST_OP_DIVIDE, B, C); } -multiplicative_expr(A) ::= multiplicative_expr(B) PERCENT cast_expr(C). { A = new_binary_expr(ctx, AST_OP_MODULO, B, C); } +multiplicative_expr(A) ::= multiplicative_expr(B) STAR cast_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_MULTIPLY, B, C); } +multiplicative_expr(A) ::= multiplicative_expr(B) SLASH cast_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_DIVIDE, B, C); } +multiplicative_expr(A) ::= multiplicative_expr(B) PERCENT cast_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_MODULO, B, C); } -%type additive_expr { Expression * } +%type additive_expr { MOJOSHADER_astExpression * } %destructor additive_expr { delete_expr(ctx, $$); } additive_expr(A) ::= multiplicative_expr(B). { A = B; } -additive_expr(A) ::= additive_expr(B) PLUS multiplicative_expr(C). { A = new_binary_expr(ctx, AST_OP_ADD, B, C); } -additive_expr(A) ::= additive_expr(B) MINUS multiplicative_expr(C). { A = new_binary_expr(ctx, AST_OP_SUBTRACT, B, C); } +additive_expr(A) ::= additive_expr(B) PLUS multiplicative_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_ADD, B, C); } +additive_expr(A) ::= additive_expr(B) MINUS multiplicative_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_SUBTRACT, B, C); } -%type shift_expr { Expression * } +%type shift_expr { MOJOSHADER_astExpression * } %destructor shift_expr { delete_expr(ctx, $$); } shift_expr(A) ::= additive_expr(B). { A = B; } -shift_expr(A) ::= shift_expr(B) LSHIFT additive_expr(C). { A = new_binary_expr(ctx, AST_OP_LSHIFT, B, C); } -shift_expr(A) ::= shift_expr(B) RSHIFT additive_expr(C). { A = new_binary_expr(ctx, AST_OP_RSHIFT, B, C); } +shift_expr(A) ::= shift_expr(B) LSHIFT additive_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_LSHIFT, B, C); } +shift_expr(A) ::= shift_expr(B) RSHIFT additive_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_RSHIFT, B, C); } -%type relational_expr { Expression * } +%type relational_expr { MOJOSHADER_astExpression * } %destructor relational_expr { delete_expr(ctx, $$); } relational_expr(A) ::= shift_expr(B). { A = B; } -relational_expr(A) ::= relational_expr(B) LT shift_expr(C). { A = new_binary_expr(ctx, AST_OP_LESSTHAN, B, C); } -relational_expr(A) ::= relational_expr(B) GT shift_expr(C). { A = new_binary_expr(ctx, AST_OP_GREATERTHAN, B, C); } -relational_expr(A) ::= relational_expr(B) LEQ shift_expr(C). { A = new_binary_expr(ctx, AST_OP_LESSTHANOREQUAL, B, C); } -relational_expr(A) ::= relational_expr(B) GEQ shift_expr(C). { A = new_binary_expr(ctx, AST_OP_GREATERTHANOREQUAL, B, C); } +relational_expr(A) ::= relational_expr(B) LT shift_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_LESSTHAN, B, C); } +relational_expr(A) ::= relational_expr(B) GT shift_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_GREATERTHAN, B, C); } +relational_expr(A) ::= relational_expr(B) LEQ shift_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_LESSTHANOREQUAL, B, C); } +relational_expr(A) ::= relational_expr(B) GEQ shift_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_GREATERTHANOREQUAL, B, C); } -%type equality_expr { Expression * } +%type equality_expr { MOJOSHADER_astExpression * } %destructor equality_expr { delete_expr(ctx, $$); } equality_expr(A) ::= relational_expr(B). { A = B; } -equality_expr(A) ::= equality_expr(B) EQL relational_expr(C). { A = new_binary_expr(ctx, AST_OP_EQUAL, B, C); } -equality_expr(A) ::= equality_expr(B) NEQ relational_expr(C). { A = new_binary_expr(ctx, AST_OP_NOTEQUAL, B, C); } +equality_expr(A) ::= equality_expr(B) EQL relational_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_EQUAL, B, C); } +equality_expr(A) ::= equality_expr(B) NEQ relational_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_NOTEQUAL, B, C); } -%type and_expr { Expression * } +%type and_expr { MOJOSHADER_astExpression * } %destructor and_expr { delete_expr(ctx, $$); } and_expr(A) ::= equality_expr(B). { A = B; } -and_expr(A) ::= and_expr(B) AND equality_expr(C). { A = new_binary_expr(ctx, AST_OP_BINARYAND, B, C); } +and_expr(A) ::= and_expr(B) AND equality_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_BINARYAND, B, C); } -%type exclusive_or_expr { Expression * } +%type exclusive_or_expr { MOJOSHADER_astExpression * } %destructor exclusive_or_expr { delete_expr(ctx, $$); } exclusive_or_expr(A) ::= and_expr(B). { A = B; } -exclusive_or_expr(A) ::= exclusive_or_expr(B) XOR and_expr(C). { A = new_binary_expr(ctx, AST_OP_BINARYXOR, B, C); } +exclusive_or_expr(A) ::= exclusive_or_expr(B) XOR and_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_BINARYXOR, B, C); } -%type inclusive_or_expr { Expression * } +%type inclusive_or_expr { MOJOSHADER_astExpression * } %destructor inclusive_or_expr { delete_expr(ctx, $$); } inclusive_or_expr(A) ::= exclusive_or_expr(B). { A = B; } -inclusive_or_expr(A) ::= inclusive_or_expr(B) OR exclusive_or_expr(C). { A = new_binary_expr(ctx, AST_OP_BINARYOR, B, C); } +inclusive_or_expr(A) ::= inclusive_or_expr(B) OR exclusive_or_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_BINARYOR, B, C); } -%type logical_and_expr { Expression * } +%type logical_and_expr { MOJOSHADER_astExpression * } %destructor logical_and_expr { delete_expr(ctx, $$); } logical_and_expr(A) ::= inclusive_or_expr(B). { A = B; } -logical_and_expr(A) ::= logical_and_expr(B) ANDAND inclusive_or_expr(C). { A = new_binary_expr(ctx, AST_OP_LOGICALAND, B, C); } +logical_and_expr(A) ::= logical_and_expr(B) ANDAND inclusive_or_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_LOGICALAND, B, C); } -%type logical_or_expr { Expression * } +%type logical_or_expr { MOJOSHADER_astExpression * } %destructor logical_or_expr { delete_expr(ctx, $$); } logical_or_expr(A) ::= logical_and_expr(B). { A = B; } -logical_or_expr(A) ::= logical_or_expr(B) OROR logical_and_expr(C). { A = new_binary_expr(ctx, AST_OP_LOGICALOR, B, C); } +logical_or_expr(A) ::= logical_or_expr(B) OROR logical_and_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_LOGICALOR, B, C); } -%type conditional_expr { Expression * } +%type conditional_expr { MOJOSHADER_astExpression * } %destructor conditional_expr { delete_expr(ctx, $$); } conditional_expr(A) ::= logical_or_expr(B). { A = B; } -conditional_expr(A) ::= logical_or_expr(B) QUESTION logical_or_expr(C) COLON conditional_expr(D). { A = new_ternary_expr(ctx, AST_OP_CONDITIONAL, B, C, D); } +conditional_expr(A) ::= logical_or_expr(B) QUESTION logical_or_expr(C) COLON conditional_expr(D). { A = new_ternary_expr(ctx, MOJOSHADER_AST_OP_CONDITIONAL, B, C, D); } -%type assignment_expr { Expression * } +%type assignment_expr { MOJOSHADER_astExpression * } %destructor assignment_expr { delete_expr(ctx, $$); } assignment_expr(A) ::= conditional_expr(B). { A = B; } -assignment_expr(A) ::= unary_expr(B) ASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_ASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) MULASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_MULASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) DIVASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_DIVASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) MODASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_MODASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) ADDASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_ADDASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) SUBASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_SUBASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) LSHIFTASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_LSHIFTASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) RSHIFTASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_RSHIFTASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) ANDASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_ANDASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) XORASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_XORASSIGN, B, C); } -assignment_expr(A) ::= unary_expr(B) ORASSIGN assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_ORASSIGN, B, C); } - -%type expression { Expression * } +assignment_expr(A) ::= unary_expr(B) ASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_ASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) MULASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_MULASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) DIVASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_DIVASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) MODASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_MODASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) ADDASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_ADDASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) SUBASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_SUBASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) LSHIFTASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_LSHIFTASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) RSHIFTASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_RSHIFTASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) ANDASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_ANDASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) XORASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_XORASSIGN, B, C); } +assignment_expr(A) ::= unary_expr(B) ORASSIGN assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_ORASSIGN, B, C); } + +%type expression { MOJOSHADER_astExpression * } %destructor expression { delete_expr(ctx, $$); } expression(A) ::= assignment_expr(B). { A = B; } -expression(A) ::= expression(B) COMMA assignment_expr(C). { A = new_binary_expr(ctx, AST_OP_COMMA, B, C); } +expression(A) ::= expression(B) COMMA assignment_expr(C). { A = new_binary_expr(ctx, MOJOSHADER_AST_OP_COMMA, B, C); } // end of mojoshader_parser_hlsl.lemon ... diff --git a/utils/mojoshader-compiler.c b/utils/mojoshader-compiler.c index ff010b3f..1cf068cd 100644 --- a/utils/mojoshader-compiler.c +++ b/utils/mojoshader-compiler.c @@ -10,8 +10,14 @@ #include #include #include +#include + #include "mojoshader.h" +#ifndef _WIN32 +#define stricmp(a,b) strcasecmp(a,b) +#endif + static const char **include_paths = NULL; static unsigned int include_path_count = 0; @@ -48,6 +54,555 @@ static void fail(const char *err) exit(1); } // fail +static void print_unroll_attr(const int unroll) +{ + if (unroll == 0) + printf("[loop] "); + else if (unroll < 0) + printf("[unroll] "); + else + printf("[unroll(%d)] ", unroll); +} // print_unroll_attr + +// !!! FIXME: this screws up on order of operations. +static void print_ast(const int substmt, const void *_ast) +{ + const MOJOSHADER_astNode *ast = (const MOJOSHADER_astNode *) _ast; + const char *nl = substmt ? "" : "\n"; + int typeint = 0; + static int indent = 0; + int isblock = 0; + int i; + + // These _HAVE_ to be in the same order as MOJOSHADER_astNodeType! + static const char *binary[] = + { + ",", "*", "/", "%", "+", "-", "<<", ">>", "<", ">", "<=", ">=", "==", + "!=", "&", "^", "|", "&&", "||", "=", "*=", "/=", "%=", "+=", "-=", + "<<=", ">>=", "&=", "^=", "|=" + }; + + static const char *pre_unary[] = { "++", "--", "-", "~", "!" }; + static const char *post_unary[] = { "++", "--" }; + static const char *simple_stmt[] = { "", "break", "continue", "discard" }; + static const char *inpmod[] = { "", "in ", "out ", "in out ", "uniform " }; + static const char *fnstorage[] = { "", "inline " }; + + static const char *interpmod[] = { + "", " linear", " centroid", " nointerpolation", + " noperspective", " sample" + }; + + if (!ast) return; + + typeint = (int) ast->ast.type; + + #define DO_INDENT do { \ + if (!substmt) { for (i = 0; i < indent; i++) printf(" "); } \ + } while (0) + + switch (ast->ast.type) + { + case MOJOSHADER_AST_OP_PREINCREMENT: + case MOJOSHADER_AST_OP_PREDECREMENT: + case MOJOSHADER_AST_OP_NEGATE: + case MOJOSHADER_AST_OP_COMPLEMENT: + case MOJOSHADER_AST_OP_NOT: + printf("%s", pre_unary[(typeint-MOJOSHADER_AST_OP_START_RANGE_UNARY)-1]); + print_ast(0, ast->unary.operand); + break; + + case MOJOSHADER_AST_OP_POSTINCREMENT: + case MOJOSHADER_AST_OP_POSTDECREMENT: + print_ast(0, ast->unary.operand); + printf("%s", post_unary[typeint-MOJOSHADER_AST_OP_POSTINCREMENT]); + break; + + case MOJOSHADER_AST_OP_MULTIPLY: + case MOJOSHADER_AST_OP_DIVIDE: + case MOJOSHADER_AST_OP_MODULO: + case MOJOSHADER_AST_OP_ADD: + case MOJOSHADER_AST_OP_SUBTRACT: + case MOJOSHADER_AST_OP_LSHIFT: + case MOJOSHADER_AST_OP_RSHIFT: + case MOJOSHADER_AST_OP_LESSTHAN: + case MOJOSHADER_AST_OP_GREATERTHAN: + case MOJOSHADER_AST_OP_LESSTHANOREQUAL: + case MOJOSHADER_AST_OP_GREATERTHANOREQUAL: + case MOJOSHADER_AST_OP_EQUAL: + case MOJOSHADER_AST_OP_NOTEQUAL: + case MOJOSHADER_AST_OP_BINARYAND: + case MOJOSHADER_AST_OP_BINARYXOR: + case MOJOSHADER_AST_OP_BINARYOR: + case MOJOSHADER_AST_OP_LOGICALAND: + case MOJOSHADER_AST_OP_LOGICALOR: + case MOJOSHADER_AST_OP_ASSIGN: + case MOJOSHADER_AST_OP_MULASSIGN: + case MOJOSHADER_AST_OP_DIVASSIGN: + case MOJOSHADER_AST_OP_MODASSIGN: + case MOJOSHADER_AST_OP_ADDASSIGN: + case MOJOSHADER_AST_OP_SUBASSIGN: + case MOJOSHADER_AST_OP_LSHIFTASSIGN: + case MOJOSHADER_AST_OP_RSHIFTASSIGN: + case MOJOSHADER_AST_OP_ANDASSIGN: + case MOJOSHADER_AST_OP_XORASSIGN: + case MOJOSHADER_AST_OP_ORASSIGN: + printf(" "); // then fall through! (no space before the comma). + case MOJOSHADER_AST_OP_COMMA: + print_ast(0, ast->binary.left); + printf("%s ", binary[ + (typeint - MOJOSHADER_AST_OP_START_RANGE_BINARY) - 1]); + print_ast(0, ast->binary.right); + break; + + case MOJOSHADER_AST_OP_DEREF_ARRAY: + print_ast(0, ast->binary.left); + printf("["); + print_ast(0, ast->binary.right); + printf("]"); + break; + + case MOJOSHADER_AST_OP_DEREF_STRUCT: + print_ast(0, ast->derefstruct.identifier); + printf("."); + printf("%s", ast->derefstruct.member); + break; + + case MOJOSHADER_AST_OP_CONDITIONAL: + print_ast(0, ast->ternary.left); + printf(" ? "); + print_ast(0, ast->ternary.center); + printf(" : "); + print_ast(0, ast->ternary.right); + break; + + case MOJOSHADER_AST_OP_IDENTIFIER: + printf("%s", ast->identifier.identifier); + break; + + case MOJOSHADER_AST_OP_INT_LITERAL: + printf("%d", ast->intliteral.value); + break; + + case MOJOSHADER_AST_OP_FLOAT_LITERAL: + { + const float f = ast->floatliteral.value; + const long long flr = (long long) f; + if (((float) flr) == f) + printf("%lld.0", flr); + else + printf("%.16g", f); + break; + } // case + + case MOJOSHADER_AST_OP_STRING_LITERAL: + printf("\"%s\"", ast->stringliteral.string); + break; + + case MOJOSHADER_AST_OP_BOOLEAN_LITERAL: + printf("%s", ast->boolliteral.value ? "true" : "false"); + break; + + case MOJOSHADER_AST_ARGUMENTS: + print_ast(0, ast->arguments.argument); + if (ast->arguments.next != NULL) + { + printf(", "); + print_ast(0, ast->arguments.next); + } // if + break; + + case MOJOSHADER_AST_OP_CALLFUNC: + print_ast(0, ast->callfunc.identifier); + printf("("); + print_ast(0, ast->callfunc.args); + printf(")"); + break; + + case MOJOSHADER_AST_OP_CONSTRUCTOR: + printf("%s(", ast->constructor.datatype); + print_ast(0, ast->constructor.args); + printf(")"); + break; + + case MOJOSHADER_AST_OP_CAST: + printf("(%s) (", ast->cast.datatype); + print_ast(0, ast->cast.operand); + printf(")"); + break; + + case MOJOSHADER_AST_STATEMENT_EXPRESSION: + DO_INDENT; + print_ast(0, ast->exprstmt.expr); // !!! FIXME: This is named badly... + printf(";%s", nl); + print_ast(0, ast->exprstmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_IF: + DO_INDENT; + printf("if ("); + print_ast(0, ast->ifstmt.expr); + printf(")\n"); + isblock = ast->ifstmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK; + if (!isblock) indent++; + print_ast(0, ast->ifstmt.statement); + if (!isblock) indent--; + print_ast(0, ast->ifstmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_TYPEDEF: + DO_INDENT; + print_ast(1, ast->typedefstmt.type_info); + printf("%s", nl); + print_ast(0, ast->typedefstmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_SWITCH: + DO_INDENT; + switch ( ast->switchstmt.attributes ) + { + case MOJOSHADER_AST_SWITCHATTR_NONE: break; + case MOJOSHADER_AST_SWITCHATTR_FLATTEN: printf("[flatten] "); break; + case MOJOSHADER_AST_SWITCHATTR_BRANCH: printf("[branch] "); break; + case MOJOSHADER_AST_SWITCHATTR_FORCECASE: printf("[forcecase] "); break; + case MOJOSHADER_AST_SWITCHATTR_CALL: printf("[call] "); break; + } // switch + + printf("switch ("); + print_ast(0, ast->switchstmt.expr); + printf(")\n"); + DO_INDENT; + printf("{\n"); + indent++; + print_ast(0, ast->switchstmt.cases); + indent--; + printf("\n"); + DO_INDENT; + printf("}\n"); + print_ast(0, ast->switchstmt.next); + break; + + case MOJOSHADER_AST_SWITCH_CASE: + DO_INDENT; + printf("case "); + print_ast(0, ast->cases.expr); + printf(":\n"); + isblock = ast->cases.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK; + if (!isblock) indent++; + print_ast(0, ast->cases.statement); + if (!isblock) indent--; + print_ast(0, ast->cases.next); + break; + + case MOJOSHADER_AST_STATEMENT_STRUCT: + DO_INDENT; + print_ast(0, ast->structstmt.struct_info); + printf(";%s%s", nl, nl); // always space these out. + print_ast(0, ast->structstmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_VARDECL: + DO_INDENT; + print_ast(1, ast->vardeclstmt.declaration); + printf(";%s", nl); + print_ast(0, ast->vardeclstmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_BLOCK: + DO_INDENT; + printf("{\n"); + indent++; + print_ast(0, ast->blockstmt.statements); + indent--; + DO_INDENT; + printf("}\n"); + print_ast(0, ast->blockstmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_FOR: + DO_INDENT; + print_unroll_attr(ast->forstmt.unroll); + printf("for ("); + print_ast(1, ast->forstmt.var_decl); + if (ast->forstmt.initializer != NULL) + { + printf(" = "); + print_ast(1, ast->forstmt.initializer); + } // if + printf("; "); + print_ast(1, ast->forstmt.looptest); + printf("; "); + print_ast(1, ast->forstmt.counter); + + printf(")\n"); + isblock = ast->forstmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK; + if (!isblock) indent++; + print_ast(0, ast->forstmt.statement); + if (!isblock) indent--; + + print_ast(0, ast->forstmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_DO: + DO_INDENT; + print_unroll_attr(ast->dostmt.unroll); + printf("do\n"); + + isblock = ast->dostmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK; + if (!isblock) indent++; + print_ast(0, ast->dostmt.statement); + if (!isblock) indent--; + + DO_INDENT; + printf("while ("); + print_ast(0, ast->dostmt.expr); + printf(");\n"); + + print_ast(0, ast->dostmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_WHILE: + DO_INDENT; + print_unroll_attr(ast->whilestmt.unroll); + printf("while ("); + print_ast(0, ast->whilestmt.expr); + printf(")\n"); + + isblock = ast->whilestmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK; + if (!isblock) indent++; + print_ast(0, ast->whilestmt.statement); + if (!isblock) indent--; + + print_ast(0, ast->whilestmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_RETURN: + DO_INDENT; + printf("return"); + if (ast->returnstmt.expr) + { + printf(" "); + print_ast(0, ast->returnstmt.expr); + } // if + printf(";%s", nl); + print_ast(0, ast->returnstmt.next); + break; + + case MOJOSHADER_AST_STATEMENT_EMPTY: + case MOJOSHADER_AST_STATEMENT_BREAK: + case MOJOSHADER_AST_STATEMENT_CONTINUE: + case MOJOSHADER_AST_STATEMENT_DISCARD: + DO_INDENT; + printf("%s;%s", + simple_stmt[(typeint-MOJOSHADER_AST_STATEMENT_START_RANGE)-1], + nl); + print_ast(0, ast->stmt.next); + break; + + case MOJOSHADER_AST_COMPUNIT_FUNCTION: + DO_INDENT; + print_ast(0, ast->funcunit.declaration); + if (ast->funcunit.definition == NULL) + printf(";%s", nl); + else + { + printf("%s", nl); + print_ast(0, ast->funcunit.definition); + printf("%s", nl); + } // else + print_ast(0, ast->funcunit.next); + break; + + case MOJOSHADER_AST_COMPUNIT_TYPEDEF: + DO_INDENT; + print_ast(0, ast->typedefunit.type_info); + printf("%s", nl); + print_ast(0, ast->typedefunit.next); + break; + + case MOJOSHADER_AST_COMPUNIT_STRUCT: + DO_INDENT; + print_ast(0, ast->structunit.struct_info); + printf(";%s%s", nl, nl); // always space these out. + print_ast(0, ast->structunit.next); + break; + + case MOJOSHADER_AST_COMPUNIT_VARIABLE: + DO_INDENT; + print_ast(1, ast->varunit.declaration); + printf(";%s", nl); + if (ast->varunit.next && + ast->varunit.next->ast.type!=MOJOSHADER_AST_COMPUNIT_VARIABLE) + { + printf("%s", nl); // group vars together, and space out other things. + } // if + print_ast(0, ast->varunit.next); + break; + + case MOJOSHADER_AST_SCALAR_OR_ARRAY: + printf("%s", ast->soa.identifier); + if (ast->soa.isarray) + { + printf("["); + print_ast(0, ast->soa.dimension); + printf("]"); + } // if + break; + + case MOJOSHADER_AST_TYPEDEF: + DO_INDENT; + printf("typedef %s%s ", + ast->typdef.isconst ? "const " : "", ast->typdef.datatype); + print_ast(0, ast->typdef.details); + printf(";%s", nl); + break; + + case MOJOSHADER_AST_FUNCTION_PARAMS: + printf("%s", inpmod[(int) ast->params.input_modifier]); + printf("%s %s", ast->params.datatype, ast->params.identifier); + if (ast->params.semantic) + printf(" : %s", ast->params.semantic); + printf("%s", interpmod[(int) ast->params.interpolation_modifier]); + + if (ast->params.initializer) + { + printf(" = "); + print_ast(0, ast->params.initializer); + } // if + + if (ast->params.next) + { + printf(", "); + print_ast(0, ast->params.next); + } // if + break; + + case MOJOSHADER_AST_FUNCTION_SIGNATURE: + printf("%s", fnstorage[(int) ast->funcsig.storage_class]); + printf("%s %s(", + ast->funcsig.datatype ? ast->funcsig.datatype : "void", + ast->funcsig.identifier); + print_ast(0, ast->funcsig.params); + printf(")"); + if (ast->funcsig.semantic) + printf(" : %s", ast->funcsig.semantic); + break; + + case MOJOSHADER_AST_STRUCT_DECLARATION: + printf("struct %s\n", ast->structdecl.name); + DO_INDENT; + printf("{\n"); + indent++; + print_ast(0, ast->structdecl.members); + indent--; + DO_INDENT; + printf("}"); + break; + + case MOJOSHADER_AST_STRUCT_MEMBER: + DO_INDENT; + printf("%s", interpmod[(int)ast->structmembers.interpolation_mod]); + printf("%s ", ast->structmembers.datatype); + print_ast(0, ast->structmembers.details); + if (ast->structmembers.semantic) + printf(" : %s", ast->structmembers.semantic); + printf(";%s", nl); + print_ast(0, ast->structmembers.next); + break; + + case MOJOSHADER_AST_VARIABLE_DECLARATION: + DO_INDENT; + if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_EXTERN) + printf("extern "); + if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_NOINTERPOLATION) + printf("nointerpolation "); + if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_SHARED) + printf("shared"); + if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_STATIC) + printf("static "); + if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_UNIFORM) + printf("uniform "); + if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_VOLATILE) + printf("nointerpolation "); + if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_CONST) + printf("const "); + if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_ROWMAJOR) + printf("rowmajor "); + if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_COLUMNMAJOR) + printf("columnmajor "); + + if (ast->vardecl.datatype) + printf("%s", ast->vardecl.datatype); + else + print_ast(0, ast->vardecl.anonymous_datatype); + printf(" "); + print_ast(0, ast->vardecl.details); + if (ast->vardecl.semantic) + printf(" : %s", ast->vardecl.semantic); + if (ast->vardecl.annotations) + { + printf(" "); + print_ast(0, ast->vardecl.annotations); + } // if + if (ast->vardecl.initializer != NULL) + { + printf(" = "); + print_ast(0, ast->vardecl.initializer); + } // if + print_ast(0, ast->vardecl.lowlevel); + + if (ast->vardecl.next == NULL) + printf("%s", nl); + else + { + const int attr = ast->vardecl.next->attributes; + printf(", "); + ast->vardecl.next->attributes = 0; + print_ast(1, ast->vardecl.next); + ast->vardecl.next->attributes = attr; + } // if + break; + + case MOJOSHADER_AST_PACK_OFFSET: + printf(" : packoffset(%s%s%s)", ast->packoffset.ident1, + ast->packoffset.ident2 ? "." : "", + ast->packoffset.ident2 ? ast->packoffset.ident2 : ""); + break; + + case MOJOSHADER_AST_VARIABLE_LOWLEVEL: + print_ast(0, ast->varlowlevel.packoffset); + if (ast->varlowlevel.register_name) + printf(" : register(%s)", ast->varlowlevel.register_name); + break; + + case MOJOSHADER_AST_ANNOTATION: + { + const MOJOSHADER_astAnnotations *a = &ast->annotations; + printf("<"); + while (a) + { + printf(" %s ", a->datatype); + if (a->initializer != NULL) + { + printf(" = "); + print_ast(0, a->initializer); + } // if + if (a->next) + printf(","); + a = a->next; + } // while + printf(" >"); + break; + } // case + + default: + assert(0 && "unexpected type"); + break; + } // switch + + #undef DO_INDENT +} // print_ast + static int open_include(MOJOSHADER_includeType inctype, const char *fname, const char *parent, const char **outdata, @@ -192,13 +747,19 @@ static int assemble(const char *fname, const char *buf, int len, return retval; } // assemble -void MOJOSHADER_compile(const char *filename, - const char *source, unsigned int sourcelen, - const MOJOSHADER_preprocessorDefine *defines, - unsigned int define_count, - MOJOSHADER_includeOpen include_open, - MOJOSHADER_includeClose include_close, - MOJOSHADER_malloc m, MOJOSHADER_free f, void *d); +static int ast(const char *fname, const char *buf, int len, + const char *outfile, const MOJOSHADER_preprocessorDefine *defs, + unsigned int defcount, FILE *io) +{ + // !!! FIXME: write me. + //const MOJOSHADER_parseData *pd; + //int retval = 0; + + MOJOSHADER_parseAst(MOJOSHADER_SRC_PROFILE_HLSL_PS_1_1, // !!! FIXME + fname, buf, len, defs, defcount, + open_include, close_include, Malloc, Free, NULL); + return 1; +} // ast static int compile(const char *fname, const char *buf, int len, const char *outfile, @@ -209,7 +770,8 @@ static int compile(const char *fname, const char *buf, int len, //const MOJOSHADER_parseData *pd; //int retval = 0; - MOJOSHADER_compile(fname, buf, len, defs, defcount, + MOJOSHADER_compile(MOJOSHADER_SRC_PROFILE_HLSL_PS_1_1, // !!! FIXME + fname, buf, len, defs, defcount, open_include, close_include, Malloc, Free, NULL); return 1; @@ -221,6 +783,7 @@ typedef enum ACTION_VERSION, ACTION_PREPROCESS, ACTION_ASSEMBLE, + ACTION_AST, ACTION_COMPILE, } Action; @@ -240,6 +803,7 @@ int main(int argc, char **argv) include_paths[0] = "."; include_path_count = 1; + // !!! FIXME: clean this up. for (i = 1; i < argc; i++) { const char *arg = argv[i]; @@ -258,6 +822,13 @@ int main(int argc, char **argv) action = ACTION_ASSEMBLE; } // else if + else if (strcmp(arg, "-T") == 0) + { + if ((action != ACTION_UNKNOWN) && (action != ACTION_AST)) + fail("Multiple actions specified"); + action = ACTION_AST; + } // else if + else if (strcmp(arg, "-C") == 0) { if ((action != ACTION_UNKNOWN) && (action != ACTION_COMPILE)) @@ -358,6 +929,8 @@ int main(int argc, char **argv) retval = (!preprocess(infile, buf, rc, outfile, defs, defcount, outio)); else if (action == ACTION_ASSEMBLE) retval = (!assemble(infile, buf, rc, outfile, defs, defcount, outio)); + else if (action == ACTION_AST) + retval = (!ast(infile, buf, rc, outfile, defs, defcount, outio)); else if (action == ACTION_COMPILE) retval = (!compile(infile, buf, rc, outfile, defs, defcount, outio));