[gtk+/wip/otte/shader: 31/55] gsksl: Add GskSlPrinter



commit 754f73ff75a59b7beb683e7d4a15741ea987e37c
Author: Benjamin Otte <otte redhat com>
Date:   Sat Sep 30 04:36:19 2017 +0200

    gsksl: Add GskSlPrinter
    
    This is a subclass for pretty-printing. It's not yet very useful, but
    will become so once we nest blocks or have way too long statements to
    fit on a single line.

 gsk/gskslexpression.c         |   86 ++++++++++---------
 gsk/gskslexpressionprivate.h  |    2 +-
 gsk/gskslfunction.c           |  151 +++++++++++++++++++++++++++++----
 gsk/gskslfunctionprivate.h    |   26 +------
 gsk/gskslnode.c               |   37 ++++----
 gsk/gskslnodeprivate.h        |    8 +-
 gsk/gskslpointertype.c        |   11 ++-
 gsk/gskslpointertypeprivate.h |    2 +-
 gsk/gskslprinter.c            |  154 ++++++++++++++++++++++++++++++++++
 gsk/gskslprinterprivate.h     |   53 ++++++++++++
 gsk/gskslprogram.c            |   24 ++++--
 gsk/gskslscope.c              |   17 ++++
 gsk/gsksltype.c               |  185 +++++++++++++++++++++++++++++-----------
 gsk/gsksltypeprivate.h        |   12 +--
 gsk/gsksltypesprivate.h       |   53 ++++++++++++
 gsk/gskslvalue.c              |    4 +-
 gsk/gskslvalueprivate.h       |    2 +-
 gsk/gskslvariable.c           |   11 ++-
 gsk/gskslvariableprivate.h    |    2 +-
 gsk/meson.build               |    2 +
 20 files changed, 653 insertions(+), 189 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 5aaa29f..3f194c5 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -24,6 +24,7 @@
 #include "gskslfunctionprivate.h"
 #include "gskslnodeprivate.h"
 #include "gskslpointertypeprivate.h"
+#include "gskslprinterprivate.h"
 #include "gskslscopeprivate.h"
 #include "gsksltokenizerprivate.h"
 #include "gsksltypeprivate.h"
@@ -44,7 +45,7 @@ struct _GskSlExpressionClass {
   void                  (* free)                                (GskSlExpression        *expression);
 
   void                  (* print)                               (const GskSlExpression  *expression,
-                                                                 GString                *string);
+                                                                 GskSlPrinter           *printer);
   GskSlType *           (* get_return_type)                     (const GskSlExpression  *expression);
   GskSlValue *          (* get_constant)                        (const GskSlExpression  *expression);
   guint32               (* write_spv)                           (const GskSlExpression  *expression,
@@ -92,52 +93,52 @@ gsk_sl_expression_assignment_free (GskSlExpression *expression)
 
 static void
 gsk_sl_expression_assignment_print (const GskSlExpression *expression,
-                                    GString               *string)
+                                    GskSlPrinter          *printer)
 {
   const GskSlExpressionAssignment *assignment = (const GskSlExpressionAssignment *) expression;
 
-  gsk_sl_expression_print (assignment->lvalue, string);
+  gsk_sl_expression_print (assignment->lvalue, printer);
 
   switch (assignment->op)
   {
     case GSK_SL_TOKEN_EQUAL:
-      g_string_append (string, " = ");
+      gsk_sl_printer_append (printer, " = ");
       break;
     case GSK_SL_TOKEN_MUL_ASSIGN:
-      g_string_append (string, " *= ");
+      gsk_sl_printer_append (printer, " *= ");
       break;
     case GSK_SL_TOKEN_DIV_ASSIGN:
-      g_string_append (string, " /= ");
+      gsk_sl_printer_append (printer, " /= ");
       break;
     case GSK_SL_TOKEN_MOD_ASSIGN:
-      g_string_append (string, " %= ");
+      gsk_sl_printer_append (printer, " %= ");
       break;
     case GSK_SL_TOKEN_ADD_ASSIGN:
-      g_string_append (string, " += ");
+      gsk_sl_printer_append (printer, " += ");
       break;
     case GSK_SL_TOKEN_SUB_ASSIGN:
-      g_string_append (string, " -= ");
+      gsk_sl_printer_append (printer, " -= ");
       break;
     case GSK_SL_TOKEN_LEFT_ASSIGN:
-      g_string_append (string, " <<= ");
+      gsk_sl_printer_append (printer, " <<= ");
       break;
     case GSK_SL_TOKEN_RIGHT_ASSIGN:
-      g_string_append (string, " >>= ");
+      gsk_sl_printer_append (printer, " >>= ");
       break;
     case GSK_SL_TOKEN_AND_ASSIGN:
-      g_string_append (string, " &= ");
+      gsk_sl_printer_append (printer, " &= ");
       break;
     case GSK_SL_TOKEN_XOR_ASSIGN:
-      g_string_append (string, " ^= ");
+      gsk_sl_printer_append (printer, " ^= ");
       break;
     case GSK_SL_TOKEN_OR_ASSIGN:
-      g_string_append (string, " |= ");
+      gsk_sl_printer_append (printer, " |= ");
       break;
     default:
       g_assert_not_reached ();
       break;
   }
-  gsk_sl_expression_print (assignment->rvalue, string);
+  gsk_sl_expression_print (assignment->rvalue, printer);
 }
 
 static GskSlType *
@@ -219,7 +220,7 @@ gsk_sl_expression_operation_free (GskSlExpression *expression)
 
 static void
 gsk_sl_expression_operation_print (const GskSlExpression *expression,
-                                   GString               *string)
+                                   GskSlPrinter          *printer)
 {
   const char *op_str[] = {
     [GSK_SL_OPERATION_MUL] = " * ",
@@ -246,9 +247,9 @@ gsk_sl_expression_operation_print (const GskSlExpression *expression,
 
   /* XXX: figure out the need for bracketing here */
 
-  gsk_sl_expression_print (operation->left, string);
-  g_string_append (string, op_str[operation->op]);
-  gsk_sl_expression_print (operation->right, string);
+  gsk_sl_expression_print (operation->left, printer);
+  gsk_sl_printer_append (printer, op_str[operation->op]);
+  gsk_sl_expression_print (operation->right, printer);
 }
 
 static GskSlType *
@@ -655,11 +656,11 @@ gsk_sl_expression_reference_free (GskSlExpression *expression)
 
 static void
 gsk_sl_expression_reference_print (const GskSlExpression *expression,
-                                   GString   *string)
+                                   GskSlPrinter          *printer)
 {
   GskSlExpressionReference *reference = (GskSlExpressionReference *) expression;
 
-  g_string_append (string, gsk_sl_variable_get_name (reference->variable));
+  gsk_sl_printer_append (printer, gsk_sl_variable_get_name (reference->variable));
 }
 
 static GskSlType *
@@ -746,22 +747,22 @@ gsk_sl_expression_function_call_free (GskSlExpression *expression)
 
 static void
 gsk_sl_expression_function_call_print (const GskSlExpression *expression,
-                                       GString               *string)
+                                       GskSlPrinter          *printer)
 {
   const GskSlExpressionFunctionCall *function_call = (const GskSlExpressionFunctionCall *) expression;
   guint i;
 
-  g_string_append (string, gsk_sl_function_get_name (function_call->function));
-  g_string_append (string, " (");
+  gsk_sl_printer_append (printer, gsk_sl_function_get_name (function_call->function));
+  gsk_sl_printer_append (printer, " (");
   
   for (i = 0; i < function_call->n_arguments; i++)
     {
       if (i > 0)
-        g_string_append (string, ", ");
-      gsk_sl_expression_print (function_call->arguments[i], string);
+        gsk_sl_printer_append (printer, ", ");
+      gsk_sl_expression_print (function_call->arguments[i], printer);
     }
 
-  g_string_append (string, ")");
+  gsk_sl_printer_append (printer, ")");
 }
 
 static GskSlType *
@@ -819,13 +820,13 @@ gsk_sl_expression_member_free (GskSlExpression *expression)
 
 static void
 gsk_sl_expression_member_print (const GskSlExpression *expression,
-                                GString               *string)
+                                GskSlPrinter          *printer)
 {
   const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression;
 
-  gsk_sl_expression_print (member->expr, string);
-  g_string_append (string, ".");
-  g_string_append (string, gsk_sl_type_get_member_name (gsk_sl_expression_get_return_type (member->expr), 
member->id));
+  gsk_sl_expression_print (member->expr, printer);
+  gsk_sl_printer_append (printer, ".");
+  gsk_sl_printer_append (printer, gsk_sl_type_get_member_name (gsk_sl_expression_get_return_type 
(member->expr), member->id));
 }
 
 static GskSlType *
@@ -918,16 +919,16 @@ gsk_sl_expression_swizzle_free (GskSlExpression *expression)
 
 static void
 gsk_sl_expression_swizzle_print (const GskSlExpression *expression,
-                                 GString               *string)
+                                 GskSlPrinter          *printer)
 {
   const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
   guint i;
 
-  gsk_sl_expression_print (swizzle->expr, string);
-  g_string_append (string, ".");
+  gsk_sl_expression_print (swizzle->expr, printer);
+  gsk_sl_printer_append (printer, ".");
   for (i = 0; i < swizzle->length; i++)
     {
-      g_string_append_c (string, swizzle_options[swizzle->name][swizzle->indexes[i]]);
+      gsk_sl_printer_append_c (printer, swizzle_options[swizzle->name][swizzle->indexes[i]]);
     }
 }
 
@@ -1078,12 +1079,12 @@ gsk_sl_expression_negation_free (GskSlExpression *expression)
 
 static void
 gsk_sl_expression_negation_print (const GskSlExpression *expression,
-                                  GString               *string)
+                                  GskSlPrinter          *printer)
 {
   const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
 
-  g_string_append (string, "-");
-  gsk_sl_expression_print (negation->expr, string);
+  gsk_sl_printer_append (printer, "-");
+  gsk_sl_expression_print (negation->expr, printer);
 }
 
 static GskSlType *
@@ -1214,11 +1215,11 @@ gsk_sl_expression_constant_free (GskSlExpression *expression)
 
 static void
 gsk_sl_expression_constant_print (const GskSlExpression *expression,
-                                  GString               *string)
+                                  GskSlPrinter          *printer)
 {
   const GskSlExpressionConstant *constant = (const GskSlExpressionConstant *) expression;
 
-  gsk_sl_value_print (constant->value, string);
+  gsk_sl_value_print (constant->value, printer);
 }
 
 static GskSlType *
@@ -1451,6 +1452,7 @@ gsk_sl_expression_parse_primary (GskSlScope        *scope,
             GskSlFunctionMatcher matcher;
             GskSlFunction *constructor;
 
+            gsk_sl_preprocessor_consume (stream, NULL);
             constructor = gsk_sl_function_new_constructor (type);
             gsk_sl_function_matcher_init (&matcher, g_list_prepend (NULL, constructor));
             expr = gsk_sl_expression_parse_function_call (scope, stream, &matcher, constructor);
@@ -2363,9 +2365,9 @@ gsk_sl_expression_unref (GskSlExpression *expression)
 
 void
 gsk_sl_expression_print (const GskSlExpression *expression,
-                         GString               *string)
+                         GskSlPrinter          *printer)
 {
-  expression->class->print (expression, string);
+  expression->class->print (expression, printer);
 }
 
 GskSlType *
diff --git a/gsk/gskslexpressionprivate.h b/gsk/gskslexpressionprivate.h
index 02be57c..3c169e8 100644
--- a/gsk/gskslexpressionprivate.h
+++ b/gsk/gskslexpressionprivate.h
@@ -38,7 +38,7 @@ GskSlExpression *       gsk_sl_expression_ref                   (GskSlExpression
 void                    gsk_sl_expression_unref                 (GskSlExpression        *expression);
 
 void                    gsk_sl_expression_print                 (const GskSlExpression  *expression,
-                                                                 GString                *string);
+                                                                 GskSlPrinter           *printer);
 GskSlType *             gsk_sl_expression_get_return_type       (const GskSlExpression  *expression);
 GskSlValue *            gsk_sl_expression_get_constant          (const GskSlExpression  *expression);
 
diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c
index 779fe7f..890dd6f 100644
--- a/gsk/gskslfunction.c
+++ b/gsk/gskslfunction.c
@@ -20,15 +20,40 @@
 
 #include "gskslfunctionprivate.h"
 
+#include "gskslnativefunctionprivate.h"
 #include "gskslnodeprivate.h"
 #include "gskslpointertypeprivate.h"
 #include "gskslpreprocessorprivate.h"
+#include "gskslprinterprivate.h"
 #include "gskslscopeprivate.h"
 #include "gsksltokenizerprivate.h"
 #include "gsksltypeprivate.h"
 #include "gskslvariableprivate.h"
 #include "gskspvwriterprivate.h"
 
+typedef struct _GskSlFunctionClass GskSlFunctionClass;
+
+struct _GskSlFunction
+{
+  const GskSlFunctionClass *class;
+
+  int ref_count;
+};
+
+struct _GskSlFunctionClass {
+  void                  (* free)                                (GskSlFunction          *function);
+
+  GskSlType *           (* get_return_type)                     (const GskSlFunction    *function);
+  const char *          (* get_name)                            (const GskSlFunction    *function);
+  gsize                 (* get_n_arguments)                     (const GskSlFunction    *function);
+  GskSlType *           (* get_argument_type)                   (const GskSlFunction    *function,
+                                                                 gsize                   i);
+  void                  (* print)                               (const GskSlFunction    *function,
+                                                                 GskSlPrinter           *printer);
+  guint32               (* write_spv)                           (const GskSlFunction    *function,
+                                                                 GskSpvWriter           *writer);
+};
+
 static GskSlFunction *
 gsk_sl_function_alloc (const GskSlFunctionClass *klass,
                        gsize                     size)
@@ -44,7 +69,7 @@ gsk_sl_function_alloc (const GskSlFunctionClass *klass,
 }
 #define gsk_sl_function_new(_name, _klass) ((_name *) gsk_sl_function_alloc ((_klass), sizeof (_name)))
 
-/* BUILTIN CONSTRUCTOR */
+/* CONSTRUCTOR */
 
 typedef struct _GskSlFunctionBuiltinConstructor GskSlFunctionBuiltinConstructor;
 
@@ -95,7 +120,7 @@ gsk_sl_function_builtin_constructor_get_argument_type (const GskSlFunction *func
 
 static void
 gsk_sl_function_builtin_constructor_print (const GskSlFunction *function,
-                                           GString             *string)
+                                           GskSlPrinter        *printer)
 {
 }
 
