📄 slang_compile.c
字号:
static int slang_struct_equal (const slang_struct *x, const slang_struct *y)
{
unsigned int i;
if (x->fields->num_variables != y->fields->num_variables)
return 0;
for (i = 0; i < x->fields->num_variables; i++)
{
slang_variable *varx = x->fields->variables + i;
slang_variable *vary = y->fields->variables + i;
if (slang_string_compare (varx->name, vary->name) != 0)
return 0;
if (!slang_type_specifier_equal (&varx->type.specifier, &vary->type.specifier))
return 0;
if (varx->type.specifier.type == slang_spec_array)
{
/* TODO compare array sizes */
}
}
return 1;
}
/* slang_function */
/* XXX mem! */
static void slang_function_construct (slang_function *func)
{
func->kind = slang_func_ordinary;
slang_variable_construct (&func->header);
func->parameters = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope));
slang_variable_scope_construct (func->parameters);
func->body = NULL;
func->address = ~0;
}
static void slang_function_destruct (slang_function *func)
{
slang_variable_destruct (&func->header);
slang_variable_scope_destruct (func->parameters);
slang_alloc_free (func->parameters);
if (func->body != NULL)
{
slang_operation_destruct (func->body);
slang_alloc_free (func->body);
}
}
/* slang_function_scope */
static void slang_function_scope_construct (slang_function_scope *scope)
{
scope->functions = NULL;
scope->num_functions = 0;
scope->outer_scope = NULL;
}
static void slang_function_scope_destruct (slang_function_scope *scope)
{
unsigned int i;
for (i = 0; i < scope->num_functions; i++)
slang_function_destruct (scope->functions + i);
slang_alloc_free (scope->functions);
}
static int slang_function_scope_find_by_name (slang_function_scope *funcs, const char *name,
int all_scopes)
{
unsigned int i;
for (i = 0; i < funcs->num_functions; i++)
if (slang_string_compare (name, funcs->functions[i].header.name) == 0)
return 1;
if (all_scopes && funcs->outer_scope != NULL)
return slang_function_scope_find_by_name (funcs->outer_scope, name, 1);
return 0;
}
static slang_function *slang_function_scope_find (slang_function_scope *funcs, slang_function *fun,
int all_scopes)
{
unsigned int i;
for (i = 0; i < funcs->num_functions; i++)
{
slang_function *f = funcs->functions + i;
unsigned int j;
if (slang_string_compare (fun->header.name, f->header.name) != 0)
continue;
if (fun->param_count != f->param_count)
continue;
for (j = 0; j < fun->param_count; j++)
{
if (!slang_type_specifier_equal (&fun->parameters->variables[j].type.specifier,
&f->parameters->variables[j].type.specifier))
{
break;
}
}
if (j == fun->param_count)
return f;
}
if (all_scopes && funcs->outer_scope != NULL)
return slang_function_scope_find (funcs->outer_scope, fun, 1);
return NULL;
}
/* slang_translation_unit */
void slang_translation_unit_construct (slang_translation_unit *unit)
{
slang_variable_scope_construct (&unit->globals);
slang_function_scope_construct (&unit->functions);
slang_struct_scope_construct (&unit->structs);
}
void slang_translation_unit_destruct (slang_translation_unit *unit)
{
slang_variable_scope_destruct (&unit->globals);
slang_function_scope_destruct (&unit->functions);
slang_struct_scope_destruct (&unit->structs);
}
/* slang_info_log */
static char *out_of_memory = "error: out of memory\n";
void slang_info_log_construct (slang_info_log *log)
{
log->text = NULL;
log->dont_free_text = 0;
}
void slang_info_log_destruct (slang_info_log *log)
{
if (!log->dont_free_text)
slang_alloc_free (log->text);
}
static int slang_info_log_message (slang_info_log *log, const char *prefix, const char *msg)
{
unsigned int new_size;
if (log->dont_free_text)
return 0;
new_size = slang_string_length (prefix) + 3 + slang_string_length (msg);
if (log->text != NULL)
{
log->text = (char *) slang_alloc_realloc (log->text, slang_string_length (log->text) + 1,
new_size + slang_string_length (log->text) + 1);
}
else
{
log->text = (char *) slang_alloc_malloc (new_size + 1);
if (log->text != NULL)
*log->text = '\0';
}
if (log->text == NULL)
return 0;
slang_string_concat (log->text, prefix);
slang_string_concat (log->text, ": ");
slang_string_concat (log->text, msg);
slang_string_concat (log->text, "\n");
return 1;
}
int slang_info_log_error (slang_info_log *log, const char *msg, ...)
{
va_list va;
char buf[1024];
va_start (va, msg);
vsprintf (buf, msg, va);
if (slang_info_log_message (log, "error", buf))
return 1;
slang_info_log_memory (log);
va_end (va);
return 0;
}
int slang_info_log_warning (slang_info_log *log, const char *msg, ...)
{
va_list va;
char buf[1024];
va_start (va, msg);
vsprintf (buf, msg, va);
if (slang_info_log_message (log, "warning", buf))
return 1;
slang_info_log_memory (log);
va_end (va);
return 0;
}
void slang_info_log_memory (slang_info_log *log)
{
if (!slang_info_log_message (log, "error", "out of memory"))
{
log->dont_free_text = 1;
log->text = out_of_memory;
}
}
/* slang_parse_ctx */
typedef struct slang_parse_ctx_
{
const byte *I;
slang_info_log *L;
int parsing_builtin;
} slang_parse_ctx;
/* _slang_compile() */
static int parse_identifier (slang_parse_ctx *C, char **id)
{
*id = slang_string_duplicate ((const char *) C->I);
if (*id == NULL)
{
slang_info_log_memory (C->L);
return 0;
}
C->I += strlen ((const char *) C->I) + 1;
return 1;
}
static int parse_number (slang_parse_ctx *C, int *number)
{
const int radix = (int) (*C->I++);
*number = 0;
while (*C->I != '\0')
{
int digit;
if (*C->I >= '0' && *C->I <= '9')
digit = (int) (*C->I - '0');
else if (*C->I >= 'A' && *C->I <= 'Z')
digit = (int) (*C->I - 'A') + 10;
else
digit = (int) (*C->I - 'a') + 10;
*number = *number * radix + digit;
C->I++;
}
C->I++;
if (*number > 65535)
slang_info_log_warning (C->L, "%d: literal integer overflow", *number);
return 1;
}
static int parse_float (slang_parse_ctx *C, float *number)
{
char *integral = NULL;
char *fractional = NULL;
char *exponent = NULL;
char *whole = NULL;
if (!parse_identifier (C, &integral))
return 0;
if (!parse_identifier (C, &fractional))
{
slang_alloc_free (integral);
return 0;
}
if (!parse_identifier (C, &exponent))
{
slang_alloc_free (fractional);
slang_alloc_free (integral);
return 0;
}
whole = (char *) (slang_alloc_malloc ((strlen (integral) + strlen (fractional) + strlen (
exponent) + 3) * sizeof (char)));
if (whole == NULL)
{
slang_alloc_free (exponent);
slang_alloc_free (fractional);
slang_alloc_free (integral);
slang_info_log_memory (C->L);
return 0;
}
slang_string_copy (whole, integral);
slang_string_concat (whole, ".");
slang_string_concat (whole, fractional);
slang_string_concat (whole, "E");
slang_string_concat (whole, exponent);
*number = (float) (atof (whole));
slang_alloc_free (whole);
slang_alloc_free (exponent);
slang_alloc_free (fractional);
slang_alloc_free (integral);
return 1;
}
/* revision number - increment after each change affecting emitted output */
#define REVISION 2
static int check_revision (slang_parse_ctx *C)
{
if (*C->I != REVISION)
{
slang_info_log_error (C->L, "internal compiler error");
return 0;
}
C->I++;
return 1;
}
static int parse_statement (slang_parse_ctx *, slang_operation *, slang_variable_scope *,
slang_struct_scope *, slang_function_scope *);
static int parse_expression (slang_parse_ctx *, slang_operation *, slang_variable_scope *,
slang_struct_scope *, slang_function_scope *);
/* type qualifier */
#define TYPE_QUALIFIER_NONE 0
#define TYPE_QUALIFIER_CONST 1
#define TYPE_QUALIFIER_ATTRIBUTE 2
#define TYPE_QUALIFIER_VARYING 3
#define TYPE_QUALIFIER_UNIFORM 4
#define TYPE_QUALIFIER_FIXEDOUTPUT 5
#define TYPE_QUALIFIER_FIXEDINPUT 6
static int parse_type_qualifier (slang_parse_ctx *C, slang_type_qualifier *qual)
{
switch (*C->I++)
{
case TYPE_QUALIFIER_NONE:
*qual = slang_qual_none;
break;
case TYPE_QUALIFIER_CONST:
*qual = slang_qual_const;
break;
case TYPE_QUALIFIER_ATTRIBUTE:
*qual = slang_qual_attribute;
break;
case TYPE_QUALIFIER_VARYING:
*qual = slang_qual_varying;
break;
case TYPE_QUALIFIER_UNIFORM:
*qual = slang_qual_uniform;
break;
case TYPE_QUALIFIER_FIXEDOUTPUT:
*qual = slang_qual_fixedoutput;
break;
case TYPE_QUALIFIER_FIXEDINPUT:
*qual = slang_qual_fixedinput;
break;
default:
return 0;
}
return 1;
}
/* type specifier */
#define TYPE_SPECIFIER_VOID 0
#define TYPE_SPECIFIER_BOOL 1
#define TYPE_SPECIFIER_BVEC2 2
#define TYPE_SPECIFIER_BVEC3 3
#define TYPE_SPECIFIER_BVEC4 4
#define TYPE_SPECIFIER_INT 5
#define TYPE_SPECIFIER_IVEC2 6
#define TYPE_SPECIFIER_IVEC3 7
#define TYPE_SPECIFIER_IVEC4 8
#define TYPE_SPECIFIER_FLOAT 9
#define TYPE_SPECIFIER_VEC2 10
#define TYPE_SPECIFIER_VEC3 11
#define TYPE_SPECIFIER_VEC4 12
#define TYPE_SPECIFIER_MAT2 13
#define TYPE_SPECIFIER_MAT3 14
#define TYPE_SPECIFIER_MAT4 15
#define TYPE_SPECIFIER_SAMPLER1D 16
#define TYPE_SPECIFIER_SAMPLER2D 17
#define TYPE_SPECIFIER_SAMPLER3D 18
#define TYPE_SPECIFIER_SAMPLERCUBE 19
#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
#define TYPE_SPECIFIER_STRUCT 22
#define TYPE_SPECIFIER_TYPENAME 23
/* structure field */
#define FIELD_NONE 0
#define FIELD_NEXT 1
#define FIELD_ARRAY 2
static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec,
slang_struct_scope *structs, slang_variable_scope *scope, slang_function_scope *funcs)
{
switch (*C->I++)
{
case TYPE_SPECIFIER_VOID:
spec->type = slang_spec_void;
break;
case TYPE_SPECIFIER_BOOL:
spec->type = slang_spec_bool;
break;
case TYPE_SPECIFIER_BVEC2:
spec->type = slang_spec_bvec2;
break;
case TYPE_SPECIFIER_BVEC3:
spec->type = slang_spec_bvec3;
break;
case TYPE_SPECIFIER_BVEC4:
spec->type = slang_spec_bvec4;
break;
case TYPE_SPECIFIER_INT:
spec->type = slang_spec_int;
break;
case TYPE_SPECIFIER_IVEC2:
spec->type = slang_spec_ivec2;
break;
case TYPE_SPECIFIER_IVEC3:
spec->type = slang_spec_ivec3;
break;
case TYPE_SPECIFIER_IVEC4:
spec->type = slang_spec_ivec4;
break;
case TYPE_SPECIFIER_FLOAT:
spec->type = slang_spec_float;
break;
case TYPE_SPECIFIER_VEC2:
spec->type = slang_spec_vec2;
break;
case TYPE_SPECIFIER_VEC3:
spec->type = slang_spec_vec3;
break;
case TYPE_SPECIFIER_VEC4:
spec->type = slang_spec_vec4;
break;
case TYPE_SPECIFIER_MAT2:
spec->type = slang_spec_mat2;
break;
case TYPE_SPECIFIER_MAT3:
spec->type = slang_spec_mat3;
break;
case TYPE_SPECIFIER_MAT4:
spec->type = slang_spec_mat4;
break;
case TYPE_SPECIFIER_SAMPLER1D:
spec->type = slang_spec_sampler1D;
break;
case TYPE_SPECIFIER_SAMPLER2D:
spec->type = slang_spec_sampler2D;
break;
case TYPE_SPECIFIER_SAMPLER3D:
spec->type = slang_spec_sampler3D;
break;
case TYPE_SPECIFIER_SAMPLERCUBE:
spec->type = slang_spec_samplerCube;
break;
case TYPE_SPECIFIER_SAMPLER1DSHADOW:
spec->type = slang_spec_sampler1DShadow;
break;
case TYPE_SPECIFIER_SAMPLER2DSHADOW:
spec->type = slang_spec_sampler2DShadow;
break;
case TYPE_SPECIFIER_STRUCT:
spec->type = slang_spec_struct;
{
char *name;
if (!parse_identifier (C, &name))
return 0;
if (*name != '\0' && slang_struct_scope_find (structs, name, 0) != NULL)
{
slang_info_log_error (C->L, "%s: duplicate type name", name);
slang_alloc_free (name);
return 0;
}
spec->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));
if (spec->_struct == NULL)
{
slang_alloc_free (name);
slang_info_log_memory (C->L);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -