]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ast.h
Fix memleak
[xonotic/gmqcc.git] / ast.h
diff --git a/ast.h b/ast.h
index f130fb45b2bea1ba3a5408e751474f4c13101170..3df25e859b5ace2093365818ee616cd2de2f257b 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -29,8 +29,8 @@
  * "main" ast node types for now.
  */
 
-typedef union ast_node_u ast_node;
-typedef union ast_expression_u ast_expression;
+typedef struct ast_node_common       ast_node;
+typedef struct ast_expression_common ast_expression;
 
 typedef struct ast_value_s       ast_value;
 typedef struct ast_function_s    ast_function;
@@ -51,6 +51,7 @@ typedef struct ast_breakcont_s   ast_breakcont;
 typedef struct ast_switch_s      ast_switch;
 typedef struct ast_label_s       ast_label;
 typedef struct ast_goto_s        ast_goto;
+typedef struct ast_argpipe_s     ast_argpipe;
 
 enum {
     TYPE_ast_node,        /*  0 */
@@ -73,17 +74,18 @@ enum {
     TYPE_ast_breakcont,   /* 17 */
     TYPE_ast_switch,      /* 18 */
     TYPE_ast_label,       /* 19 */
-    TYPE_ast_goto         /* 20 */
+    TYPE_ast_goto,        /* 20 */
+    TYPE_ast_argpipe      /* 21 */
 };
 
-#define ast_istype(x, t) ( ((ast_node_common*)x)->nodetype == (TYPE_##t) )
-#define ast_ctx(node) (((ast_node_common*)(node))->context)
-#define ast_side_effects(node) (((ast_node_common*)(node))->side_effects)
+#define ast_istype(x, t) ( ((ast_node*)x)->nodetype == (TYPE_##t) )
+#define ast_ctx(node) (((ast_node*)(node))->context)
+#define ast_side_effects(node) (((ast_node*)(node))->side_effects)
 
 /* Node interface with common components
  */
 typedef void ast_node_delete(ast_node*);
-typedef struct
+struct ast_node_common
 {
     lex_ctx          context;
     /* I don't feel comfortable using keywords like 'delete' as names... */
@@ -94,14 +96,14 @@ typedef struct
      */
     bool             keep;
     bool             side_effects;
-} ast_node_common;
-
-#define ast_delete(x) (*( ((ast_node*)(x))->node.destroy ))((ast_node*)(x))
-#define ast_unref(x) do                     \
-{                                           \
-    if (! (((ast_node*)(x))->node.keep) ) { \
-        ast_delete(x);                      \
-    }                                       \
+};
+
+#define ast_delete(x) (*( ((ast_node*)(x))->destroy ))((ast_node*)(x))
+#define ast_unref(x) do                \
+{                                      \
+    if (! (((ast_node*)(x))->keep) ) { \
+        ast_delete(x);                 \
+    }                                  \
 } while(0)
 
 /* Expression interface
@@ -123,9 +125,9 @@ typedef bool ast_expression_codegen(ast_expression*,
  * type `expression`, so the ast_ident's codegen would search for
  * variables through the environment (or functions, constants...).
  */
-typedef struct
+struct ast_expression_common
 {
-    ast_node_common         node;
+    ast_node                node;
     ast_expression_codegen *codegen;
     int                     vtype;
     ast_expression         *next;
@@ -144,7 +146,7 @@ typedef struct
      */
     ir_value               *outl;
     ir_value               *outr;
-} ast_expression_common;
+};
 #define AST_FLAG_VARIADIC     (1<<0)
 #define AST_FLAG_NORETURN     (1<<1)
 #define AST_FLAG_INLINE       (1<<2)
@@ -153,6 +155,9 @@ typedef struct
 #define AST_FLAG_INCLUDE_DEF  (1<<5)
 #define AST_FLAG_IS_VARARG    (1<<6)
 #define AST_FLAG_ALIAS        (1<<7)
+/* An array declared as []
+ * so that the size is taken from the initializer */
+#define AST_FLAG_ARRAY_INIT   (1<<8)
 #define AST_FLAG_TYPE_MASK (AST_FLAG_VARIADIC | AST_FLAG_NORETURN)
 
 /* Value
@@ -173,18 +178,13 @@ typedef union {
 } basic_value_t;
 struct ast_value_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     const char *name;
     const char *desc;
 
     const char *argcounter;
 
-    /*
-    int         vtype;
-    ast_value  *next;
-    */
-
     int  cvq;     /* const/var qualifier */
     bool isfield; /* this declares a field */
     bool isimm;   /* an immediate, not just const */
@@ -231,6 +231,7 @@ void ast_type_adopt_impl(ast_expression *self, const ast_expression *other);
 void ast_type_to_string(ast_expression *e, char *buf, size_t bufsize);
 
 typedef enum ast_binary_ref_s {
+    AST_REF_NONE  = 0,
     AST_REF_LEFT  = 1 << 1,
     AST_REF_RIGHT = 1 << 2,
     AST_REF_ALL   = (AST_REF_LEFT | AST_REF_RIGHT)
@@ -243,7 +244,7 @@ typedef enum ast_binary_ref_s {
  */
 struct ast_binary_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     int             op;
     ast_expression *left;
@@ -263,7 +264,7 @@ ast_binary* ast_binary_new(lex_ctx    ctx,
  */
 struct ast_binstore_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     int             opstore;
     int             opbin;
@@ -284,7 +285,7 @@ ast_binstore* ast_binstore_new(lex_ctx    ctx,
  */
 struct ast_unary_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     int             op;
     ast_expression *operand;
@@ -301,7 +302,7 @@ ast_unary* ast_unary_new(lex_ctx    ctx,
  */
 struct ast_return_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *operand;
 };
 ast_return* ast_return_new(lex_ctx    ctx,
@@ -322,7 +323,7 @@ ast_return* ast_return_new(lex_ctx    ctx,
  */
 struct ast_entfield_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     /* The entity can come from an expression of course. */
     ast_expression *entity;
     /* As can the field, it just must result in a value of TYPE_FIELD */
@@ -338,7 +339,7 @@ ast_entfield* ast_entfield_new_force(lex_ctx ctx, ast_expression *entity, ast_ex
  */
 struct ast_member_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *owner;
     unsigned int    field;
     const char     *name;
@@ -361,12 +362,23 @@ bool ast_member_set_name(ast_member*, const char *name);
  */
 struct ast_array_index_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *array;
     ast_expression *index;
 };
 ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_expression *index);
 
+/* Vararg pipe node:
+ *
+ * copy all varargs starting from a specific index
+ */
+struct ast_argpipe_s
+{
+    ast_expression        expression;
+    ast_expression *index;
+};
+ast_argpipe* ast_argpipe_new(lex_ctx ctx, ast_expression *index);
+
 /* Store
  *
  * Stores left<-right and returns left.
@@ -374,7 +386,7 @@ ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_exp
  */
 struct ast_store_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     int             op;
     ast_expression *dest;
     ast_expression *source;
@@ -395,7 +407,7 @@ ast_store* ast_store_new(lex_ctx ctx, int op,
  */
 struct ast_ifthen_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *cond;
     /* It's all just 'expressions', since an ast_block is one too. */
     ast_expression *on_true;
@@ -418,7 +430,7 @@ ast_ifthen* ast_ifthen_new(lex_ctx ctx, ast_expression *cond, ast_expression *on
  */
 struct ast_ternary_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *cond;
     /* It's all just 'expressions', since an ast_block is one too. */
     ast_expression *on_true;
@@ -451,7 +463,7 @@ continue:      // a 'continue' will jump here
  */
 struct ast_loop_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *initexpr;
     ast_expression *precond;
     ast_expression *postcond;
@@ -477,7 +489,7 @@ ast_loop* ast_loop_new(lex_ctx ctx,
  */
 struct ast_breakcont_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     bool         is_continue;
     unsigned int levels;
 };
@@ -499,7 +511,7 @@ typedef struct {
 } ast_switch_case;
 struct ast_switch_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     ast_expression  *operand;
     ast_switch_case *cases;
@@ -513,7 +525,7 @@ ast_switch* ast_switch_new(lex_ctx ctx, ast_expression *op);
  */
 struct ast_label_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     const char *name;
     ir_block   *irblock;
     ast_goto  **gotos;
@@ -529,7 +541,7 @@ ast_label* ast_label_new(lex_ctx ctx, const char *name, bool undefined);
  */
 struct ast_goto_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     const char *name;
     ast_label  *target;
     ir_block   *irblock_from;
@@ -550,21 +562,21 @@ void ast_goto_set_label(ast_goto*, ast_label*);
  */
 struct ast_call_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
     ast_expression *func;
     ast_expression* *params;
     ast_expression *va_count;
 };
 ast_call* ast_call_new(lex_ctx ctx,
                        ast_expression *funcexpr);
-bool ast_call_check_types(ast_call*);
+bool ast_call_check_types(ast_call*, ast_expression *this_func_va_type);
 
 /* Blocks
  *
  */
 struct ast_block_s
 {
-    ast_expression_common expression;
+    ast_expression        expression;
 
     ast_value*      *locals;
     ast_expression* *exprs;
@@ -589,7 +601,7 @@ bool GMQCC_WARN ast_block_add_expr(ast_block*, ast_expression*);
  */
 struct ast_function_s
 {
-    ast_node_common node;
+    ast_node        node;
 
     ast_value  *vtype;
     const char *name;
@@ -622,6 +634,7 @@ struct ast_function_s
     ast_value   *varargs;
     ast_value   *argc;
     ast_value   *fixedparams;
+    ast_value   *return_value;
 };
 ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype);
 /* This will NOT delete the underlying ast_value */
@@ -634,18 +647,4 @@ void ast_function_delete(ast_function*);
 bool ast_function_codegen(ast_function *self, ir_builder *builder);
 bool ast_generate_accessors(ast_value *asvalue, ir_builder *ir);
 
-/* Expression union
- */
-union ast_expression_u
-{
-    ast_expression_common expression;
-};
-
-/* Node union
- */
-union ast_node_u
-{
-    ast_node_common node;
-};
-
 #endif