@@ -171,7 +196,7 @@ gsk_sl_function_constructor_get_argument_type (const GskSlFunction *function,
 
 static void
 gsk_sl_function_constructor_print (const GskSlFunction *function,
-                                   GString             *string)
+                                   GskSlPrinter        *printer)
 {
 }
 
@@ -192,6 +217,79 @@ static const GskSlFunctionClass GSK_SL_FUNCTION_CONSTRUCTOR = {
   gsk_sl_function_constructor_write_spv,
 };
 
+/* NATIVE */
+
+typedef struct _GskSlFunctionNative GskSlFunctionNative;
+
+struct _GskSlFunctionNative {
+  GskSlFunction parent;
+
+  const GskSlNativeFunction *native;
+};
+
+static void
+gsk_sl_function_native_free (GskSlFunction *function)
+{
+  GskSlFunctionNative *native = (GskSlFunctionNative *) function;
+
+  g_slice_free (GskSlFunctionNative, native);
+}
+
+static GskSlType *
+gsk_sl_function_native_get_return_type (const GskSlFunction *function)
+{
+  const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
+
+  return gsk_sl_type_get_builtin (native->native->return_type);
+}
+
+static const char *
+gsk_sl_function_native_get_name (const GskSlFunction *function)
+{
+  const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
+
+  return native->native->name;
+}
+
+static gsize
+gsk_sl_function_native_get_n_arguments (const GskSlFunction *function)
+{
+  const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
+
+  return native->native->n_arguments;
+}
+
+static GskSlType *
+gsk_sl_function_native_get_argument_type (const GskSlFunction *function,
+                                          gsize                i)
+{
+  const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
+
+  return gsk_sl_type_get_builtin (native->native->argument_types[i]);
+}
+static void
+gsk_sl_function_native_print (const GskSlFunction *function,
+                              GskSlPrinter        *printer)
+{
+}
+
+static guint32
+gsk_sl_function_native_write_spv (const GskSlFunction *function,
+                                  GskSpvWriter        *writer)
+{
+  return 0;
+}
+
+static const GskSlFunctionClass GSK_SL_FUNCTION_NATIVE = {
+  gsk_sl_function_native_free,
+  gsk_sl_function_native_get_return_type,
+  gsk_sl_function_native_get_name,
+  gsk_sl_function_native_get_n_arguments,
+  gsk_sl_function_native_get_argument_type,
+  gsk_sl_function_native_print,
+  gsk_sl_function_native_write_spv
+};
+
 /* DECLARED */
 
 typedef struct _GskSlFunctionDeclared GskSlFunctionDeclared;
@@ -260,33 +358,38 @@ gsk_sl_function_declared_get_argument_type (const GskSlFunction *function,
 }
 static void
 gsk_sl_function_declared_print (const GskSlFunction *function,
-                                GString             *string)
+                                GskSlPrinter        *printer)
 {
   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");
+  gsk_sl_printer_append (printer, gsk_sl_type_get_name (declared->return_type));
+  gsk_sl_printer_newline (printer);
 
-  g_string_append (string, declared->name);
-  g_string_append (string, " (");
+  gsk_sl_printer_append (printer, declared->name);
+  gsk_sl_printer_append (printer, " (");
   for (i = 0; i < declared->n_arguments; i++)
     {
       if (i > 0)
-        g_string_append (string, ", ");
-      gsk_sl_variable_print (declared->arguments[i], string);
+        gsk_sl_printer_append (printer, ", ");
+      gsk_sl_variable_print (declared->arguments[i], printer);
     }
-  g_string_append (string, ")\n");
+  gsk_sl_printer_append (printer, ")");
+  gsk_sl_printer_newline (printer);
 
-  g_string_append (string, "{\n");
+  gsk_sl_printer_append (printer, "{");
+  gsk_sl_printer_push_indentation (printer);
   for (l = declared->statements; l; l = l->next)
     {
-      g_string_append (string, "  ");
-      gsk_sl_node_print (l->data, string);
-      g_string_append (string, ";\n");
+      gsk_sl_printer_newline (printer);
+      gsk_sl_node_print (l->data, printer);
+      gsk_sl_printer_append (printer, ";");
     }
-  g_string_append (string, "}\n");
+  gsk_sl_printer_pop_indentation (printer);
+  gsk_sl_printer_newline (printer);
+  gsk_sl_printer_append (printer, "}");
+  gsk_sl_printer_newline (printer);
 }
 
 static guint32
@@ -381,6 +484,18 @@ gsk_sl_function_new_constructor (GskSlType *type)
 }
 
 GskSlFunction *
+gsk_sl_function_new_native (const GskSlNativeFunction *native)
+{
+  GskSlFunctionNative *function;
+
+  function = gsk_sl_function_new (GskSlFunctionNative, &GSK_SL_FUNCTION_NATIVE);
+
+  function->native = native;
+
+  return &function->parent;
+}
+
+GskSlFunction *
 gsk_sl_function_new_parse (GskSlScope        *scope,
                            GskSlPreprocessor *preproc,
                            GskSlType         *return_type,
@@ -563,9 +678,9 @@ gsk_sl_function_get_argument_type (const GskSlFunction *function,
 
 void
 gsk_sl_function_print (const GskSlFunction *function,
-                       GString             *string)
+                       GskSlPrinter        *printer)
 {
-  function->class->print (function, string);
+  function->class->print (function, printer);
 }
 
 guint32
diff --git a/gsk/gskslfunctionprivate.h b/gsk/gskslfunctionprivate.h
index 92d11f7..1d5cbd3 100644
--- a/gsk/gskslfunctionprivate.h
+++ b/gsk/gskslfunctionprivate.h
@@ -25,30 +25,8 @@
 
 G_BEGIN_DECLS
 
-typedef struct _GskSlFunctionClass GskSlFunctionClass;
-
-struct _GskSlFunction
-{
-  const GskSlFunctionClass *class;
-
-  int ref_count;
-};
-
-struct _GskSlFunctionClass {
-  void                  (* free)                                (GskSlFunction  *function);
-
-  GskSlType *           (* get_return_type)                     (const GskSlFunction    *function);
-  const char *          (* get_name)                            (const GskSlFunction    *function);
-  gsize                 (* get_n_arguments)                     (const GskSlFunction    *function);
-  GskSlType *           (* get_argument_type)                   (const GskSlFunction    *function,
-                                                                 gsize                   i);
-  void                  (* print)                               (const GskSlFunction    *function,
-                                                                 GString                *string);
-  guint32               (* write_spv)                           (const GskSlFunction    *function,
-                                                                 GskSpvWriter           *writer);
-};
-
 GskSlFunction *         gsk_sl_function_new_constructor         (GskSlType              *type);
+GskSlFunction *         gsk_sl_function_new_native              (const GskSlNativeFunction *native);
 GskSlFunction *         gsk_sl_function_new_parse               (GskSlScope             *scope,
                                                                  GskSlPreprocessor      *stream,
                                                                  GskSlType              *return_type,
@@ -60,7 +38,7 @@ void                    gsk_sl_function_unref                   (GskSlFunction
 gboolean                gsk_sl_function_is_builtin_constructor  (const GskSlFunction    *function);
 
 void                    gsk_sl_function_print                   (const GskSlFunction    *function,
-                                                                 GString                *string);
+                                                                 GskSlPrinter           *printer);
 
 const char *            gsk_sl_function_get_name                (const GskSlFunction    *function);
 GskSlType *             gsk_sl_function_get_return_type         (const GskSlFunction    *function);
diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c
index b1fa4c4..73d129e 100644
--- a/gsk/gskslnode.c
+++ b/gsk/gskslnode.c
@@ -24,6 +24,7 @@
 #include "gskslfunctionprivate.h"
 #include "gskslpointertypeprivate.h"
 #include "gskslpreprocessorprivate.h"
+#include "gskslprinterprivate.h"
 #include "gskslscopeprivate.h"
 #include "gsksltokenizerprivate.h"
 #include "gsksltypeprivate.h"
@@ -68,8 +69,8 @@ gsk_sl_node_empty_free (GskSlNode *node)
 }
 
 static void
-gsk_sl_node_empty_print (GskSlNode *node,
-                         GString   *string)
+gsk_sl_node_empty_print (const GskSlNode *node,
+                         GskSlPrinter    *printer)
 {
 }
 
@@ -110,16 +111,16 @@ gsk_sl_node_declaration_free (GskSlNode *node)
 }
 
 static void
-gsk_sl_node_declaration_print (GskSlNode *node,
-                               GString   *string)
+gsk_sl_node_declaration_print (const GskSlNode *node,
+                               GskSlPrinter    *printer)
 {
   GskSlNodeDeclaration *declaration = (GskSlNodeDeclaration *) node;
 
-  gsk_sl_variable_print (declaration->variable, string);
+  gsk_sl_variable_print (declaration->variable, printer);
   if (declaration->initial)
     {
-      g_string_append (string, " = ");
-      gsk_sl_expression_print (declaration->initial, string);
+      gsk_sl_printer_append (printer, " = ");
+      gsk_sl_expression_print (declaration->initial, printer);
     }
 }
 
@@ -172,16 +173,16 @@ gsk_sl_node_return_free (GskSlNode *node)
 }
 
 static void
-gsk_sl_node_return_print (GskSlNode *node,
-                          GString   *string)
+gsk_sl_node_return_print (const GskSlNode *node,
+                          GskSlPrinter    *printer)
 {
   GskSlNodeReturn *return_node = (GskSlNodeReturn *) node;
 
-  g_string_append (string, "return");
+  gsk_sl_printer_append (printer, "return");
   if (return_node->value)
     {
-      g_string_append (string, " ");
-      gsk_sl_expression_print (return_node->value, string);
+      gsk_sl_printer_append (printer, " ");
+      gsk_sl_expression_print (return_node->value, printer);
     }
 }
 
@@ -221,12 +222,12 @@ gsk_sl_node_expression_free (GskSlNode *node)
 }
  
 static void
-gsk_sl_node_expression_print (GskSlNode *node,
-                              GString   *string)
+gsk_sl_node_expression_print (const GskSlNode *node,
+                              GskSlPrinter    *printer)
 {
   GskSlNodeExpression *expression_node = (GskSlNodeExpression *) node;
 
-  gsk_sl_expression_print (expression_node->expression, string);
+  gsk_sl_expression_print (expression_node->expression, printer);
 }
  
 static guint32
@@ -520,10 +521,10 @@ gsk_sl_node_unref (GskSlNode *node)
 }
 
 void
-gsk_sl_node_print (GskSlNode *node,
-                   GString   *string)
+gsk_sl_node_print (const GskSlNode *node,
+                   GskSlPrinter    *printer)
 {
-  node->class->print (node, string);
+  node->class->print (node, printer);
 }
 
 guint32
diff --git a/gsk/gskslnodeprivate.h b/gsk/gskslnodeprivate.h
index 5cb00c4..0150d29 100644
--- a/gsk/gskslnodeprivate.h
+++ b/gsk/gskslnodeprivate.h
@@ -35,8 +35,8 @@ struct _GskSlNode {
 struct _GskSlNodeClass {
   void                  (* free)                                (GskSlNode           *node);
 
-  void                  (* print)                               (GskSlNode           *node,
-                                                                 GString             *string);
+  void                  (* print)                               (const GskSlNode     *node,
+                                                                 GskSlPrinter        *printer);
   guint32               (* write_spv)                           (const GskSlNode     *node,
                                                                  GskSpvWriter        *writer);
 };
@@ -47,8 +47,8 @@ GskSlNode *             gsk_sl_node_parse_statement             (GskSlScope
 GskSlNode *             gsk_sl_node_ref                         (GskSlNode           *node);
 void                    gsk_sl_node_unref                       (GskSlNode           *node);
 
-void                    gsk_sl_node_print                       (GskSlNode           *node,
-                                                                 GString             *string);
+void                    gsk_sl_node_print                       (const GskSlNode     *node,
+                                                                 GskSlPrinter        *printer);
 
 guint32                 gsk_sl_node_write_spv                   (const GskSlNode     *node,
                                                                  GskSpvWriter        *writer);
diff --git a/gsk/gskslpointertype.c b/gsk/gskslpointertype.c
index 2df1379..5833ca0 100644
--- a/gsk/gskslpointertype.c
+++ b/gsk/gskslpointertype.c
@@ -22,6 +22,7 @@
 
 #include "gskslexpressionprivate.h"
 #include "gskslpreprocessorprivate.h"
+#include "gskslprinterprivate.h"
 #include "gsksltokenizerprivate.h"
 #include "gsksltypeprivate.h"
 #include "gskslvalueprivate.h"
@@ -372,16 +373,16 @@ gsk_sl_pointer_type_unref (GskSlPointerType *type)
 
 void
 gsk_sl_pointer_type_print (const GskSlPointerType *type,
-                           GString                *string)
+                           GskSlPrinter           *printer)
 {
   if (type->access == GSK_SL_DECORATION_ACCESS_READWRITE)
-    g_string_append (string, "inout ");
+    gsk_sl_printer_append (printer, "inout ");
   else if (type->access == GSK_SL_DECORATION_ACCESS_READ)
-    g_string_append (string, "in ");
+    gsk_sl_printer_append (printer, "in ");
   else if (type->access == GSK_SL_DECORATION_ACCESS_WRITE)
-    g_string_append (string, "out ");
+    gsk_sl_printer_append (printer, "out ");
 
-  g_string_append (string, gsk_sl_type_get_name (type->type));
+  gsk_sl_printer_append (printer, gsk_sl_type_get_name (type->type));
 }
 
 GskSlType *
diff --git a/gsk/gskslpointertypeprivate.h b/gsk/gskslpointertypeprivate.h
index 9e92dfd..1a891a2 100644
--- a/gsk/gskslpointertypeprivate.h
+++ b/gsk/gskslpointertypeprivate.h
@@ -70,7 +70,7 @@ GskSlPointerType *      gsk_sl_pointer_type_ref                         (GskSlPo
 void                    gsk_sl_pointer_type_unref                       (GskSlPointerType           *type);
 
 void                    gsk_sl_pointer_type_print                       (const GskSlPointerType     *type,
-                                                                         GString                    *string);
+                                                                         GskSlPrinter               
*printer);
 
 GskSlType *             gsk_sl_pointer_type_get_type                    (const GskSlPointerType     *type);
 
diff --git a/gsk/gskslprinter.c b/gsk/gskslprinter.c
new file mode 100644
index 0000000..901367d
--- /dev/null
+++ b/gsk/gskslprinter.c
@@ -0,0 +1,154 @@
+/* GTK - The GIMP Toolkit
+ *   
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gskslprinterprivate.h"
+
+struct _GskSlPrinter
+{
+  guint ref_count;
+
+  GString *string;
+
+  guint indentation;
+};
+
+GskSlPrinter *
+gsk_sl_printer_new (void)
+{
+  GskSlPrinter *printer;
+
+  printer = g_slice_new0 (GskSlPrinter);
+
+  printer->ref_count = 1;
+
+  printer->string = g_string_new (NULL);
+
+  return printer;
+}
+
+GskSlPrinter *
+gsk_sl_printer_ref (GskSlPrinter *printer)
+{
+  g_return_val_if_fail (printer != NULL, NULL);
+
+  printer->ref_count += 1;
+
+  return printer;
+}
+
+void
+gsk_sl_printer_unref (GskSlPrinter *printer)
+{
+  if (printer == NULL)
+    return;
+
+  printer->ref_count -= 1;
+  if (printer->ref_count > 0)
+    return;
+
+  if (printer->indentation > 0)
+    {
+      g_warning ("Missing call to gsk_sl_printer_pop_indentation().");
+    }
+
+  g_string_free (printer->string, TRUE);
+
+  g_slice_free (GskSlPrinter, printer);
+}
+
+char *
+gsk_sl_printer_write_to_string (GskSlPrinter *printer)
+{
+  return g_strdup (printer->string->str);
+}
+
+void
+gsk_sl_printer_push_indentation (GskSlPrinter *printer)
+{
+  printer->indentation++;
+}
+
+void
+gsk_sl_printer_pop_indentation (GskSlPrinter *printer)
+{
+  if (printer->indentation == 0)
+    {
+      g_warning ("Calling gsk_sl_printer_pop_indentation() without preceding call to 
gsk_sl_printer_push_indentation()");
+      return;
+    }
+
+  printer->indentation--;
+}
+
+
+void
+gsk_sl_printer_append (GskSlPrinter *printer,
+                       const char   *str)
+{
+  g_string_append (printer->string, str);
+}
+
+void
+gsk_sl_printer_append_c (GskSlPrinter *printer,
+                         char          c)
+{
+  g_string_append_c (printer->string, c);
+}
+
+void
+gsk_sl_printer_append_int (GskSlPrinter *printer,
+                           int           i)
+{
+  g_string_append_printf (printer->string, "%d", i);
+}
+
+void
+gsk_sl_printer_append_uint (GskSlPrinter *printer,
+                            guint         u)
+{
+  g_string_append_printf (printer->string, "%u", u);
+}
+
+void
+gsk_sl_printer_append_double (GskSlPrinter *printer,
+                              double        d,
+                              gboolean      with_dot)
+{
+  char buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+  g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, d);
+  g_string_append (printer->string, buf);
+  if (with_dot && strchr (buf, '.') == NULL)
+    g_string_append (printer->string, ".0");
+}
+
+void
+gsk_sl_printer_newline (GskSlPrinter *printer)
+{
+  guint i;
+
+  g_string_append_c (printer->string, '\n');
+
+  for (i = 0; i < printer->indentation; i++)
+    {
+      g_string_append (printer->string, "  ");
+    }
+}
+
diff --git a/gsk/gskslprinterprivate.h b/gsk/gskslprinterprivate.h
new file mode 100644
index 0000000..83be55d
--- /dev/null
+++ b/gsk/gskslprinterprivate.h
@@ -0,0 +1,53 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GSK_SL_PRINTER_PRIVATE_H__
+#define __GSK_SL_PRINTER_PRIVATE_H__
+
+#include <glib.h>
+
+#include "gsksltypesprivate.h"
+
+G_BEGIN_DECLS
+
+GskSlPrinter *          gsk_sl_printer_new                      (void);
+
+GskSlPrinter *          gsk_sl_printer_ref                      (GskSlPrinter          *printer);
+void                    gsk_sl_printer_unref                    (GskSlPrinter          *printer);
+
+char *                  gsk_sl_printer_write_to_string          (GskSlPrinter          *printer);
+
+void                    gsk_sl_printer_push_indentation         (GskSlPrinter          *printer);
+void                    gsk_sl_printer_pop_indentation          (GskSlPrinter          *printer);
+
+void                    gsk_sl_printer_append                   (GskSlPrinter          *printer,
+                                                                 const char            *str);
+void                    gsk_sl_printer_append_c                 (GskSlPrinter          *printer,
+                                                                 char                   c);
+void                    gsk_sl_printer_append_int               (GskSlPrinter          *printer,
+                                                                 int                    i);
+void                    gsk_sl_printer_append_uint              (GskSlPrinter          *printer,
+                                                                 guint                  u);
+void                    gsk_sl_printer_append_double            (GskSlPrinter          *printer,
+                                                                 double                 d,
+                                                                 gboolean               with_dot);
+void                    gsk_sl_printer_newline                  (GskSlPrinter          *printer);
+
+G_END_DECLS
+
+#endif /* __GSK_SL_PRINTER_PRIVATE_H__ */
diff --git a/gsk/gskslprogram.c b/gsk/gskslprogram.c
index d9a78c9..4c4f453 100644
--- a/gsk/gskslprogram.c
+++ b/gsk/gskslprogram.c
@@ -25,6 +25,7 @@
 #include "gskslnodeprivate.h"
 #include "gskslpointertypeprivate.h"
 #include "gskslpreprocessorprivate.h"
+#include "gskslprinterprivate.h"
 #include "gskslscopeprivate.h"
 #include "gsksltokenizerprivate.h"
 #include "gsksltypeprivate.h"
@@ -219,30 +220,41 @@ void
 gsk_sl_program_print (GskSlProgram *program,
                       GString      *string)
 {
+  GskSlPrinter *printer;
   GSList *l;
+  char *str;
 
   g_return_if_fail (GSK_IS_SL_PROGRAM (program));
   g_return_if_fail (string != NULL);
 
+  printer = gsk_sl_printer_new ();
+
   for (l = program->variables; l; l = l->next)
     {
       const GskSlValue *value;
-      gsk_sl_variable_print (l->data, string);
+      gsk_sl_variable_print (l->data, printer);
       value = gsk_sl_variable_get_initial_value (l->data);
       if (value)
         {
-          g_string_append (string, " = ");
-          gsk_sl_value_print (value, string);
+          gsk_sl_printer_append (printer, " = ");
+          gsk_sl_value_print (value, printer);
         }
-      g_string_append (string, ";\n");
+      gsk_sl_printer_append (printer, ";");
+      gsk_sl_printer_newline (printer);
     }
 
   for (l = program->functions; l; l = l->next)
     {
       if (l != program->functions || program->variables != NULL)
-        g_string_append (string, "\n");
-      gsk_sl_function_print (l->data, string);
+        gsk_sl_printer_newline (printer);
+      gsk_sl_function_print (l->data, printer);
     }
+
+  str = gsk_sl_printer_write_to_string (printer);
+  g_string_append (string, str);
+  g_free (str);
+
+  gsk_sl_printer_unref (printer);
 }
 
 static void
diff --git a/gsk/gskslscope.c b/gsk/gskslscope.c
index df1b630..1e64c96 100644
--- a/gsk/gskslscope.c
+++ b/gsk/gskslscope.c
@@ -21,6 +21,7 @@
 #include "gskslscopeprivate.h"
 
 #include "gskslfunctionprivate.h"
+#include "gskslnativefunctionprivate.h"
 #include "gsksltypeprivate.h"
 #include "gskslvariableprivate.h"
 
@@ -44,6 +45,19 @@ free_function_list (gpointer data)
   g_list_free_full (data, (GDestroyNotify) gsk_sl_function_unref);
 }
 
