📄 slang_compile.c
字号:
return 0; break; case OP_SUBASSIGN: op->type = slang_oper_subassign; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_MULASSIGN: op->type = slang_oper_mulassign; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_DIVASSIGN: op->type = slang_oper_divassign; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; /*case OP_MODASSIGN:*/ /*case OP_LSHASSIGN:*/ /*case OP_RSHASSIGN:*/ /*case OP_ORASSIGN:*/ /*case OP_XORASSIGN:*/ /*case OP_ANDASSIGN:*/ case OP_SELECT: op->type = slang_oper_select; if (!handle_nary_expression (C, op, &ops, &num_ops, 3)) return 0; break; case OP_LOGICALOR: op->type = slang_oper_logicalor; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_LOGICALXOR: op->type = slang_oper_logicalxor; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_LOGICALAND: op->type = slang_oper_logicaland; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; /*case OP_BITOR:*/ /*case OP_BITXOR:*/ /*case OP_BITAND:*/ case OP_EQUAL: op->type = slang_oper_equal; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_NOTEQUAL: op->type = slang_oper_notequal; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_LESS: op->type = slang_oper_less; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_GREATER: op->type = slang_oper_greater; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_LESSEQUAL: op->type = slang_oper_lessequal; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_GREATEREQUAL: op->type = slang_oper_greaterequal; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; /*case OP_LSHIFT:*/ /*case OP_RSHIFT:*/ case OP_ADD: op->type = slang_oper_add; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_SUBTRACT: op->type = slang_oper_subtract; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_MULTIPLY: op->type = slang_oper_multiply; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_DIVIDE: op->type = slang_oper_divide; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; /*case OP_MODULUS:*/ case OP_PREINCREMENT: op->type = slang_oper_preincrement; if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_PREDECREMENT: op->type = slang_oper_predecrement; if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_PLUS: op->type = slang_oper_plus; if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_MINUS: op->type = slang_oper_minus; if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_NOT: op->type = slang_oper_not; if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; /*case OP_COMPLEMENT:*/ case OP_SUBSCRIPT: op->type = slang_oper_subscript; if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_CALL: op->type = slang_oper_call; op->a_id = parse_identifier (C); if (op->a_id == SLANG_ATOM_NULL) return 0; while (*C->I != OP_END) if (!parse_child_operation (C, O, op, 0)) return 0; C->I++; if (!C->parsing_builtin && !slang_function_scope_find_by_name (O->funs, op->a_id, 1)) { const char *id; id = slang_atom_pool_id (C->atoms, op->a_id); if (!is_constructor_name (id, op->a_id, O->structs)) { slang_info_log_error (C->L, "%s: undeclared function name", id); return 0; } } break; case OP_FIELD: op->type = slang_oper_field; op->a_id = parse_identifier (C); if (op->a_id == SLANG_ATOM_NULL) return 0; if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_POSTINCREMENT: op->type = slang_oper_postincrement; if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_POSTDECREMENT: op->type = slang_oper_postdecrement; if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; default: return 0; } } C->I++; *oper = *ops; slang_alloc_free (ops); return 1;}/* parameter qualifier */#define PARAM_QUALIFIER_IN 0#define PARAM_QUALIFIER_OUT 1#define PARAM_QUALIFIER_INOUT 2/* function parameter array presence */#define PARAMETER_ARRAY_NOT_PRESENT 0#define PARAMETER_ARRAY_PRESENT 1static int parse_parameter_declaration (slang_parse_ctx *C, slang_output_ctx *O, slang_variable *param){ /* parse and validate the parameter's type qualifiers (there can be two at most) because * not all combinations are valid */ if (!parse_type_qualifier (C, ¶m->type.qualifier)) return 0; switch (*C->I++) { case PARAM_QUALIFIER_IN: if (param->type.qualifier != slang_qual_const && param->type.qualifier != slang_qual_none) { slang_info_log_error (C->L, "invalid type qualifier"); return 0; } break; case PARAM_QUALIFIER_OUT: if (param->type.qualifier == slang_qual_none) param->type.qualifier = slang_qual_out; else { slang_info_log_error (C->L, "invalid type qualifier"); return 0; } break; case PARAM_QUALIFIER_INOUT: if (param->type.qualifier == slang_qual_none) param->type.qualifier = slang_qual_inout; else { slang_info_log_error (C->L, "invalid type qualifier"); return 0; } break; default: return 0; } /* parse parameter's type specifier and name */ if (!parse_type_specifier (C, O, ¶m->type.specifier)) return 0; param->a_name = parse_identifier (C); if (param->a_name == SLANG_ATOM_NULL) return 0; /* if the parameter is an array, parse its size (the size must be explicitly defined */ if (*C->I++ == PARAMETER_ARRAY_PRESENT) { slang_type_specifier p; slang_type_specifier_ctr (&p); if (!slang_type_specifier_copy (&p, ¶m->type.specifier)) { slang_type_specifier_dtr (&p); return GL_FALSE; } if (!convert_to_array (C, param, &p)) { slang_type_specifier_dtr (&p); return GL_FALSE; } slang_type_specifier_dtr (&p); if (!parse_array_len (C, O, ¶m->array_len)) return GL_FALSE; } /* calculate the parameter size */ if (!calculate_var_size (C, O, param)) return GL_FALSE; /* TODO: allocate the local address here? */ return 1;}/* function type */#define FUNCTION_ORDINARY 0#define FUNCTION_CONSTRUCTOR 1#define FUNCTION_OPERATOR 2/* function parameter */#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_atom parse_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 int parse_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; } /* parse function parameters */ while (*C->I++ == PARAMETER_NEXT) { slang_variable *p; func->parameters->variables = (slang_variable *) slang_alloc_realloc ( func->parameters->variables, func->parameters->num_variables * sizeof (slang_variable), (func->parameters->num_variables + 1) * sizeof (slang_variable)); if (func->parameters->variables == NULL) { slang_info_log_memory (C->L); return 0; } p = &func->parameters->variables[func->parameters->num_variables]; if (!slang_variable_construct (p)) return 0; func->parameters->num_variables++; if (!parse_parameter_declaration (C, O, p)) return 0; } /* 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 int parse_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_malloc (sizeof (slang_operation)); if (func->body == NULL) { slang_info_log_memory (C->L); return 0; } if (!slang_operation_construct (func->body)) { slang_alloc_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 = 0; o.vars = func->parameters; if (!parse_statement (C, &o, func->body)) return 0; C->global_scope = 1; return 1;}static GLboolean initialize_global (slang_assemble_ctx *A, slang_variable *var){ slang_assembly_file_restore_point point; slang_machine mach; slang_assembly_local_info save_local = A->local; slang_operation op_id, op_assign; GLboolean result; /* save the current assembly */ if (!slang_assembly_file_restore_point_save (A->file, &point)) return GL_FALSE; /* setup the machine */ mach = *A->mach; mach.ip = A->file->count; /* allocate local storage for expression */ A->local.ret_size = 0; A->local.addr_tmp = 0; A->local.swizzle_tmp = 4; if (!slang_assembly_file_push_label (A->file, slang_asm_local_alloc, 20)) return GL_FALSE; if (!slang_assembly_file_push_label (A->file, slang_asm_enter, 20)) return GL_FALSE; /* 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_malloc (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_malloc (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; /* insert the actual expression */ result = _slang_assemble_operation (A, &op_assign, slang_ref_forbid); /* carefully destroy the operations */ op_assign.num_children = 0; slang_alloc_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; if (!slang_assembly_file_push (A->file, slang_asm_exit)) return GL_FALSE; /* execute the expression */ if (!_slang_execute2 (A->file, &mach)) return GL_FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -