gskslfunction: Parse arguments

This commit is contained in:
Benjamin Otte
2017-09-28 23:11:34 +02:00
parent fad4112d78
commit c22b36d2b5
2 changed files with 113 additions and 7 deletions

View File

@@ -21,10 +21,12 @@
#include "gskslfunctionprivate.h"
#include "gskslnodeprivate.h"
#include "gskslpointertypeprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslscopeprivate.h"
#include "gsksltokenizerprivate.h"
#include "gsksltypeprivate.h"
#include "gskslvariableprivate.h"
#include "gskspvwriterprivate.h"
static GskSlFunction *
@@ -220,6 +222,8 @@ struct _GskSlFunctionDeclared {
GskSlScope *scope;
GskSlType *return_type;
char *name;
GskSlVariable **arguments;
gsize n_arguments;
GSList *statements;
};
@@ -227,7 +231,11 @@ static void
gsk_sl_function_declared_free (GskSlFunction *function)
{
GskSlFunctionDeclared *declared = (GskSlFunctionDeclared *) function;
guint i;
for (i = 0; i < declared->n_arguments; i++)
gsk_sl_variable_unref (declared->arguments[i]);
g_free (declared->arguments);
if (declared->scope)
gsk_sl_scope_unref (declared->scope);
if (declared->return_type)
@@ -260,12 +268,19 @@ gsk_sl_function_declared_print (const GskSlFunction *function,
{
const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
GSList *l;
guint i;
g_string_append (string, gsk_sl_type_get_name (declared->return_type));
g_string_append (string, "\n");
g_string_append (string, declared->name);
g_string_append (string, " (");
for (i = 0; i < declared->n_arguments; i++)
{
if (i > 0)
g_string_append (string, ", ");
gsk_sl_variable_print (declared->arguments[i], string);
}
g_string_append (string, ")\n");
g_string_append (string, "{\n");
@@ -284,10 +299,34 @@ gsk_sl_function_declared_matches (const GskSlFunction *function,
gsize n_arguments,
GError **error)
{
if (n_arguments > 0)
const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
guint i;
if (n_arguments != declared->n_arguments)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "Function only takes %u arguments.", 0);
return FALSE;
g_set_error (error,
GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH,
"Function %s needs %"G_GSIZE_FORMAT" arguments, but %"G_GSIZE_FORMAT" given.",
declared->name,
declared->n_arguments,
n_arguments);
return FALSE;
}
for (i = 0; i < n_arguments; i++)
{
GskSlType *type = gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (declared->arguments[i]));
if (!gsk_sl_type_can_convert (type, arguments[i]))
{
g_set_error (error,
GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH,
"Cannot convert argument %u from %s to %s.",
i,
gsk_sl_type_get_name (arguments[i]),
gsk_sl_type_get_name (type));
return FALSE;
}
}
return TRUE;
@@ -385,7 +424,71 @@ gsk_sl_function_new_parse (GskSlScope *scope,
}
gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
function->scope = gsk_sl_scope_new (scope, function->return_type);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
{
GPtrArray *arguments = g_ptr_array_new ();
while (TRUE)
{
GskSlDecorations decoration;
GskSlType *type;
GskSlVariable *variable;
gsk_sl_decoration_list_parse (scope,
preproc,
&decoration);
type = gsk_sl_type_new_parse (scope, preproc);
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
GskSlPointerType *pointer_type;
guint i;
if (gsk_sl_scope_lookup_variable (function->scope, token->str))
{
for (i = 0; i < function->n_arguments; i++)
{
if (g_str_equal (gsk_sl_variable_get_name (g_ptr_array_index (arguments, i)), token->str))
{
gsk_sl_preprocessor_error (preproc, DECLARATION, "Duplicate argument name \"%s\".", token->str);
break;
}
}
if (i == arguments->len)
gsk_sl_preprocessor_warn (preproc, SHADOW, "Function argument \"%s\" shadows global variable of same name.", token->str);
}
pointer_type = gsk_sl_pointer_type_new (type, TRUE, decoration.values[GSK_SL_DECORATION_CALLER_ACCESS].value);
variable = gsk_sl_variable_new (pointer_type, g_strdup (token->str), NULL, decoration.values[GSK_SL_DECORATION_CONST].set);
gsk_sl_pointer_type_unref (pointer_type);
g_ptr_array_add (arguments, variable);
gsk_sl_scope_add_variable (function->scope, variable);
gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
}
else
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected an identifier as the variable name.");
}
gsk_sl_type_unref (type);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
break;
gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
}
function->n_arguments = arguments->len;
function->arguments = (GskSlVariable **) g_ptr_array_free (arguments, FALSE);
}
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected a closing \")\"");
@@ -407,8 +510,6 @@ gsk_sl_function_new_parse (GskSlScope *scope,
}
gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
function->scope = gsk_sl_scope_new (scope, function->return_type);
for (token = gsk_sl_preprocessor_get (preproc);
!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE) && !gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
token = gsk_sl_preprocessor_get (preproc))

View File

@@ -382,11 +382,11 @@ gsk_sl_node_parse_statement (GskSlScope *scope,
case GSK_SL_TOKEN_DMAT4X3:
case GSK_SL_TOKEN_DMAT4X4:
case GSK_SL_TOKEN_STRUCT:
case GSK_SL_TOKEN_IDENTIFIER:
{
GskSlType *type;
GskSlDecorations decoration;
its_a_type:
gsk_sl_decoration_list_parse (scope,
preproc,
&decoration);
@@ -458,10 +458,15 @@ gsk_sl_node_parse_statement (GskSlScope *scope,
}
break;
case GSK_SL_TOKEN_IDENTIFIER:
if (gsk_sl_scope_lookup_type (scope, token->str))
goto its_a_type;
/* else fall through*/
default:
{
GskSlNodeExpression *node_expression;
node_expression = gsk_sl_node_new (GskSlNodeExpression, &GSK_SL_NODE_EXPRESSION);
node_expression->expression = gsk_sl_expression_parse (scope, preproc);