+static void
+gsk_sl_scope_add_native_functions (GskSlScope *scope)
+{
+  guint i;
+
+  for (i = 0; gsk_glsl_functions[i].name; i++)
+    {
+      GskSlFunction *function = gsk_sl_function_new_native (&gsk_glsl_functions[i]);
+      gsk_sl_scope_add_function (scope, function);
+      gsk_sl_function_unref (function);
+    }
+}
+
 GskSlScope *
 gsk_sl_scope_new (GskSlScope *parent,
                   GskSlType  *return_type)
@@ -61,6 +75,9 @@ gsk_sl_scope_new (GskSlScope *parent,
   scope->functions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) 
free_function_list);
   scope->types = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gsk_sl_type_unref);
 
+  if (!parent)
+    gsk_sl_scope_add_native_functions (scope);
+
   return scope;
 }
 
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index a21d1c0..30f743b 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -22,6 +22,7 @@
 
 #include "gskslfunctionprivate.h"
 #include "gskslpreprocessorprivate.h"
+#include "gskslprinterprivate.h"
 #include "gskslscopeprivate.h"
 #include "gsksltokenizerprivate.h"
 #include "gskslvalueprivate.h"
@@ -65,7 +66,7 @@ struct _GskSlTypeClass {
   guint32               (* write_spv)                           (const GskSlType     *type,
                                                                  GskSpvWriter        *writer);
   void                  (* print_value)                         (const GskSlType     *type,
-                                                                 GString             *string,
+                                                                 GskSlPrinter        *printer,
                                                                  gpointer             value);
   guint32               (* write_value_spv)                     (GskSlType           *type,
                                                                  GskSpvWriter        *writer,
@@ -73,7 +74,7 @@ struct _GskSlTypeClass {
 };
 
 static void
-print_void (GString *string,
+print_void (GskSlPrinter *printer,
             gpointer value)
 {
   g_assert_not_reached ();
@@ -86,16 +87,12 @@ write_void_spv (GskSpvWriter *writer, gpointer value)
 }
 
 static void
-print_float (GString *string,
-             gpointer value)
+print_float (GskSlPrinter *printer,
+             gpointer      value)
 {
-  char buf[G_ASCII_DTOSTR_BUF_SIZE];
   gfloat *f = value;
       
-  g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, *f);
-  g_string_append (string, buf);
-  if (strchr (buf, '.') == NULL)
-    g_string_append (string, ".0");
+  gsk_sl_printer_append_double (printer, *f, TRUE);
 }
 
 static guint32
@@ -116,17 +113,13 @@ write_float_spv (GskSpvWriter *writer, gpointer value)
 }
 
 static void
-print_double (GString *string,
-              gpointer value)
+print_double (GskSlPrinter *printer,
+              gpointer      value)
 {
-  char buf[G_ASCII_DTOSTR_BUF_SIZE];
   gdouble *d = value;
       
-  g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, *d);
-  g_string_append (string, buf);
-  if (strchr (buf, '.') == NULL)
-    g_string_append (string, ".0");
-  g_string_append (string, "lf");
+  gsk_sl_printer_append_double (printer, *d, TRUE);
+  gsk_sl_printer_append (printer, "lf");
 }
 
 static guint32
@@ -148,12 +141,12 @@ write_double_spv (GskSpvWriter *writer, gpointer value)
 }
 
 static void
-print_int (GString *string,
-           gpointer value)
+print_int (GskSlPrinter *printer,
+           gpointer      value)
 {
   gint32 *i = value;
 
-  g_string_append_printf (string, "%i", (gint) *i);
+  gsk_sl_printer_append_int (printer, *i);
 }
 
 static guint32
@@ -174,12 +167,13 @@ write_int_spv (GskSpvWriter *writer, gpointer value)
 }
 
 static void
-print_uint (GString *string,
-            gpointer value)
+print_uint (GskSlPrinter *printer,
+            gpointer      value)
 {
   guint32 *u = value;
   
-  g_string_append_printf (string, "%uu", (guint) *u);
+  gsk_sl_printer_append_uint (printer, *u);
+  gsk_sl_printer_append_c (printer, 'u');
 }
 
 static guint32
@@ -200,12 +194,12 @@ write_uint_spv (GskSpvWriter *writer, gpointer value)
 }
 
 static void
-print_bool (GString *string,
-            gpointer value)
+print_bool (GskSlPrinter *printer,
+            gpointer      value)
 {
   guint32 *u = value;
   
-  g_string_append_printf (string, *u ? "true" : "false");
+  gsk_sl_printer_append (printer, *u ? "true" : "false");
 }
 
 static guint32
