configure.ac: Add checks for Flex/Yacc/Bison and other furry animals, for the new...
[platform/upstream/gst-plugins-good.git] / gst / goom / goomsl_yacc.y
1 /**
2  * copyright 2004, Jean-Christophe Hoelt <jeko@ios-software.com>
3  *
4  * This program is released under the terms of the GNU Lesser General Public Licence.
5  */
6 %{
7     #include <stdio.h>
8     #include <stdlib.h>
9     #include <string.h>
10     #include "goomsl.h"
11     #include "goomsl_private.h"
12
13 #define STRUCT_ALIGNMENT 16
14 /* #define VERBOSE  */
15
16     int yylex(void);
17     void yyerror(char *);
18     extern GoomSL *currentGoomSL;
19
20     static NodeType *nodeNew(const char *str, int type, int line_number);
21     static NodeType *nodeClone(NodeType *node);
22     static void nodeFreeInternals(NodeType *node);
23     static void nodeFree(NodeType *node);
24
25     static void commit_node(NodeType *node, int releaseIfTemp);
26     static void precommit_node(NodeType *node);
27
28     static NodeType *new_constInt(const char *str, int line_number);
29     static NodeType *new_constFloat(const char *str, int line_number);
30     static NodeType *new_constPtr(const char *str, int line_number);
31     static NodeType *new_var(const char *str, int line_number);
32     static NodeType *new_nop(const char *str);
33     static NodeType *new_op(const char *str, int type, int nbOp);
34
35     static int  allocateLabel();
36     static int  allocateTemp();
37     static void releaseTemp(int n);
38     static void releaseAllTemps();
39
40     static int is_tmp_expr(NodeType *node) {
41         if (node->str) {
42             return (!strncmp(node->str,"_i_tmp_",7))
43               || (!strncmp(node->str,"_f_tmp_",7))
44               || (!strncmp(node->str,"_p_tmp",7));
45         }
46         return 0;
47     }
48     /* pre: is_tmp_expr(node); */
49     static int get_tmp_id(NodeType *node)  { return atoi((node->str)+5); }
50
51     static int is_commutative_expr(int itype)
52     { /* {{{ */
53         return (itype == INSTR_ADD)
54             || (itype == INSTR_MUL)
55             || (itype == INSTR_ISEQUAL);
56     } /* }}} */
57
58     static void GSL_PUT_LABEL(char *name, int line_number)
59     { /* {{{ */
60 #ifdef VERBOSE
61       printf("label %s\n", name);
62 #endif
63       currentGoomSL->instr = gsl_instr_init(currentGoomSL, "label", INSTR_LABEL, 1, line_number);
64       gsl_instr_add_param(currentGoomSL->instr, name, TYPE_LABEL);
65     } /* }}} */
66     static void GSL_PUT_JUMP(char *name, int line_number)
67     { /* {{{ */
68 #ifdef VERBOSE
69       printf("jump %s\n", name);
70 #endif
71       currentGoomSL->instr = gsl_instr_init(currentGoomSL, "jump", INSTR_JUMP, 1, line_number);
72       gsl_instr_add_param(currentGoomSL->instr, name, TYPE_LABEL);
73     } /* }}} */
74
75     static void GSL_PUT_JXXX(char *name, char *iname, int instr_id, int line_number)
76     { /* {{{ */
77 #ifdef VERBOSE
78       printf("%s %s\n", iname, name);
79 #endif
80       currentGoomSL->instr = gsl_instr_init(currentGoomSL, iname, instr_id, 1, line_number);
81       gsl_instr_add_param(currentGoomSL->instr, name, TYPE_LABEL);
82     } /* }}} */
83     static void GSL_PUT_JZERO(char *name,int line_number)
84     { /* {{{ */
85       GSL_PUT_JXXX(name,"jzero.i",INSTR_JZERO,line_number);
86     } /* }}} */
87     static void GSL_PUT_JNZERO(char *name, int line_number)
88     { /* {{{ */
89       GSL_PUT_JXXX(name,"jnzero.i",INSTR_JNZERO,line_number);
90     } /* }}} */
91
92     /* Structures Management */
93
94 #define ALIGN_ADDR(_addr,_align) {\
95    if (_align>1) {\
96        int _dec = (_addr%_align);\
97        if (_dec != 0) _addr += _align - _dec;\
98    }}
99
100     /* */
101     void gsl_prepare_struct(GSL_Struct *s, int s_align, int i_align, int f_align)
102     {
103       int i;
104       int consumed = 0;
105       int iblk=0, fblk=0;
106
107       s->iBlock[0].size = 0;
108       s->iBlock[0].data = 0;
109       s->fBlock[0].size = 0;
110       s->fBlock[0].data = 0;
111
112       /* Prepare sub-struct and calculate space needed for their storage */
113       for (i = 0; i < s->nbFields; ++i)
114       {
115         if (s->fields[i]->type < FIRST_RESERVED)
116         {
117           int j=0;
118           GSL_Struct *substruct = currentGoomSL->gsl_struct[s->fields[i]->type];
119           consumed += sizeof(int); /* stocke le prefix */
120           ALIGN_ADDR(consumed, s_align);
121           s->fields[i]->offsetInStruct = consumed;
122           gsl_prepare_struct(substruct, s_align, i_align, f_align);
123           for(j=0;substruct->iBlock[j].size>0;++j) {
124             s->iBlock[iblk].data = consumed + substruct->iBlock[j].data;
125             s->iBlock[iblk].size = substruct->iBlock[j].size;
126             iblk++;
127           }
128           for(j=0;substruct->fBlock[j].size>0;++j) {
129             s->fBlock[fblk].data = consumed + substruct->fBlock[j].data;
130             s->fBlock[fblk].size = substruct->fBlock[j].size;
131             fblk++;
132           }
133           consumed += substruct->size;
134         }
135       }
136
137       /* Then prepare integers */
138       ALIGN_ADDR(consumed, i_align);
139       for (i = 0; i < s->nbFields; ++i)
140       {
141         if (s->fields[i]->type == INSTR_INT)
142         {
143           if (s->iBlock[iblk].size == 0) {
144             s->iBlock[iblk].size = 1;
145             s->iBlock[iblk].data = consumed;
146           } else {
147             s->iBlock[iblk].size += 1;
148           }
149           s->fields[i]->offsetInStruct = consumed;
150           consumed += sizeof(int);
151         }
152       }
153
154       iblk++;
155       s->iBlock[iblk].size = 0;
156       s->iBlock[iblk].data = 0;
157
158       /* Then prepare floats */
159       ALIGN_ADDR(consumed, f_align);
160       for (i = 0; i < s->nbFields; ++i)
161       {
162         if (s->fields[i]->type == INSTR_FLOAT)
163         {
164           if (s->fBlock[fblk].size == 0) {
165             s->fBlock[fblk].size = 1;
166             s->fBlock[fblk].data = consumed;
167           } else {
168             s->fBlock[fblk].size += 1;
169           }
170           s->fields[i]->offsetInStruct = consumed;
171           consumed += sizeof(int);
172         }
173       }
174
175       fblk++;
176       s->fBlock[fblk].size = 0;
177       s->fBlock[fblk].data = 0;
178       
179       /* Finally prepare pointers */
180       ALIGN_ADDR(consumed, i_align);
181       for (i = 0; i < s->nbFields; ++i)
182       {
183         if (s->fields[i]->type == INSTR_PTR)
184         {
185           s->fields[i]->offsetInStruct = consumed;
186           consumed += sizeof(int);
187         }
188       }
189       s->size = consumed;
190     }
191
192     /* Returns the ID of a struct from its name */
193     int gsl_get_struct_id(const char *name) /* {{{ */
194     {
195       HashValue *ret = goom_hash_get(currentGoomSL->structIDS, name);
196       if (ret != NULL) return ret->i;
197       return -1;
198     } /* }}} */
199
200     /* Adds the definition of a struct */
201     void gsl_add_struct(const char *name, GSL_Struct *gsl_struct) /* {{{ */
202     {
203       /* Prepare the struct: ie calculate internal storage format */
204       gsl_prepare_struct(gsl_struct, STRUCT_ALIGNMENT, STRUCT_ALIGNMENT, STRUCT_ALIGNMENT);
205       
206       /* If the struct does not already exists */
207       if (gsl_get_struct_id(name) < 0)
208       {
209         /* adds it */
210         int id = currentGoomSL->nbStructID++;
211         goom_hash_put_int(currentGoomSL->structIDS, name, id);
212         if (currentGoomSL->gsl_struct_size <= id) {
213           currentGoomSL->gsl_struct_size *= 2;
214           currentGoomSL->gsl_struct = (GSL_Struct**)realloc(currentGoomSL->gsl_struct,
215                                                             sizeof(GSL_Struct*) * currentGoomSL->gsl_struct_size);
216         }
217         currentGoomSL->gsl_struct[id] = gsl_struct;
218       }
219     } /* }}} */
220     
221     /* Creates a field for a struct */
222     GSL_StructField *gsl_new_struct_field(const char *name, int type)
223     {
224       GSL_StructField *field = (GSL_StructField*)malloc(sizeof(GSL_StructField));
225       strcpy(field->name, name);
226       field->type = type;
227       return field;
228     }
229     
230     /* Create as field for a struct which will be a struct itself */
231     GSL_StructField *gsl_new_struct_field_struct(const char *name, const char *type)
232     {
233       GSL_StructField *field = gsl_new_struct_field(name, gsl_get_struct_id(type));
234       if (field->type < 0) {
235         fprintf(stderr, "ERROR: Line %d, Unknown structure: '%s'\n",
236                 currentGoomSL->num_lines, type);
237         exit(1);
238       }
239       return field;
240     }
241
242     /* Creates a Struct */
243     GSL_Struct *gsl_new_struct(GSL_StructField *field)
244     {
245       GSL_Struct *s = (GSL_Struct*)malloc(sizeof(GSL_Struct));
246       s->nbFields = 1;
247       s->fields[0] = field;
248       return s;
249     }
250
251     /* Adds a field to a struct */
252     void gsl_add_struct_field(GSL_Struct *s, GSL_StructField *field)
253     {
254       s->fields[s->nbFields++] = field;
255     }
256
257     int gsl_type_of_var(GoomHash *ns, const char *name)
258     {
259         char type_of[256];
260         HashValue *hv;
261         sprintf(type_of, "__type_of_%s", name);
262         hv = goom_hash_get(ns, type_of);
263         if (hv != NULL)
264           return hv->i;
265         fprintf(stderr, "ERROR: Unknown variable type: '%s'\n", name);
266         return -1;
267     }
268
269     static void gsl_declare_var(GoomHash *ns, const char *name, int type, void *space)
270     {
271         char type_of[256];
272         if (name[0] == '@') { ns = currentGoomSL->vars; }
273
274         if (space == NULL) {
275           switch (type) {
276             case INSTR_INT:
277             case INSTR_FLOAT:
278             case INSTR_PTR:
279               space = goom_heap_malloc_with_alignment(currentGoomSL->data_heap,
280                   sizeof(int), sizeof(int));
281             break;
282             case -1:
283               fprintf(stderr, "What the fuck!\n");
284               exit(1);
285             default: /* On a un struct_id */
286               space = goom_heap_malloc_with_alignment_prefixed(currentGoomSL->data_heap,
287                   currentGoomSL->gsl_struct[type]->size, STRUCT_ALIGNMENT, sizeof(int));
288           }
289         }
290         goom_hash_put_ptr(ns, name, (void*)space);
291         sprintf(type_of, "__type_of_%s", name);
292         goom_hash_put_int(ns, type_of, type);
293
294         /* Ensuite le hack: on ajoute les champs en tant que variables. */
295         if (type < FIRST_RESERVED)
296         {
297           int i;
298           GSL_Struct *gsl_struct = currentGoomSL->gsl_struct[type];
299           ((int*)space)[-1] = type; /* stockage du type dans le prefixe de structure */
300           for (i = 0; i < gsl_struct->nbFields; ++i)
301           {
302             char full_name[256];
303             char *cspace = (char*)space + gsl_struct->fields[i]->offsetInStruct;
304             sprintf(full_name, "%s.%s", name, gsl_struct->fields[i]->name);
305             gsl_declare_var(ns, full_name, gsl_struct->fields[i]->type, cspace);
306           }
307        }
308     }
309     
310     /* Declare a variable which will be a struct */
311     static void gsl_struct_decl(GoomHash *namespace, const char *struct_name, const char *name)
312     {
313         int  struct_id = gsl_get_struct_id(struct_name);
314         gsl_declare_var(namespace, name, struct_id, NULL);
315     }
316
317     static void gsl_float_decl_global(const char *name)
318     {
319         gsl_declare_var(currentGoomSL->vars, name, INSTR_FLOAT, NULL);
320     }
321     static void gsl_int_decl_global(const char *name)
322     {
323         gsl_declare_var(currentGoomSL->vars, name, INSTR_INT, NULL);
324     }
325     static void gsl_ptr_decl_global(const char *name)
326     {
327         gsl_declare_var(currentGoomSL->vars, name, INSTR_PTR, NULL);
328     }
329     static void gsl_struct_decl_global_from_id(const char *name, int id)
330     {
331         gsl_declare_var(currentGoomSL->vars, name, id, NULL);
332     }
333     
334     /* FLOAT */
335     static void gsl_float_decl_local(const char *name)
336     {
337         gsl_declare_var(currentGoomSL->namespaces[currentGoomSL->currentNS], name, INSTR_FLOAT, NULL);
338     }
339     /* INT */
340     static void gsl_int_decl_local(const char *name)
341     {
342         gsl_declare_var(currentGoomSL->namespaces[currentGoomSL->currentNS], name, INSTR_INT, NULL);
343     }
344     /* PTR */
345     static void gsl_ptr_decl_local(const char *name)
346     {
347         gsl_declare_var(currentGoomSL->namespaces[currentGoomSL->currentNS], name, INSTR_PTR, NULL);
348     }
349     /* STRUCT */
350     static void gsl_struct_decl_local(const char *struct_name, const char *name)
351     {
352         gsl_struct_decl(currentGoomSL->namespaces[currentGoomSL->currentNS],struct_name,name);
353     }
354
355
356     static void commit_test2(NodeType *set,const char *type, int instr);
357     static NodeType *new_call(const char *name, NodeType *affect_list);
358
359     /* SETTER */
360     static NodeType *new_set(NodeType *lvalue, NodeType *expression)
361     { /* {{{ */
362         NodeType *set = new_op("set", OPR_SET, 2);
363         set->unode.opr.op[0] = lvalue;
364         set->unode.opr.op[1] = expression;
365         return set;
366     } /* }}} */
367     static void commit_set(NodeType *set)
368     { /* {{{ */
369       commit_test2(set,"set",INSTR_SET);
370     } /* }}} */
371
372     /* PLUS_EQ */
373     static NodeType *new_plus_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
374     {
375         NodeType *set = new_op("plus_eq", OPR_PLUS_EQ, 2);
376         set->unode.opr.op[0] = lvalue;
377         set->unode.opr.op[1] = expression;
378         return set;
379     }
380     static void commit_plus_eq(NodeType *set)
381     {
382         precommit_node(set->unode.opr.op[1]);
383 #ifdef VERBOSE
384         printf("add %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
385 #endif
386         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "add", INSTR_ADD, 2, set->line_number);
387         commit_node(set->unode.opr.op[0],0);
388         commit_node(set->unode.opr.op[1],1);
389     } /* }}} */
390
391     /* SUB_EQ */
392     static NodeType *new_sub_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
393     {
394         NodeType *set = new_op("sub_eq", OPR_SUB_EQ, 2);
395         set->unode.opr.op[0] = lvalue;
396         set->unode.opr.op[1] = expression;
397         return set;
398     }
399     static void commit_sub_eq(NodeType *set)
400     {
401         precommit_node(set->unode.opr.op[1]);
402 #ifdef VERBOSE
403         printf("sub %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
404 #endif
405         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "sub", INSTR_SUB, 2, set->line_number);
406         commit_node(set->unode.opr.op[0],0);
407         commit_node(set->unode.opr.op[1],1);
408     } /* }}} */
409
410     /* MUL_EQ */
411     static NodeType *new_mul_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
412     {
413         NodeType *set = new_op("mul_eq", OPR_MUL_EQ, 2);
414         set->unode.opr.op[0] = lvalue;
415         set->unode.opr.op[1] = expression;
416         return set;
417     }
418     static void commit_mul_eq(NodeType *set)
419     {
420         precommit_node(set->unode.opr.op[1]);
421 #ifdef VERBOSE
422         printf("mul %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
423 #endif
424         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "mul", INSTR_MUL, 2, set->line_number);
425         commit_node(set->unode.opr.op[0],0);
426         commit_node(set->unode.opr.op[1],1);
427     } /* }}} */
428
429     /* DIV_EQ */
430     static NodeType *new_div_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
431     {
432         NodeType *set = new_op("div_eq", OPR_DIV_EQ, 2);
433         set->unode.opr.op[0] = lvalue;
434         set->unode.opr.op[1] = expression;
435         return set;
436     }
437     static void commit_div_eq(NodeType *set)
438     {
439         precommit_node(set->unode.opr.op[1]);
440 #ifdef VERBOSE
441         printf("div %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
442 #endif
443         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "div", INSTR_DIV, 2, set->line_number);
444         commit_node(set->unode.opr.op[0],0);
445         commit_node(set->unode.opr.op[1],1);
446     } /* }}} */
447
448     /* commodity method for add, mult, ... */
449
450     static void precommit_expr(NodeType *expr, const char *type, int instr_id)
451     { /* {{{ */
452         NodeType *tmp, *tmpcpy;
453         int toAdd;
454
455         /* compute "left" and "right" */
456         switch (expr->unode.opr.nbOp) {
457         case 2:
458           precommit_node(expr->unode.opr.op[1]);
459         case 1:
460           precommit_node(expr->unode.opr.op[0]);
461         }
462
463         if (is_tmp_expr(expr->unode.opr.op[0])) {
464             tmp = expr->unode.opr.op[0];
465             toAdd = 1;
466         }
467         else if (is_commutative_expr(instr_id) && (expr->unode.opr.nbOp==2) && is_tmp_expr(expr->unode.opr.op[1])) {
468             tmp = expr->unode.opr.op[1];
469             toAdd = 0;
470         }
471         else {
472             char stmp[256];
473             /* declare a temporary variable to store the result */
474             if (expr->unode.opr.op[0]->type == CONST_INT_NODE) {
475                 sprintf(stmp,"_i_tmp_%i",allocateTemp());
476                 gsl_int_decl_global(stmp);
477             }
478             else if (expr->unode.opr.op[0]->type == CONST_FLOAT_NODE) {
479                 sprintf(stmp,"_f_tmp%i",allocateTemp());
480                 gsl_float_decl_global(stmp);
481             }
482             else if (expr->unode.opr.op[0]->type == CONST_PTR_NODE) {
483                 sprintf(stmp,"_p_tmp%i",allocateTemp());
484                 gsl_ptr_decl_global(stmp);
485             }
486             else {
487                 int type = gsl_type_of_var(expr->unode.opr.op[0]->vnamespace, expr->unode.opr.op[0]->str);
488                 if (type == INSTR_FLOAT) {
489                     sprintf(stmp,"_f_tmp_%i",allocateTemp());
490                     gsl_float_decl_global(stmp);
491                 }
492                 else if (type == INSTR_PTR) {
493                     sprintf(stmp,"_p_tmp_%i",allocateTemp());
494                     gsl_ptr_decl_global(stmp);
495                 }
496                 else if (type == INSTR_INT) {
497                     sprintf(stmp,"_i_tmp_%i",allocateTemp());
498                     gsl_int_decl_global(stmp);
499                 }
500                 else if (type == -1) {
501                     fprintf(stderr, "ERROR: Line %d, Could not find variable '%s'\n",
502                             expr->line_number, expr->unode.opr.op[0]->str);
503                     exit(1);
504                 }
505                 else { /* type is a struct_id */
506                     sprintf(stmp,"_s_tmp_%i",allocateTemp());
507                     gsl_struct_decl_global_from_id(stmp,type);
508                 }
509             }
510             tmp = new_var(stmp,expr->line_number);
511
512             /* set the tmp to the value of "op1" */
513             tmpcpy = nodeClone(tmp);
514             commit_node(new_set(tmp,expr->unode.opr.op[0]),0);
515             toAdd = 1;
516
517             tmp = tmpcpy;
518         }
519
520         /* add op2 to tmp */
521 #ifdef VERBOSE
522         if (expr->unode.opr.nbOp == 2)
523           printf("%s %s %s\n", type, tmp->str, expr->unode.opr.op[toAdd]->str);
524         else
525           printf("%s %s\n", type, tmp->str);
526 #endif
527         currentGoomSL->instr = gsl_instr_init(currentGoomSL, type, instr_id, expr->unode.opr.nbOp, expr->line_number);
528         tmpcpy = nodeClone(tmp);
529         commit_node(tmp,0);
530         if (expr->unode.opr.nbOp == 2) {
531           commit_node(expr->unode.opr.op[toAdd],1);
532         }
533     
534         /* redefine the ADD node now as the computed variable */
535         nodeFreeInternals(expr);
536         *expr = *tmpcpy;
537         free(tmpcpy);
538     } /* }}} */
539
540     static NodeType *new_expr1(const char *name, int id, NodeType *expr1)
541     { /* {{{ */
542         NodeType *add = new_op(name, id, 1);
543         add->unode.opr.op[0] = expr1;
544         return add;
545     } /* }}} */
546
547     static NodeType *new_expr2(const char *name, int id, NodeType *expr1, NodeType *expr2)
548     { /* {{{ */
549         NodeType *add = new_op(name, id, 2);
550         add->unode.opr.op[0] = expr1;
551         add->unode.opr.op[1] = expr2;
552         return add;
553     } /* }}} */
554
555     /* ADD */
556     static NodeType *new_add(NodeType *expr1, NodeType *expr2) { /* {{{ */
557         return new_expr2("add", OPR_ADD, expr1, expr2);
558     }
559     static void precommit_add(NodeType *add) {
560         precommit_expr(add,"add",INSTR_ADD);
561     } /* }}} */
562
563     /* SUB */
564     static NodeType *new_sub(NodeType *expr1, NodeType *expr2) { /* {{{ */
565         return new_expr2("sub", OPR_SUB, expr1, expr2);
566     }
567     static void precommit_sub(NodeType *sub) {
568         precommit_expr(sub,"sub",INSTR_SUB);
569     } /* }}} */
570
571     /* NEG */
572     static NodeType *new_neg(NodeType *expr) { /* {{{ */
573         NodeType *zeroConst = NULL;
574         if (expr->type == CONST_INT_NODE)
575           zeroConst = new_constInt("0", currentGoomSL->num_lines);
576         else if (expr->type == CONST_FLOAT_NODE)
577           zeroConst = new_constFloat("0.0", currentGoomSL->num_lines);
578         else if (expr->type == CONST_PTR_NODE) {
579           fprintf(stderr, "ERROR: Line %d, Could not negate const pointer.\n",
580             currentGoomSL->num_lines);
581           exit(1);
582         }
583         else {
584             int type = gsl_type_of_var(expr->vnamespace, expr->str);
585             if (type == INSTR_FLOAT)
586               zeroConst = new_constFloat("0.0", currentGoomSL->num_lines);
587             else if (type == INSTR_PTR) {
588               fprintf(stderr, "ERROR: Line %d, Could not negate pointer.\n",
589                 currentGoomSL->num_lines);
590               exit(1);
591             }
592             else if (type == INSTR_INT)
593               zeroConst = new_constInt("0", currentGoomSL->num_lines);
594             else if (type == -1) {
595                 fprintf(stderr, "ERROR: Line %d, Could not find variable '%s'\n",
596                         expr->line_number, expr->unode.opr.op[0]->str);
597                 exit(1);
598             }
599             else { /* type is a struct_id */
600                 fprintf(stderr, "ERROR: Line %d, Could not negate struct '%s'\n",
601                         expr->line_number, expr->str);
602                 exit(1);
603             }
604         }
605         return new_expr2("sub", OPR_SUB, zeroConst, expr);
606     }
607     /* }}} */
608
609     /* MUL */
610     static NodeType *new_mul(NodeType *expr1, NodeType *expr2) { /* {{{ */
611         return new_expr2("mul", OPR_MUL, expr1, expr2);
612     }
613     static void precommit_mul(NodeType *mul) {
614         precommit_expr(mul,"mul",INSTR_MUL);
615     } /* }}} */
616     
617     /* DIV */
618     static NodeType *new_div(NodeType *expr1, NodeType *expr2) { /* {{{ */
619         return new_expr2("div", OPR_DIV, expr1, expr2);
620     }
621     static void precommit_div(NodeType *mul) {
622         precommit_expr(mul,"div",INSTR_DIV);
623     } /* }}} */
624
625     /* CALL EXPRESSION */
626     static NodeType *new_call_expr(const char *name, NodeType *affect_list) { /* {{{ */
627         NodeType *call = new_call(name,affect_list);
628         NodeType *node = new_expr1(name, OPR_CALL_EXPR, call);
629         node->vnamespace = gsl_find_namespace(name);
630         if (node->vnamespace == NULL)
631           fprintf(stderr, "ERROR: Line %d, No return type for: '%s'\n", currentGoomSL->num_lines, name);
632         return node;
633     }
634     static void precommit_call_expr(NodeType *call) {
635         char stmp[256];
636         NodeType *tmp,*tmpcpy;
637         int type = gsl_type_of_var(call->vnamespace, call->str);
638         if (type == INSTR_FLOAT) {
639           sprintf(stmp,"_f_tmp_%i",allocateTemp());
640           gsl_float_decl_global(stmp);
641         }
642         else if (type == INSTR_PTR) {
643           sprintf(stmp,"_p_tmp_%i",allocateTemp());
644           gsl_ptr_decl_global(stmp);
645         }
646         else if (type == INSTR_INT) {
647           sprintf(stmp,"_i_tmp_%i",allocateTemp());
648           gsl_int_decl_global(stmp);
649         }
650         else if (type == -1) {
651           fprintf(stderr, "ERROR: Line %d, Could not find variable '%s'\n",
652                   call->line_number, call->str);
653           exit(1);
654         }
655         else { /* type is a struct_id */
656           sprintf(stmp,"_s_tmp_%i",allocateTemp());
657           gsl_struct_decl_global_from_id(stmp,type);
658         }
659         tmp = new_var(stmp,call->line_number);
660         commit_node(call->unode.opr.op[0],0);
661         tmpcpy = nodeClone(tmp);
662         commit_node(new_set(tmp,new_var(call->str,call->line_number)),0);
663         
664         nodeFreeInternals(call);
665         *call = *tmpcpy;
666         free(tmpcpy);
667     } /* }}} */
668
669     static void commit_test2(NodeType *set,const char *type, int instr)
670     { /* {{{ */
671         NodeType *tmp;
672         char stmp[256];
673         precommit_node(set->unode.opr.op[0]);
674         precommit_node(set->unode.opr.op[1]);
675         tmp = set->unode.opr.op[0];
676         
677         stmp[0] = 0;
678         if (set->unode.opr.op[0]->type == CONST_INT_NODE) {
679             sprintf(stmp,"_i_tmp_%i",allocateTemp());
680             gsl_int_decl_global(stmp);
681         }
682         else if (set->unode.opr.op[0]->type == CONST_FLOAT_NODE) {
683             sprintf(stmp,"_f_tmp%i",allocateTemp());
684             gsl_float_decl_global(stmp);
685         }
686         else if (set->unode.opr.op[0]->type == CONST_PTR_NODE) {
687             sprintf(stmp,"_p_tmp%i",allocateTemp());
688             gsl_ptr_decl_global(stmp);
689         }
690         if (stmp[0]) {
691             NodeType *tmpcpy;
692             tmp = new_var(stmp, set->line_number);
693             tmpcpy = nodeClone(tmp);
694             commit_node(new_set(tmp,set->unode.opr.op[0]),0);
695             tmp = tmpcpy;
696         }
697
698 #ifdef VERBOSE
699         printf("%s %s %s\n", type, tmp->str, set->unode.opr.op[1]->str);
700 #endif
701         currentGoomSL->instr = gsl_instr_init(currentGoomSL, type, instr, 2, set->line_number);
702         commit_node(tmp,instr!=INSTR_SET);
703         commit_node(set->unode.opr.op[1],1);
704     } /* }}} */
705     
706     /* NOT */
707     static NodeType *new_not(NodeType *expr1) { /* {{{ */
708         return new_expr1("not", OPR_NOT, expr1);
709     }
710     static void commit_not(NodeType *set)
711     {
712         commit_node(set->unode.opr.op[0],0);
713 #ifdef VERBOSE
714         printf("not\n");
715 #endif
716         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "not", INSTR_NOT, 1, set->line_number);
717         gsl_instr_add_param(currentGoomSL->instr, "|dummy|", TYPE_LABEL);
718     } /* }}} */
719     
720     /* EQU */
721     static NodeType *new_equ(NodeType *expr1, NodeType *expr2) { /* {{{ */
722         return new_expr2("isequal", OPR_EQU, expr1, expr2);
723     }
724     static void commit_equ(NodeType *mul) {
725         commit_test2(mul,"isequal",INSTR_ISEQUAL);
726     } /* }}} */
727     
728     /* INF */
729     static NodeType *new_low(NodeType *expr1, NodeType *expr2) { /* {{{ */
730         return new_expr2("islower", OPR_LOW, expr1, expr2);
731     }
732     static void commit_low(NodeType *mul) {
733         commit_test2(mul,"islower",INSTR_ISLOWER);
734     } /* }}} */
735
736     /* WHILE */
737     static NodeType *new_while(NodeType *expression, NodeType *instr) { /* {{{ */
738         NodeType *node = new_op("while", OPR_WHILE, 2);
739         node->unode.opr.op[0] = expression;
740         node->unode.opr.op[1] = instr;
741         return node;
742     }
743
744     static void commit_while(NodeType *node)
745     {
746         int lbl = allocateLabel();
747         char start_while[1024], test_while[1024];
748         sprintf(start_while, "|start_while_%d|", lbl);
749         sprintf(test_while, "|test_while_%d|", lbl);
750        
751         GSL_PUT_JUMP(test_while,node->line_number);
752         GSL_PUT_LABEL(start_while,node->line_number);
753
754         /* code */
755         commit_node(node->unode.opr.op[1],0);
756
757         GSL_PUT_LABEL(test_while,node->line_number);
758         commit_node(node->unode.opr.op[0],0);
759         GSL_PUT_JNZERO(start_while,node->line_number);
760     } /* }}} */
761
762     /* FOR EACH */
763     static NodeType *new_static_foreach(NodeType *var, NodeType *var_list, NodeType *instr) { /* {{{ */
764         NodeType *node = new_op("for", OPR_FOREACH, 3);
765         node->unode.opr.op[0] = var;
766         node->unode.opr.op[1] = var_list;
767         node->unode.opr.op[2] = instr;
768         node->line_number = currentGoomSL->num_lines;
769         return node;
770     }
771     static void commit_foreach(NodeType *node)
772     {
773         NodeType *cur = node->unode.opr.op[1];
774         char tmp_func[256], tmp_loop[256];
775         int lbl = allocateLabel();
776         sprintf(tmp_func, "|foreach_func_%d|", lbl);
777         sprintf(tmp_loop, "|foreach_loop_%d|", lbl);
778
779         GSL_PUT_JUMP(tmp_loop, node->line_number);
780         GSL_PUT_LABEL(tmp_func, node->line_number);
781
782         precommit_node(node->unode.opr.op[2]);
783         commit_node(node->unode.opr.op[2], 0);
784
785         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "ret", INSTR_RET, 1, node->line_number);
786         gsl_instr_add_param(currentGoomSL->instr, "|dummy|", TYPE_LABEL);
787 #ifdef VERBOSE
788         printf("ret\n");
789 #endif
790         
791         GSL_PUT_LABEL(tmp_loop, node->line_number);
792         
793         while (cur != NULL)
794         {
795           NodeType *x, *var;
796
797           /* 1: x=var */
798           x   = nodeClone(node->unode.opr.op[0]);
799           var = nodeClone(cur->unode.opr.op[0]);
800           commit_node(new_set(x, var),0);
801           
802           /* 2: instr */
803           currentGoomSL->instr = gsl_instr_init(currentGoomSL, "call", INSTR_CALL, 1, node->line_number);
804           gsl_instr_add_param(currentGoomSL->instr, tmp_func, TYPE_LABEL);
805 #ifdef VERBOSE
806           printf("call %s\n", tmp_func);
807 #endif
808           
809           /* 3: var=x */
810           x   = nodeClone(node->unode.opr.op[0]);
811           var = cur->unode.opr.op[0];
812           commit_node(new_set(var, x),0);
813           cur = cur->unode.opr.op[1];
814         }
815         nodeFree(node->unode.opr.op[0]);
816     } /* }}} */
817
818     /* IF */
819     static NodeType *new_if(NodeType *expression, NodeType *instr) { /* {{{ */
820         NodeType *node = new_op("if", OPR_IF, 2);
821         node->unode.opr.op[0] = expression;
822         node->unode.opr.op[1] = instr;
823         return node;
824     }
825     static void commit_if(NodeType *node) {
826
827         char slab[1024];
828         sprintf(slab, "|eif%d|", allocateLabel());
829         commit_node(node->unode.opr.op[0],0);
830         GSL_PUT_JZERO(slab,node->line_number);
831         /* code */
832         commit_node(node->unode.opr.op[1],0);
833         GSL_PUT_LABEL(slab,node->line_number);
834     } /* }}} */
835
836     /* BLOCK */
837     static NodeType *new_block(NodeType *lastNode) { /* {{{ */
838         NodeType *blk = new_op("block", OPR_BLOCK, 2);
839         blk->unode.opr.op[0] = new_nop("start_of_block");
840         blk->unode.opr.op[1] = lastNode;        
841         return blk;
842     }
843     static void commit_block(NodeType *node) {
844         commit_node(node->unode.opr.op[0]->unode.opr.next,0);
845     } /* }}} */
846
847     /* FUNCTION INTRO */
848     static NodeType *new_function_intro(const char *name) { /* {{{ */
849         char stmp[256];
850         if (strlen(name) < 200) {
851            sprintf(stmp, "|__func_%s|", name);
852         }
853         return new_op(stmp, OPR_FUNC_INTRO, 0);
854     }
855     static void commit_function_intro(NodeType *node) {
856         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "label", INSTR_LABEL, 1, node->line_number);
857         gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_LABEL);
858 #ifdef VERBOSE
859         printf("label %s\n", node->str);
860 #endif
861     } /* }}} */
862
863     /* FUNCTION OUTRO */
864     static NodeType *new_function_outro() { /* {{{ */
865         return new_op("ret", OPR_FUNC_OUTRO, 0);
866     }
867     static void commit_function_outro(NodeType *node) {
868         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "ret", INSTR_RET, 1, node->line_number);
869         gsl_instr_add_param(currentGoomSL->instr, "|dummy|", TYPE_LABEL);
870         releaseAllTemps();
871 #ifdef VERBOSE
872         printf("ret\n");
873 #endif
874     } /* }}} */
875     
876     /* AFFECTATION LIST */
877     static NodeType *new_affec_list(NodeType *set, NodeType *next) /* {{{ */
878     {
879       NodeType *node = new_op("affect_list", OPR_AFFECT_LIST, 2);
880       node->unode.opr.op[0] = set;
881       node->unode.opr.op[1] = next;
882       return node;
883     }
884     static NodeType *new_affect_list_after(NodeType *affect_list)
885     {
886       NodeType *ret  = NULL;
887       NodeType *cur  =  affect_list;
888       while(cur != NULL) {
889         NodeType *set  = cur->unode.opr.op[0];
890         NodeType *next = cur->unode.opr.op[1];
891         NodeType *lvalue     = set->unode.opr.op[0];
892         NodeType *expression = set->unode.opr.op[1];
893         if ((lvalue->str[0] == '&') && (expression->type == VAR_NODE)) {
894           NodeType *nset = new_set(nodeClone(expression), nodeClone(lvalue));
895           ret  = new_affec_list(nset, ret);
896         }
897         cur = next;
898       }
899       return ret;
900     }
901     static void commit_affect_list(NodeType *node)
902     {
903       NodeType *cur = node;
904       while(cur != NULL) {
905         NodeType *set = cur->unode.opr.op[0];
906         precommit_node(set->unode.opr.op[0]);
907         precommit_node(set->unode.opr.op[1]);
908         cur = cur->unode.opr.op[1];
909       }
910       cur = node;
911       while(cur != NULL) {
912         NodeType *set = cur->unode.opr.op[0];
913         commit_node(set,0);
914         cur = cur->unode.opr.op[1];
915       }
916     } /* }}} */
917
918     /* VAR LIST */
919     static NodeType *new_var_list(NodeType *var, NodeType *next) /* {{{ */
920     {
921       NodeType *node = new_op("var_list", OPR_VAR_LIST, 2);
922       node->unode.opr.op[0] = var;
923       node->unode.opr.op[1] = next;
924       return node;
925     }
926     static void commit_var_list(NodeType *node)
927     {
928     } /* }}} */
929
930     /* FUNCTION CALL */
931     static NodeType *new_call(const char *name, NodeType *affect_list) { /* {{{ */
932         HashValue *fval;
933         fval = goom_hash_get(currentGoomSL->functions, name);
934         if (!fval) {
935             gsl_declare_task(name);
936             fval = goom_hash_get(currentGoomSL->functions, name);
937         }
938         if (!fval) {
939             fprintf(stderr, "ERROR: Line %d, Could not find function %s\n", currentGoomSL->num_lines, name);
940             exit(1);
941             return NULL;
942         }
943         else {
944             ExternalFunctionStruct *gef = (ExternalFunctionStruct*)fval->ptr;
945             if (gef->is_extern) {
946                 NodeType *node =  new_op(name, OPR_EXT_CALL, 1);
947                 node->unode.opr.op[0] = affect_list;
948                 return node;
949             }
950             else {
951                 NodeType *node;
952                 char stmp[256];
953                 if (strlen(name) < 200) {
954                     sprintf(stmp, "|__func_%s|", name);
955                 }
956                 node = new_op(stmp, OPR_CALL, 1);
957                 node->unode.opr.op[0] = affect_list;
958                 return node;
959             }
960         }
961     }
962     static void commit_ext_call(NodeType *node) {
963         NodeType *alafter = new_affect_list_after(node->unode.opr.op[0]);
964         commit_node(node->unode.opr.op[0],0);
965         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "extcall", INSTR_EXT_CALL, 1, node->line_number);
966         gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_VAR);
967 #ifdef VERBOSE
968         printf("extcall %s\n", node->str);
969 #endif
970         commit_node(alafter,0);
971     }
972     static void commit_call(NodeType *node) {
973         NodeType *alafter = new_affect_list_after(node->unode.opr.op[0]);
974         commit_node(node->unode.opr.op[0],0);
975         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "call", INSTR_CALL, 1, node->line_number);
976         gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_LABEL);
977 #ifdef VERBOSE
978         printf("call %s\n", node->str);
979 #endif
980         commit_node(alafter,0);
981     } /* }}} */
982
983     /** **/
984
985     static NodeType *rootNode = 0; /* TODO: reinitialiser a chaque compilation. */
986     static NodeType *lastNode = 0;
987     static NodeType *gsl_append(NodeType *curNode) {
988         if (curNode == 0) return 0; /* {{{ */
989         if (lastNode)
990             lastNode->unode.opr.next = curNode;
991         lastNode = curNode;
992         while(lastNode->unode.opr.next) lastNode = lastNode->unode.opr.next;
993         if (rootNode == 0)
994             rootNode = curNode;
995         return curNode;
996     } /* }}} */
997
998 #if 1
999     int allocateTemp() {
1000       return allocateLabel();
1001     }
1002     void releaseAllTemps() {}
1003     void releaseTemp(int n) {}
1004 #else
1005     static int nbTemp = 0;
1006     static int *tempArray = 0;
1007     static int tempArraySize = 0;
1008     int allocateTemp() { /* TODO: allocateITemp, allocateFTemp */
1009         int i = 0; /* {{{ */
1010         if (tempArray == 0) {
1011           tempArraySize = 256;
1012           tempArray = (int*)malloc(tempArraySize * sizeof(int));
1013         }
1014         while (1) {
1015           int j;
1016           for (j=0;j<nbTemp;++j) {
1017             if (tempArray[j] == i) break;
1018           }
1019           if (j == nbTemp) {
1020             if (nbTemp == tempArraySize) {
1021               tempArraySize *= 2;
1022               tempArray = (int*)realloc(tempArray,tempArraySize * sizeof(int));
1023             }
1024             tempArray[nbTemp++] = i;
1025             return i;
1026           }
1027           i++;
1028         }
1029     } /* }}} */
1030     void releaseAllTemps() {
1031       nbTemp = 0; /* {{{ */
1032     } /* }}} */
1033     void releaseTemp(int n) {
1034       int j; /* {{{ */
1035       for (j=0;j<nbTemp;++j) {
1036         if (tempArray[j] == n) {
1037           tempArray[j] = tempArray[--nbTemp];
1038           break;
1039         }
1040       }
1041     } /* }}} */
1042 #endif
1043
1044     static int lastLabel = 0;
1045     int allocateLabel() {
1046         return ++lastLabel; /* {{{ */
1047     } /* }}} */
1048
1049     void gsl_commit_compilation()
1050     { /* {{{ */
1051         commit_node(rootNode,0);
1052         rootNode = 0;
1053         lastNode = 0;
1054     } /* }}} */
1055     
1056     void precommit_node(NodeType *node)
1057     { /* {{{ */
1058         /* do here stuff for expression.. for exemple */
1059         if (node->type == OPR_NODE)
1060             switch(node->unode.opr.type) {
1061                 case OPR_ADD: precommit_add(node); break;
1062                 case OPR_SUB: precommit_sub(node); break;
1063                 case OPR_MUL: precommit_mul(node); break;
1064                 case OPR_DIV: precommit_div(node); break;
1065                 case OPR_CALL_EXPR: precommit_call_expr(node); break;
1066             }
1067     } /* }}} */
1068     
1069     void commit_node(NodeType *node, int releaseIfTmp)
1070     { /* {{{ */
1071         if (node == 0) return;
1072         
1073         switch(node->type) {
1074             case OPR_NODE:
1075                 switch(node->unode.opr.type) {
1076                     case OPR_SET:           commit_set(node); break;
1077                     case OPR_PLUS_EQ:       commit_plus_eq(node); break;
1078                     case OPR_SUB_EQ:        commit_sub_eq(node); break;
1079                     case OPR_MUL_EQ:        commit_mul_eq(node); break;
1080                     case OPR_DIV_EQ:        commit_div_eq(node); break;
1081                     case OPR_IF:            commit_if(node); break;
1082                     case OPR_WHILE:         commit_while(node); break;
1083                     case OPR_BLOCK:         commit_block(node); break;
1084                     case OPR_FUNC_INTRO:    commit_function_intro(node); break;
1085                     case OPR_FUNC_OUTRO:    commit_function_outro(node); break;
1086                     case OPR_CALL:          commit_call(node); break;
1087                     case OPR_EXT_CALL:      commit_ext_call(node); break;
1088                     case OPR_EQU:           commit_equ(node); break;
1089                     case OPR_LOW:           commit_low(node); break;
1090                     case OPR_NOT:           commit_not(node); break;
1091                     case OPR_AFFECT_LIST:   commit_affect_list(node); break;
1092                     case OPR_FOREACH:       commit_foreach(node); break;
1093                     case OPR_VAR_LIST:      commit_var_list(node); break;
1094 #ifdef VERBOSE
1095                     case EMPTY_NODE:        printf("NOP\n"); break;
1096 #endif
1097                 }
1098
1099                 commit_node(node->unode.opr.next,0); /* recursive for the moment, maybe better to do something iterative? */
1100                 break;
1101
1102             case VAR_NODE:         gsl_instr_set_namespace(currentGoomSL->instr, node->vnamespace);
1103                                    gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_VAR); break;
1104             case CONST_INT_NODE:   gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_INTEGER); break;
1105             case CONST_FLOAT_NODE: gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_FLOAT); break;
1106             case CONST_PTR_NODE:   gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_PTR); break;
1107         }
1108         if (releaseIfTmp && is_tmp_expr(node))
1109           releaseTemp(get_tmp_id(node));
1110         
1111         nodeFree(node);
1112     } /* }}} */
1113
1114     NodeType *nodeNew(const char *str, int type, int line_number) {
1115         NodeType *node = (NodeType*)malloc(sizeof(NodeType)); /* {{{ */
1116         node->type = type;
1117         node->str  = (char*)malloc(strlen(str)+1);
1118         node->vnamespace = NULL;
1119         node->line_number = line_number;
1120         strcpy(node->str, str);
1121         return node;
1122     } /* }}} */
1123     static NodeType *nodeClone(NodeType *node) {
1124         NodeType *ret = nodeNew(node->str, node->type, node->line_number); /* {{{ */
1125         ret->vnamespace = node->vnamespace;
1126         ret->unode = node->unode;
1127         return ret;
1128     } /* }}} */
1129
1130     void nodeFreeInternals(NodeType *node) {
1131         free(node->str); /* {{{ */
1132     } /* }}} */
1133     
1134     void nodeFree(NodeType *node) {
1135         nodeFreeInternals(node); /* {{{ */
1136         free(node);
1137     } /* }}} */
1138
1139     NodeType *new_constInt(const char *str, int line_number) {
1140         NodeType *node = nodeNew(str, CONST_INT_NODE, line_number); /* {{{ */
1141         node->unode.constInt.val = atoi(str);
1142         return node;
1143     } /* }}} */
1144
1145     NodeType *new_constPtr(const char *str, int line_number) {
1146         NodeType *node = nodeNew(str, CONST_PTR_NODE, line_number); /* {{{ */
1147         node->unode.constPtr.id = strtol(str,NULL,0);
1148         return node;
1149     } /* }}} */
1150
1151     NodeType *new_constFloat(const char *str, int line_number) {
1152         NodeType *node = nodeNew(str, CONST_FLOAT_NODE, line_number); /* {{{ */
1153         node->unode.constFloat.val = atof(str);
1154         return node;
1155     } /* }}} */
1156
1157     NodeType *new_var(const char *str, int line_number) {
1158         NodeType *node = nodeNew(str, VAR_NODE, line_number); /* {{{ */
1159         node->vnamespace = gsl_find_namespace(str);
1160         if (node->vnamespace == 0) {
1161             fprintf(stderr, "ERROR: Line %d, Variable not found: '%s'\n", line_number, str);
1162             exit(1);
1163         }
1164         return node;
1165     } /* }}} */
1166     
1167     NodeType *new_nop(const char *str) {
1168         NodeType *node = new_op(str, EMPTY_NODE, 0); /* {{{ */
1169         return node;
1170     } /* }}} */
1171     
1172     NodeType *new_op(const char *str, int type, int nbOp) {
1173         int i; /* {{{ */
1174         NodeType *node = nodeNew(str, OPR_NODE, currentGoomSL->num_lines);
1175         node->unode.opr.next = 0;
1176         node->unode.opr.type = type;
1177         node->unode.opr.nbOp = nbOp;
1178         for (i=0;i<nbOp;++i) node->unode.opr.op[i] = 0;
1179         return node;
1180     } /* }}} */
1181
1182
1183     void gsl_declare_global_variable(int type, char *name) {
1184       switch(type){
1185         case -1: break;
1186         case FLOAT_TK:gsl_float_decl_global(name);break;
1187         case INT_TK:  gsl_int_decl_global(name);break;
1188         case PTR_TK:  gsl_ptr_decl_global(name);break;
1189         default:
1190         {
1191           int id = type - 1000;
1192           gsl_struct_decl_global_from_id(name,id);
1193         }
1194       }
1195     }
1196
1197 %}
1198
1199 %union {
1200     int intValue;
1201     float floatValue;
1202     char charValue;
1203     char strValue[2048];
1204     NodeType *nPtr;
1205     GoomHash *namespace;
1206     GSL_Struct *gsl_struct;
1207     GSL_StructField *gsl_struct_field;
1208   };
1209   
1210 %token <strValue>   LTYPE_INTEGER
1211 %token <strValue>   LTYPE_FLOAT
1212 %token <strValue>   LTYPE_VAR
1213 %token <strValue>   LTYPE_PTR
1214
1215 %token PTR_TK INT_TK FLOAT_TK DECLARE EXTERNAL WHILE DO NOT PLUS_EQ SUB_EQ DIV_EQ MUL_EQ SUP_EQ LOW_EQ NOT_EQ STRUCT FOR IN
1216
1217 %type <intValue> return_type
1218 %type <nPtr> expression constValue instruction test func_call func_call_expression
1219 %type <nPtr> start_block affectation_list affectation_in_list affectation declaration
1220 %type <nPtr> var_list_content var_list
1221 %type <strValue> task_name ext_task_name 
1222 %type <namespace> leave_namespace
1223 %type <gsl_struct> struct_members
1224 %type <gsl_struct_field> struct_member
1225 %left '\n'
1226 %left PLUS_EQ SUB_EQ MUL_EQ DIV_EQ
1227 %left NOT
1228 %left '=' '<' '>'
1229 %left '+' '-'
1230 %left '/' '*'
1231
1232 %%
1233
1234 /* -------------- Global architechture of a GSL program ------------*/
1235
1236 gsl: gsl_code function_outro gsl_def_functions ;
1237
1238 gsl_code: gsl_code instruction              { gsl_append($2); }
1239    | gsl_code EXTERNAL '<' ext_task_name '>' return_type '\n' leave_namespace             { gsl_declare_global_variable($6,$4); }
1240    | gsl_code EXTERNAL '<' ext_task_name ':' arglist '>' return_type '\n' leave_namespace { gsl_declare_global_variable($8,$4); }
1241    | gsl_code DECLARE '<' task_name '>' return_type  '\n' leave_namespace                 { gsl_declare_global_variable($6,$4); }
1242    | gsl_code DECLARE '<' task_name ':' arglist '>' return_type '\n' leave_namespace      { gsl_declare_global_variable($8,$4); }
1243    | gsl_code struct_declaration
1244    | gsl_code '\n'
1245    |
1246    ;
1247
1248 /* ------------- Declaration of a structure ------------ */
1249
1250 struct_declaration: STRUCT  '<' LTYPE_VAR  ':' struct_members '>' '\n' { gsl_add_struct($3, $5); }
1251                   ;
1252
1253 struct_members: opt_nl struct_member                    { $$ = gsl_new_struct($2);               }
1254               | struct_members ',' opt_nl struct_member { $$ = $1; gsl_add_struct_field($1, $4); }
1255               ;
1256
1257 struct_member: INT_TK    LTYPE_VAR { $$ = gsl_new_struct_field($2, INSTR_INT); }
1258              | FLOAT_TK  LTYPE_VAR { $$ = gsl_new_struct_field($2, INSTR_FLOAT); }
1259              | PTR_TK    LTYPE_VAR { $$ = gsl_new_struct_field($2, INSTR_PTR); }
1260              | LTYPE_VAR LTYPE_VAR { $$ = gsl_new_struct_field_struct($2, $1); }
1261              ;
1262
1263 /* ------------- Fonction declarations -------------- */
1264
1265 ext_task_name: LTYPE_VAR { gsl_declare_external_task($1); gsl_enternamespace($1); strcpy($$,$1); }
1266              ;
1267 task_name:     LTYPE_VAR { gsl_declare_task($1); gsl_enternamespace($1); strcpy($$,$1); strcpy($$,$1); }
1268          ;
1269
1270 return_type:      { $$=-1; }
1271   | ':' INT_TK    { $$=INT_TK; }
1272   | ':' FLOAT_TK  { $$=FLOAT_TK; }
1273   | ':' PTR_TK    { $$=PTR_TK; }
1274   | ':' LTYPE_VAR { $$= 1000 + gsl_get_struct_id($2); }
1275   ;
1276
1277 arglist: empty_declaration
1278        | empty_declaration ',' arglist
1279        ;
1280
1281 /* ------------- Fonction definition -------------- */
1282
1283 gsl_def_functions: gsl_def_functions function
1284                  |
1285                  ;
1286
1287 function: function_intro gsl_code function_outro { gsl_leavenamespace(); }
1288
1289 function_intro: '<' task_name '>' return_type '\n'             { gsl_append(new_function_intro($2));
1290                                                                  gsl_declare_global_variable($4,$2); }
1291               | '<' task_name ':' arglist '>' return_type '\n' { gsl_append(new_function_intro($2));
1292                                                                  gsl_declare_global_variable($6,$2); }
1293               ;
1294 function_outro: { gsl_append(new_function_outro()); } ;
1295
1296 leave_namespace:      { $$ = gsl_leavenamespace();   };
1297
1298 /* ------------ Variable declaration ---------------- */
1299
1300 declaration: FLOAT_TK LTYPE_VAR '=' expression { gsl_float_decl_local($2); $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
1301            | INT_TK   LTYPE_VAR '=' expression { gsl_int_decl_local($2);   $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
1302            | PTR_TK   LTYPE_VAR '=' expression { gsl_ptr_decl_local($2);   $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
1303            | LTYPE_VAR LTYPE_VAR '=' expression { gsl_struct_decl_local($1,$2); $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
1304            | empty_declaration                { $$ = 0; }
1305            ;
1306
1307 empty_declaration: FLOAT_TK  LTYPE_VAR { gsl_float_decl_local($2);       }
1308                  | INT_TK    LTYPE_VAR { gsl_int_decl_local($2);         }
1309                  | PTR_TK    LTYPE_VAR { gsl_ptr_decl_local($2);         }
1310                  | LTYPE_VAR LTYPE_VAR { gsl_struct_decl_local($1,$2);   }
1311                  ;
1312
1313 /* -------------- Instructions and Expressions ------------------ */
1314
1315 instruction: affectation '\n' { $$ = $1; }
1316            | declaration '\n' { $$ = $1; }
1317            | '(' test ')' '?' opt_nl instruction     { $$ = new_if($2,$6); }
1318            | WHILE test opt_nl DO opt_nl instruction { $$ = new_while($2,$6); }
1319            | '{' '\n' start_block gsl_code '}' '\n'  { lastNode = $3->unode.opr.op[1]; $$=$3; }
1320            | func_call                               { $$ = $1; }
1321            | LTYPE_VAR PLUS_EQ expression { $$ = new_plus_eq(new_var($1,currentGoomSL->num_lines),$3); }
1322            | LTYPE_VAR SUB_EQ expression  { $$ = new_sub_eq(new_var($1,currentGoomSL->num_lines),$3); }
1323            | LTYPE_VAR MUL_EQ expression  { $$ = new_mul_eq(new_var($1,currentGoomSL->num_lines),$3); }
1324            | LTYPE_VAR DIV_EQ expression  { $$ = new_div_eq(new_var($1,currentGoomSL->num_lines),$3); }
1325            | FOR LTYPE_VAR IN var_list DO instruction { $$ = new_static_foreach(new_var($2, currentGoomSL->num_lines), $4, $6); }
1326            ;
1327
1328 var_list: '(' var_list_content ')'      { $$ = $2; }
1329         ;
1330 var_list_content: LTYPE_VAR             { $$ = new_var_list(new_var($1,currentGoomSL->num_lines), NULL); }
1331            | LTYPE_VAR var_list_content { $$ = new_var_list(new_var($1,currentGoomSL->num_lines), $2);   }
1332            ;
1333
1334 affectation: LTYPE_VAR '=' expression { $$ = new_set(new_var($1,currentGoomSL->num_lines),$3); } ;
1335
1336 start_block: { $$ = new_block(lastNode); lastNode = $$->unode.opr.op[0]; }
1337            ;
1338
1339 expression: LTYPE_VAR   { $$ = new_var($1,currentGoomSL->num_lines); }
1340           | constValue  { $$ = $1; }
1341           | expression '*' expression { $$ = new_mul($1,$3); } 
1342           | expression '/' expression { $$ = new_div($1,$3); } 
1343           | expression '+' expression { $$ = new_add($1,$3); } 
1344           | expression '-' expression { $$ = new_sub($1,$3); } 
1345           | '-' expression            { $$ = new_neg($2);    }
1346           | '(' expression ')'        { $$ = $2; }
1347           | func_call_expression      { $$ = $1; }
1348           ;
1349
1350 test: expression '=' expression { $$ = new_equ($1,$3); } 
1351     | expression '<' expression { $$ = new_low($1,$3); } 
1352     | expression '>' expression { $$ = new_low($3,$1); }
1353     | expression SUP_EQ expression { $$ = new_not(new_low($1,$3)); }
1354     | expression LOW_EQ expression { $$ = new_not(new_low($3,$1)); }
1355     | expression NOT_EQ expression { $$ = new_not(new_equ($1,$3)); }
1356     | NOT test                  { $$ = new_not($2);    }
1357     ;
1358
1359 constValue: LTYPE_FLOAT   { $$ = new_constFloat($1,currentGoomSL->num_lines); }
1360           | LTYPE_INTEGER { $$ = new_constInt($1,currentGoomSL->num_lines); } 
1361           | LTYPE_PTR     { $$ = new_constPtr($1,currentGoomSL->num_lines); } 
1362           ;
1363
1364 /* ---------------- Function Calls ------------------ */
1365
1366 func_call:   task_name '\n' leave_namespace                          { $$ = new_call($1,NULL); }
1367            | task_name ':' affectation_list '\n' leave_namespace         { $$ = new_call($1,$3); }
1368            | '[' task_name ']' '\n' leave_namespace                  { $$ = new_call($2,NULL); }
1369            | '[' task_name ':' affectation_list ']' '\n' leave_namespace { $$ = new_call($2,$4); }
1370            ;
1371
1372 func_call_expression:
1373             '[' task_name leave_namespace ']'                      { $$ = new_call_expr($2,NULL); }
1374           | '[' task_name ':' affectation_list ']' leave_namespace { $$ = new_call_expr($2,$4); }
1375           ;
1376              
1377 affectation_list: affectation_in_list affectation_list     { $$ = new_affec_list($1,$2);   }
1378             | affectation_in_list                          { $$ = new_affec_list($1,NULL); }
1379
1380 affectation_in_list: LTYPE_VAR '=' leave_namespace expression {
1381                               gsl_reenternamespace($3);
1382                               $$ = new_set(new_var($1,currentGoomSL->num_lines),$4);
1383                             }
1384                    | ':' leave_namespace expression {
1385                               gsl_reenternamespace($2);
1386                               $$ = new_set(new_var("&this", currentGoomSL->num_lines),$3);
1387                             }
1388                    ;
1389
1390
1391 /* ------------ Misc ---------- */
1392
1393 opt_nl: '\n' | ;
1394            
1395
1396 %%
1397
1398
1399 void yyerror(char *str)
1400 { /* {{{ */
1401     fprintf(stderr, "ERROR: Line %d, %s\n", currentGoomSL->num_lines, str);
1402     currentGoomSL->compilationOK = 0;
1403     exit(1);
1404 } /* }}} */
1405