Declaration of type-restricted varargs
authorWolfgang Bumiller <blub@speed.at>
Sat, 12 Jan 2013 10:03:17 +0000 (11:03 +0100)
committerWolfgang Bumiller <blub@speed.at>
Sat, 12 Jan 2013 10:03:17 +0000 (11:03 +0100)
ast.c
ast.h
parser.c

diff --git a/ast.c b/ast.c
index 995ba094efa04432e655135b489e7e61fb3b7148..ee41347f97b1fef73eb45c9387a4d1569f12c2ed 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -75,6 +75,7 @@ static void ast_expression_init(ast_expression *self,
     self->expression.params   = NULL;
     self->expression.count    = 0;
     self->expression.flags    = 0;
+    self->expression.varparam = NULL;
 }
 
 static void ast_expression_delete(ast_expression *self)
diff --git a/ast.h b/ast.h
index 37bbf0266aab0d332e79b6302f2fd9d397eb34a7..b93de575c19e03c4e9d8e4560e63a27e571d43bf 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -132,6 +132,10 @@ typedef struct
     size_t                  count;
     ast_value*             *params;
     uint32_t                flags;
+    /* void foo(string...) gets varparam set as a restriction
+     * for variadic parameters
+     */
+    ast_expression         *varparam;
     /* The codegen functions should store their output values
      * so we can call it multiple times without re-evaluating.
      * Store lvalue and rvalue seperately though. So that
@@ -146,6 +150,7 @@ typedef struct
 #define AST_FLAG_INITIALIZED  (1<<3)
 #define AST_FLAG_DEPRECATED   (1<<4)
 #define AST_FLAG_INCLUDE_DEF  (1<<5)
+#define AST_FLAG_VARARG_COUNT (1<<6)
 #define AST_FLAG_TYPE_MASK (AST_FLAG_VARIADIC | AST_FLAG_NORETURN)
 
 /* Value
index 2e16853217f2110ee8f317257d95779b6c2a3556..819c1e92030ff8617f05031c3529449ace103669 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -4291,6 +4291,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
     ast_value  *fval;
     bool        first = true;
     bool        variadic = false;
+    ast_value  *varparam = NULL;
 
     ctx = parser_ctx(parser);
 
@@ -4320,11 +4321,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
         if (parser->tok == TOKEN_DOTS) {
             /* '...' indicates a varargs function */
             variadic = true;
-            if (!parser_next(parser)) {
-                parseerror(parser, "expected parameter");
-                return NULL;
-            }
-            if (parser->tok != ')') {
+            if (!parser_next(parser) || parser->tok != ')') {
                 parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
                 goto on_error;
             }
@@ -4342,6 +4339,16 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
                 parseerror(parser, "type not supported as part of a parameter list: %s", tname);
                 goto on_error;
             }
+            /* type-restricted varargs */
+            if (parser->tok == TOKEN_DOTS) {
+                variadic = true;
+                varparam = vec_last(params);
+                vec_pop(params);
+                if (!parser_next(parser) || parser->tok != ')') {
+                    parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
+                    goto on_error;
+                }
+            }
         }
     }
 
@@ -4365,7 +4372,8 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
         fval->expression.flags |= AST_FLAG_VARIADIC;
     var = fval;
 
-    var->expression.params = params;
+    var->expression.params   = params;
+    var->expression.varparam = (ast_expression*)varparam;
     params = NULL;
 
     return var;