@@ -305,7 +299,7 @@ bool_to_bool (gpointer target, gconstpointer source)
 struct {
   char *name;
   gsize size;
-  void (* print_value) (GString *string, gpointer value);
+  void (* print_value) (GskSlPrinter *printer, gpointer value);
   void (* convert_value[N_SCALAR_TYPES]) (gpointer target, gconstpointer source);
   guint32 (* write_value_spv) (GskSpvWriter *writer, gpointer value);
 } scalar_infos[] = {
@@ -491,12 +485,12 @@ gsk_sl_type_scalar_write_spv (const GskSlType *type,
 
 static void
 gsk_sl_type_scalar_print_value (const GskSlType *type,
-                                GString         *string,
+                                GskSlPrinter    *printer,
                                 gpointer         value)
 {
   GskSlTypeScalar *scalar = (GskSlTypeScalar *) type;
 
-  scalar_infos[scalar->scalar].print_value (string, value);
+  scalar_infos[scalar->scalar].print_value (printer, value);
 }
 
 static guint32
@@ -641,7 +635,7 @@ gsk_sl_type_vector_write_spv (const GskSlType *type,
 
 static void
 gsk_sl_type_vector_print_value (const GskSlType *type,
-                                GString         *string,
+                                GskSlPrinter    *printer,
                                 gpointer         value)
 {
   GskSlTypeVector *vector = (GskSlTypeVector *) type;
@@ -650,17 +644,17 @@ gsk_sl_type_vector_print_value (const GskSlType *type,
 
   data = value;
 
-  g_string_append (string, vector->name);
-  g_string_append (string, "(");
+  gsk_sl_printer_append (printer, vector->name);
+  gsk_sl_printer_append (printer, "(");
   for (i = 0; i < vector->length; i++)
     {
       if (i > 0)
-        g_string_append (string, ", ");
-      scalar_infos[vector->scalar].print_value (string, data);
+        gsk_sl_printer_append (printer, ", ");
+      scalar_infos[vector->scalar].print_value (printer, data);
       data += scalar_infos[vector->scalar].size;
     }
 
-  g_string_append (string, ")");
+  gsk_sl_printer_append (printer, ")");
 }
 
 static guint32
@@ -831,7 +825,7 @@ gsk_sl_type_matrix_write_spv (const GskSlType *type,
 
 static void
 gsk_sl_type_matrix_print_value (const GskSlType *type,
-                                GString         *string,
+                                GskSlPrinter    *printer,
                                 gpointer         value)
 {
   GskSlTypeMatrix *matrix = (GskSlTypeMatrix *) type;
@@ -840,17 +834,17 @@ gsk_sl_type_matrix_print_value (const GskSlType *type,
 
   data = value;
 
-  g_string_append (string, matrix->name);
-  g_string_append (string, "(");
+  gsk_sl_printer_append (printer, matrix->name);
+  gsk_sl_printer_append (printer, "(");
   for (i = 0; i < matrix->rows * matrix->columns; i++)
     {
       if (i > 0)
-        g_string_append (string, ", ");
-      scalar_infos[matrix->scalar].print_value (string, data);
+        gsk_sl_printer_append (printer, ", ");
+      scalar_infos[matrix->scalar].print_value (printer, data);
       data += scalar_infos[matrix->scalar].size;
     }
 
-  g_string_append (string, ")");
+  gsk_sl_printer_append (printer, ")");
 }
 
 static guint32
@@ -1024,25 +1018,25 @@ gsk_sl_type_struct_write_spv (const GskSlType *type,
 
 static void
 gsk_sl_type_struct_print_value (const GskSlType *type,
-                                GString         *string,
+                                GskSlPrinter    *printer,
                                 gpointer         value)
 {
   GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
   guint i;
 
-  g_string_append (string, struc->name);
-  g_string_append (string, "(");
+  gsk_sl_printer_append (printer, struc->name);
+  gsk_sl_printer_append (printer, "(");
 
   for (i = 0; i < struc->n_members; i++)
     {
       if (i > 0)
-        g_string_append (string, ", ");
+        gsk_sl_printer_append (printer, ", ");
       gsk_sl_type_print_value (struc->members[i].type,
-                               string,
+                               printer,
                                (guchar *) value + struc->members[i].offset);
     }
 
-  g_string_append (string, ")");
+  gsk_sl_printer_append (printer, ")");
 }
 
 static guint32
@@ -1200,6 +1194,95 @@ out:
 }
 
 GskSlType *
+gsk_sl_type_get_builtin (GskSlBuiltinType builtin)
+{
+  switch (builtin)
+    {
+    case GSK_SL_BUILTIN_VOID:
+      return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_VOID));
+    case GSK_SL_BUILTIN_FLOAT:
+      return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
+    case GSK_SL_BUILTIN_DOUBLE:
+      return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_DOUBLE));
+    case GSK_SL_BUILTIN_INT:
+      return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_INT));
+    case GSK_SL_BUILTIN_UINT:
+      return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_UINT));
+    case GSK_SL_BUILTIN_BOOL:
+      return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_BOOL));
+    case GSK_SL_BUILTIN_BVEC2:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_BOOL, 2));
+    case GSK_SL_BUILTIN_BVEC3:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_BOOL, 3));
+    case GSK_SL_BUILTIN_BVEC4:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_BOOL, 4));
+    case GSK_SL_BUILTIN_IVEC2:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_INT, 2));
+    case GSK_SL_BUILTIN_IVEC3:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_INT, 3));
+    case GSK_SL_BUILTIN_IVEC4:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_INT, 4));
+    case GSK_SL_BUILTIN_UVEC2:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_UINT, 2));
+    case GSK_SL_BUILTIN_UVEC3:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_UINT, 3));
+    case GSK_SL_BUILTIN_UVEC4:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_UINT, 4));
+    case GSK_SL_BUILTIN_VEC2:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_FLOAT, 2));
+    case GSK_SL_BUILTIN_VEC3:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_FLOAT, 3));
+    case GSK_SL_BUILTIN_VEC4:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_FLOAT, 4));
+    case GSK_SL_BUILTIN_DVEC2:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_DOUBLE, 2));
+    case GSK_SL_BUILTIN_DVEC3:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_DOUBLE, 3));
+    case GSK_SL_BUILTIN_DVEC4:
+      return gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_DOUBLE, 4));
+    case GSK_SL_BUILTIN_MAT2:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 2, 2));
+    case GSK_SL_BUILTIN_MAT2X3:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 2, 3));
+    case GSK_SL_BUILTIN_MAT2X4:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 2, 4));
+    case GSK_SL_BUILTIN_MAT3X2:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 3, 2));
+    case GSK_SL_BUILTIN_MAT3:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 3, 3));
+    case GSK_SL_BUILTIN_MAT3X4:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 3, 4));
+    case GSK_SL_BUILTIN_MAT4X2:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 4, 2));
+    case GSK_SL_BUILTIN_MAT4X3:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 4, 3));
+    case GSK_SL_BUILTIN_MAT4:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 4, 4));
+    case GSK_SL_BUILTIN_DMAT2:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 2, 2));
+    case GSK_SL_BUILTIN_DMAT2X3:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 2, 3));
+    case GSK_SL_BUILTIN_DMAT2X4:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 2, 4));
+    case GSK_SL_BUILTIN_DMAT3X2:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 3, 2));
+    case GSK_SL_BUILTIN_DMAT3:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 3, 3));
+    case GSK_SL_BUILTIN_DMAT3X4:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 3, 4));
+    case GSK_SL_BUILTIN_DMAT4X2:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 4, 2));
+    case GSK_SL_BUILTIN_DMAT4X3:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 4, 3));
+    case GSK_SL_BUILTIN_DMAT4:
+      return gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 4, 4));
+    default:
+      g_assert_not_reached ();
+      return gsk_sl_type_get_scalar (GSK_SL_VOID);
+    }
+}
+
+GskSlType *
 gsk_sl_type_new_parse (GskSlScope        *scope,
                        GskSlPreprocessor *preproc)
 {
@@ -1686,11 +1769,11 @@ gsk_sl_type_write_spv (const GskSlType *type,
 }
 
 void
-gsk_sl_type_print_value (const GskSlType     *type,
-                         GString             *string,
-                         gpointer             value)
+gsk_sl_type_print_value (const GskSlType *type,
+                         GskSlPrinter    *printer,
+                         gpointer         value)
 {
-  type->class->print_value (type, string, value);
+  type->class->print_value (type, printer, value);
 }
 
 guint32
diff --git a/gsk/gsksltypeprivate.h b/gsk/gsksltypeprivate.h
index ddefc06..d22902b 100644
--- a/gsk/gsksltypeprivate.h
+++ b/gsk/gsksltypeprivate.h
@@ -25,15 +25,6 @@
 
 G_BEGIN_DECLS
 
-typedef enum {
-  GSK_SL_VOID,
-  GSK_SL_FLOAT,
-  GSK_SL_DOUBLE,
-  GSK_SL_INT,
-  GSK_SL_UINT,
-  GSK_SL_BOOL
-} GskSlScalarType;
-
 typedef struct _GskSlTypeBuilder GskSlTypeBuilder;
 
 GskSlType *             gsk_sl_type_new_parse                   (GskSlScope          *scope,
@@ -44,6 +35,7 @@ GskSlType *             gsk_sl_type_get_vector                  (GskSlScalarType
 GskSlType *             gsk_sl_type_get_matrix                  (GskSlScalarType      scalar,
                                                                  guint                columns,
                                                                  guint                rows);
+GskSlType *             gsk_sl_type_get_builtin                 (GskSlBuiltinType     builtin);
 
 GskSlType *             gsk_sl_type_ref                         (GskSlType           *type);
 void                    gsk_sl_type_unref                       (GskSlType           *type);
@@ -84,7 +76,7 @@ guint32                 gsk_sl_type_write_spv                   (const GskSlType
                                                                  GskSpvWriter        *writer);
 
 void                    gsk_sl_type_print_value                 (const GskSlType     *type,
-                                                                 GString             *string,
+                                                                 GskSlPrinter        *printer,
                                                                  gpointer             value);
 guint32                 gsk_sl_type_write_value_spv             (GskSlType           *type,
                                                                  GskSpvWriter        *writer,
diff --git a/gsk/gsksltypesprivate.h b/gsk/gsksltypesprivate.h
index 3a7125f..dfdc577 100644
--- a/gsk/gsksltypesprivate.h
+++ b/gsk/gsksltypesprivate.h
@@ -24,9 +24,11 @@
 typedef struct _GskSlExpression         GskSlExpression;
 typedef struct _GskSlFunction           GskSlFunction;
 typedef struct _GskSlFunctionMatcher    GskSlFunctionMatcher;
+typedef struct _GskSlNativeFunction     GskSlNativeFunction;
 typedef struct _GskSlNode               GskSlNode;
 typedef struct _GskSlPreprocessor       GskSlPreprocessor;
 typedef struct _GskSlPointerType        GskSlPointerType;
+typedef struct _GskSlPrinter            GskSlPrinter;
 typedef struct _GskSlScope              GskSlScope;
 typedef struct _GskSlToken              GskSlToken;
 typedef struct _GskSlType               GskSlType;
@@ -35,4 +37,55 @@ typedef struct _GskSlVariable           GskSlVariable;
 
 typedef struct _GskSpvWriter            GskSpvWriter;
 
+typedef enum {
+  GSK_SL_VOID,
+  GSK_SL_FLOAT,
+  GSK_SL_DOUBLE,
+  GSK_SL_INT,
+  GSK_SL_UINT,
+  GSK_SL_BOOL
+} GskSlScalarType;
+
+typedef enum {
+  GSK_SL_BUILTIN_VOID,
+  GSK_SL_BUILTIN_FLOAT,
+  GSK_SL_BUILTIN_DOUBLE,
+  GSK_SL_BUILTIN_INT,
+  GSK_SL_BUILTIN_UINT,
+  GSK_SL_BUILTIN_BOOL,
+  GSK_SL_BUILTIN_BVEC2,
+  GSK_SL_BUILTIN_BVEC3,
+  GSK_SL_BUILTIN_BVEC4,
+  GSK_SL_BUILTIN_IVEC2,
+  GSK_SL_BUILTIN_IVEC3,
+  GSK_SL_BUILTIN_IVEC4,
+  GSK_SL_BUILTIN_UVEC2,
+  GSK_SL_BUILTIN_UVEC3,
+  GSK_SL_BUILTIN_UVEC4,
+  GSK_SL_BUILTIN_VEC2,
+  GSK_SL_BUILTIN_VEC3,
+  GSK_SL_BUILTIN_VEC4,
+  GSK_SL_BUILTIN_DVEC2,
+  GSK_SL_BUILTIN_DVEC3,
+  GSK_SL_BUILTIN_DVEC4,
+  GSK_SL_BUILTIN_MAT2,
+  GSK_SL_BUILTIN_MAT2X3,
+  GSK_SL_BUILTIN_MAT2X4,
+  GSK_SL_BUILTIN_MAT3X2,
+  GSK_SL_BUILTIN_MAT3,
+  GSK_SL_BUILTIN_MAT3X4,
+  GSK_SL_BUILTIN_MAT4X2,
+  GSK_SL_BUILTIN_MAT4X3,
+  GSK_SL_BUILTIN_MAT4,
+  GSK_SL_BUILTIN_DMAT2,
+  GSK_SL_BUILTIN_DMAT2X3,
+  GSK_SL_BUILTIN_DMAT2X4,
+  GSK_SL_BUILTIN_DMAT3X2,
+  GSK_SL_BUILTIN_DMAT3,
+  GSK_SL_BUILTIN_DMAT3X4,
+  GSK_SL_BUILTIN_DMAT4X2,
+  GSK_SL_BUILTIN_DMAT4X3,
+  GSK_SL_BUILTIN_DMAT4
+} GskSlBuiltinType;
+
 #endif /* __GSK_SL_TYPES_H__ */
diff --git a/gsk/gskslvalue.c b/gsk/gskslvalue.c
index af348f3..91ed63b 100644
--- a/gsk/gskslvalue.c
+++ b/gsk/gskslvalue.c
@@ -215,9 +215,9 @@ gsk_sl_value_componentwise (GskSlValue    *value,
 
 void
 gsk_sl_value_print (const GskSlValue *value,
-                    GString          *string)
+                    GskSlPrinter     *printer)
 {
-  gsk_sl_type_print_value (value->type, string, value->data);
+  gsk_sl_type_print_value (value->type, printer, value->data);
 }
 
 GskSlType *
diff --git a/gsk/gskslvalueprivate.h b/gsk/gskslvalueprivate.h
index 209cde3..51e4de5 100644
--- a/gsk/gskslvalueprivate.h
+++ b/gsk/gskslvalueprivate.h
@@ -39,7 +39,7 @@ void                    gsk_sl_value_componentwise              (GskSlValue
                                                                  void (* func)       (gpointer, gpointer),
                                                                  gpointer             user_data);
 void                    gsk_sl_value_print                      (const GskSlValue    *value,
-                                                                 GString             *string);
+                                                                 GskSlPrinter        *printer);
 
 GskSlType *             gsk_sl_value_get_type                   (const GskSlValue    *value);
 gpointer                gsk_sl_value_get_data                   (const GskSlValue    *value);
diff --git a/gsk/gskslvariable.c b/gsk/gskslvariable.c
index 51c39f1..5dc722f 100644
--- a/gsk/gskslvariable.c
+++ b/gsk/gskslvariable.c
@@ -21,6 +21,7 @@
 #include "gskslvariableprivate.h"
 
 #include "gskslpointertypeprivate.h"
+#include "gskslprinterprivate.h"
 #include "gsksltypeprivate.h"
 #include "gskslvalueprivate.h"
 #include "gskspvwriterprivate.h"
@@ -84,15 +85,15 @@ gsk_sl_variable_unref (GskSlVariable *variable)
 
 void
 gsk_sl_variable_print (const GskSlVariable *variable,
-                       GString             *string)
+                       GskSlPrinter        *printer)
 {
   if (variable->constant)
-    g_string_append (string, "const ");
-  gsk_sl_pointer_type_print (variable->type, string);
+    gsk_sl_printer_append (printer, "const ");
+  gsk_sl_pointer_type_print (variable->type, printer);
   if (variable->name)
     {
-      g_string_append (string, " ");
-      g_string_append (string, variable->name);
+      gsk_sl_printer_append (printer, " ");
+      gsk_sl_printer_append (printer, variable->name);
     }
 }
 
diff --git a/gsk/gskslvariableprivate.h b/gsk/gskslvariableprivate.h
index 92f8de0..cc24660 100644
--- a/gsk/gskslvariableprivate.h
+++ b/gsk/gskslvariableprivate.h
@@ -34,7 +34,7 @@ GskSlVariable *         gsk_sl_variable_ref                     (GskSlVariable
 void                    gsk_sl_variable_unref                   (GskSlVariable          *variable);
 
 void                    gsk_sl_variable_print                   (const GskSlVariable    *variable,
-                                                                 GString                *string);
+                                                                 GskSlPrinter           *printer);
 
 GskSlPointerType *      gsk_sl_variable_get_type                (const GskSlVariable    *variable);
 const char *            gsk_sl_variable_get_name                (const GskSlVariable    *variable);
diff --git a/gsk/meson.build b/gsk/meson.build
index 9e8ff58..7ae92c5 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -37,9 +37,11 @@ gsk_private_sources = files([
   'gsksldefine.c',
   'gskslexpression.c',
   'gskslfunction.c',
+  'gskslnativefunction.c',
   'gskslnode.c',
   'gskslpreprocessor.c',
   'gskslpointertype.c',
+  'gskslprinter.c',
   'gskslscope.c',
   'gsksltokenizer.c',
   'gsksltype.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]