📄 slang_compile.c
字号:
#define PARAMETER_NONE 0#define PARAMETER_NEXT 1/* operator type */#define OPERATOR_ADDASSIGN 1#define OPERATOR_SUBASSIGN 2#define OPERATOR_MULASSIGN 3#define OPERATOR_DIVASSIGN 4/*#define OPERATOR_MODASSIGN 5*//*#define OPERATOR_LSHASSIGN 6*//*#define OPERATOR_RSHASSIGN 7*//*#define OPERATOR_ANDASSIGN 8*//*#define OPERATOR_XORASSIGN 9*//*#define OPERATOR_ORASSIGN 10*/#define OPERATOR_LOGICALXOR 11/*#define OPERATOR_BITOR 12*//*#define OPERATOR_BITXOR 13*//*#define OPERATOR_BITAND 14*/#define OPERATOR_LESS 15#define OPERATOR_GREATER 16#define OPERATOR_LESSEQUAL 17#define OPERATOR_GREATEREQUAL 18/*#define OPERATOR_LSHIFT 19*//*#define OPERATOR_RSHIFT 20*/#define OPERATOR_MULTIPLY 21#define OPERATOR_DIVIDE 22/*#define OPERATOR_MODULUS 23*/#define OPERATOR_INCREMENT 24#define OPERATOR_DECREMENT 25#define OPERATOR_PLUS 26#define OPERATOR_MINUS 27/*#define OPERATOR_COMPLEMENT 28*/#define OPERATOR_NOT 29static const struct{ unsigned int o_code; const char *o_name;} operator_names[] = { {OPERATOR_INCREMENT, "++"}, {OPERATOR_ADDASSIGN, "+="}, {OPERATOR_PLUS, "+"}, {OPERATOR_DECREMENT, "--"}, {OPERATOR_SUBASSIGN, "-="}, {OPERATOR_MINUS, "-"}, {OPERATOR_NOT, "!"}, {OPERATOR_MULASSIGN, "*="}, {OPERATOR_MULTIPLY, "*"}, {OPERATOR_DIVASSIGN, "/="}, {OPERATOR_DIVIDE, "/"}, {OPERATOR_LESSEQUAL, "<="}, /*{ OPERATOR_LSHASSIGN, "<<=" }, */ /*{ OPERATOR_LSHIFT, "<<" }, */ {OPERATOR_LESS, "<"}, {OPERATOR_GREATEREQUAL, ">="}, /*{ OPERATOR_RSHASSIGN, ">>=" }, */ /*{ OPERATOR_RSHIFT, ">>" }, */ {OPERATOR_GREATER, ">"}, /*{ OPERATOR_MODASSIGN, "%=" }, */ /*{ OPERATOR_MODULUS, "%" }, */ /*{ OPERATOR_ANDASSIGN, "&=" }, */ /*{ OPERATOR_BITAND, "&" }, */ /*{ OPERATOR_ORASSIGN, "|=" }, */ /*{ OPERATOR_BITOR, "|" }, */ /*{ OPERATOR_COMPLEMENT, "~" }, */ /*{ OPERATOR_XORASSIGN, "^=" }, */ {OPERATOR_LOGICALXOR, "^^"}, /*{ OPERATOR_BITXOR, "^" } */};static slang_atomparse_operator_name(slang_parse_ctx * C){ unsigned int i; for (i = 0; i < sizeof(operator_names) / sizeof(*operator_names); i++) { if (operator_names[i].o_code == (unsigned int) (*C->I)) { slang_atom atom = slang_atom_pool_atom(C->atoms, operator_names[i].o_name); if (atom == SLANG_ATOM_NULL) { slang_info_log_memory(C->L); return 0; } C->I++; return atom; } } return 0;}static intparse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O, slang_function * func){ /* parse function type and name */ if (!parse_fully_specified_type(C, O, &func->header.type)) return 0; switch (*C->I++) { case FUNCTION_ORDINARY: func->kind = SLANG_FUNC_ORDINARY; func->header.a_name = parse_identifier(C); if (func->header.a_name == SLANG_ATOM_NULL) return 0; break; case FUNCTION_CONSTRUCTOR: func->kind = SLANG_FUNC_CONSTRUCTOR; if (func->header.type.specifier.type == SLANG_SPEC_STRUCT) return 0; func->header.a_name = slang_atom_pool_atom(C->atoms, slang_type_specifier_type_to_string (func->header.type.specifier.type)); if (func->header.a_name == SLANG_ATOM_NULL) { slang_info_log_memory(C->L); return 0; } break; case FUNCTION_OPERATOR: func->kind = SLANG_FUNC_OPERATOR; func->header.a_name = parse_operator_name(C); if (func->header.a_name == SLANG_ATOM_NULL) return 0; break; default: return 0; } if (!legal_identifier(func->header.a_name)) { slang_info_log_error(C->L, "illegal function name '%s'", (char *) func->header.a_name); return 0; } /* parse function parameters */ while (*C->I++ == PARAMETER_NEXT) { slang_variable *p = slang_variable_scope_grow(func->parameters); if (!p) { slang_info_log_memory(C->L); return 0; } if (!parse_parameter_declaration(C, O, p)) return 0; } /* if the function returns a value, append a hidden __retVal 'out' * parameter that corresponds to the return value. */ if (_slang_function_has_return_value(func)) { slang_variable *p = slang_variable_scope_grow(func->parameters); slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal"); assert(a_retVal); p->a_name = a_retVal; p->type = func->header.type; p->type.qualifier = SLANG_QUAL_OUT; } /* function formal parameters and local variables share the same * scope, so save the information about param count in a seperate * place also link the scope to the global variable scope so when a * given identifier is not found here, the search process continues * in the global space */ func->param_count = func->parameters->num_variables; func->parameters->outer_scope = O->vars; return 1;}static intparse_function_definition(slang_parse_ctx * C, slang_output_ctx * O, slang_function * func){ slang_output_ctx o = *O; if (!parse_function_prototype(C, O, func)) return 0; /* create function's body operation */ func->body = (slang_operation *) _slang_alloc(sizeof(slang_operation)); if (func->body == NULL) { slang_info_log_memory(C->L); return 0; } if (!slang_operation_construct(func->body)) { _slang_free(func->body); func->body = NULL; slang_info_log_memory(C->L); return 0; } /* to parse the body the parse context is modified in order to * capture parsed variables into function's local variable scope */ C->global_scope = GL_FALSE; o.vars = func->parameters; if (!parse_statement(C, &o, func->body)) return 0; C->global_scope = GL_TRUE; return 1;}static GLbooleaninitialize_global(slang_assemble_ctx * A, slang_variable * var){ slang_operation op_id, op_assign; GLboolean result; /* construct the left side of assignment */ if (!slang_operation_construct(&op_id)) return GL_FALSE; op_id.type = SLANG_OPER_IDENTIFIER; op_id.a_id = var->a_name; /* put the variable into operation's scope */ op_id.locals->variables = (slang_variable **) _slang_alloc(sizeof(slang_variable *)); if (op_id.locals->variables == NULL) { slang_operation_destruct(&op_id); return GL_FALSE; } op_id.locals->num_variables = 1; op_id.locals->variables[0] = var; /* construct the assignment expression */ if (!slang_operation_construct(&op_assign)) { op_id.locals->num_variables = 0; slang_operation_destruct(&op_id); return GL_FALSE; } op_assign.type = SLANG_OPER_ASSIGN; op_assign.children = (slang_operation *) _slang_alloc(2 * sizeof(slang_operation)); if (op_assign.children == NULL) { slang_operation_destruct(&op_assign); op_id.locals->num_variables = 0; slang_operation_destruct(&op_id); return GL_FALSE; } op_assign.num_children = 2; op_assign.children[0] = op_id; op_assign.children[1] = *var->initializer; result = 1; /* carefully destroy the operations */ op_assign.num_children = 0; _slang_free(op_assign.children); op_assign.children = NULL; slang_operation_destruct(&op_assign); op_id.locals->num_variables = 0; slang_operation_destruct(&op_id); if (!result) return GL_FALSE; return GL_TRUE;}/* init declarator list */#define DECLARATOR_NONE 0#define DECLARATOR_NEXT 1/* variable declaration */#define VARIABLE_NONE 0#define VARIABLE_IDENTIFIER 1#define VARIABLE_INITIALIZER 2#define VARIABLE_ARRAY_EXPLICIT 3#define VARIABLE_ARRAY_UNKNOWN 4/** * Parse the initializer for a variable declaration. */static intparse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, const slang_fully_specified_type * type){ slang_variable *var; slang_atom a_name; /* empty init declatator (without name, e.g. "float ;") */ if (*C->I++ == VARIABLE_NONE) return 1; a_name = parse_identifier(C); /* check if name is already in this scope */ if (_slang_locate_variable(O->vars, a_name, GL_FALSE)) { slang_info_log_error(C->L, "declaration of '%s' conflicts with previous declaration", (char *) a_name); return 0; } /* make room for the new variable and initialize it */ var = slang_variable_scope_grow(O->vars); if (!var) { slang_info_log_memory(C->L); return 0; } /* copy the declarator qualifier type, parse the identifier */ var->type.qualifier = type->qualifier; var->a_name = a_name; if (var->a_name == SLANG_ATOM_NULL) return 0; switch (*C->I++) { case VARIABLE_NONE: /* simple variable declarator - just copy the specifier */ if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier)) return 0; break; case VARIABLE_INITIALIZER: /* initialized variable - copy the specifier and parse the expression */ if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier)) return 0; var->initializer = (slang_operation *) _slang_alloc(sizeof(slang_operation)); if (var->initializer == NULL) { slang_info_log_memory(C->L); return 0; } if (!slang_operation_construct(var->initializer)) { _slang_free(var->initializer); var->initializer = NULL; slang_info_log_memory(C->L); return 0; } if (!parse_expression(C, O, var->initializer)) return 0; break; case VARIABLE_ARRAY_UNKNOWN: /* unsized array - mark it as array and copy the specifier to the array element */ if (!convert_to_array(C, var, &type->specifier)) return GL_FALSE; break; case VARIABLE_ARRAY_EXPLICIT: if (!convert_to_array(C, var, &type->specifier)) return GL_FALSE; if (!parse_array_len(C, O, &var->array_len)) return GL_FALSE; break; default: return 0; } /* allocate global address space for a variable with a known size */ if (C->global_scope && !(var->type.specifier.type == SLANG_SPEC_ARRAY && var->array_len == 0)) { if (!calculate_var_size(C, O, var)) return GL_FALSE; var->address = slang_var_pool_alloc(O->global_pool, var->size); } /* emit code for global var decl */ if (C->global_scope) { slang_assemble_ctx A; A.atoms = C->atoms; A.space.funcs = O->funs; A.space.structs = O->structs; A.space.vars = O->vars; A.program = O->program; A.vartable = O->vartable; A.log = C->L; A.curFuncEndLabel = NULL; if (!_slang_codegen_global_variable(&A, var, C->type)) return 0; } /* initialize global variable */ if (C->global_scope) { if (var->initializer != NULL) { slang_assemble_ctx A; A.atoms = C->atoms; A.space.funcs = O->funs; A.space.structs = O->structs; A.space.vars = O->vars; if (!initialize_global(&A, var)) return 0; } } return 1;}/** * Parse a list of variable declarations. Each variable may have an * initializer. */static intparse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O){ slang_fully_specified_type type; /* parse the fully specified type, common to all declarators */ if (!slang_fully_specified_type_construct(&type)) return 0; if (!parse_fully_specified_type(C, O, &type)) { slang_fully_specified_type_destruct(&type); return 0; } /* parse declarators, pass-in the parsed type */ do { if (!parse_init_declarator(C, O, &type)) { slang_fully_specified_type_destruct(&type); return 0; } } while (*C->I++ == DECLARATOR_NEXT); slang_fully_specified_type_destruct(&type); return 1;}/** * Parse a function definition or declaration. * \param C parsing context * \param O output context * \param definition if non-zero expect a definition, else a declaration * \param parsed_func_ret returns the parsed function * \return GL_TRUE if success, GL_FALSE if failure */static GLbooleanparse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition, slang_function ** parsed_func_ret){ slang_function parsed_func, *found_func; /* parse function definition/declaration */ if (!slang_function_construct(&parsed_func)) return GL_FALSE; if (definition) { if (!parse_function_definition(C, O, &parsed_func)) { slang_function_destruct(&parsed_func); return GL_FALSE; } } else { if (!parse_function_prototype(C, O, &parsed_func)) { slang_function_destruct(&parsed_func); return GL_FALSE; } } /* find a function with a prototype matching the parsed one - only * the current scope is being searched to allow built-in function * overriding */ found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -