Kannel: Open Source WAP and SMS gateway  svn-r5335
wsstree.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  *
59  * wsstree.c
60  *
61  * Author: Markku Rossi <mtr@iki.fi>
62  *
63  * Copyright (c) 1999-2000 WAPIT OY LTD.
64  * All rights reserved.
65  *
66  * Syntax tree creation, manipulation and byte-code assembler
67  * generation.
68  *
69  */
70 
71 #include "wsint.h"
72 #include "wsgram.h"
73 
74 /* TODO: Constant folding. */
75 
76 /********************* Misc syntax tree structures **********************/
77 
79  char *name, WsExpression *expr)
80 {
81  WsVarDec *vardec = ws_f_malloc(compiler->pool_stree, sizeof(*vardec));
82 
83  if (vardec == NULL)
84  ws_error_memory(compiler);
85  else {
86  vardec->name = name;
87  vardec->expr = expr;
88  }
89 
90  return vardec;
91 }
92 
94  WsUInt32 line, char *name)
95 {
96  WsFormalParm *parm = ws_f_malloc(compiler->pool_stree, sizeof(*parm));
97 
98  if (parm == NULL)
99  ws_error_memory(compiler);
100  else {
101  parm->line = line;
102  parm->name = name;
103  }
104 
105  return parm;
106 }
107 
108 /********************* Linked list **************************************/
109 
111 {
112  WsList *list = ws_f_calloc(compiler->pool_stree, 1, sizeof(*list));
113 
114  if (list == NULL)
115  ws_error_memory(compiler);
116 
117  return list;
118 }
119 
120 
121 void ws_list_append(WsCompiler *compiler, WsList *list, void *value)
122 {
123  WsListItem *item;
124 
125  if (list == NULL)
126  /* A recovery code for previous memory allocation problems. */
127  return;
128 
129  item = ws_f_calloc(compiler->pool_stree, 1, sizeof(*item));
130  if (item == NULL) {
131  ws_error_memory(compiler);
132  return;
133  }
134 
135  item->data = value;
136 
137  if (list->tail) {
138  list->tail->next = item;
139  list->tail = item;
140  } else
141  list->head = list->tail = item;
142 
143  list->num_items++;
144 }
145 
146 /********************* Namespace for arguments and locals ***************/
147 
148 static void variable_hash_destructor(void *item, void *context)
149 {
150  ws_free(item);
151 }
152 
153 
155 {
157 }
158 
159 
161  WsBool variablep, char *name)
162 {
163  WsNamespace *ns;
164 
165  /* Is the symbol already defined? */
166  ns = ws_hash_get(compiler->variables_hash, name);
167  if (ns) {
168  ws_src_error(compiler, line, "redeclaration of `%s'", name);
169  ws_src_error(compiler, ns->line, "`%s' previously declared here", name);
170  return NULL;
171  }
172 
173  /* Can we still define more variables? */
174  if (compiler->next_vindex > 255) {
175  /* No we can't. */
176  ws_src_error(compiler, line, "too many local variables");
177  return NULL;
178  }
179 
180  ns = ws_calloc(1, sizeof(*ns));
181  if (ns == NULL) {
182  ws_error_memory(compiler);
183  return NULL;
184  }
185 
186  ns->line = line;
187  ns->vindex = compiler->next_vindex++;
188 
189  if (!ws_hash_put(compiler->variables_hash, name, ns)) {
190  ws_free(ns);
191  ws_error_memory(compiler);
192  return NULL;
193  }
194 
195  return ns;
196 }
197 
198 
200 {
201  return ws_hash_get(compiler->variables_hash, name);
202 }
203 
204 /********************* Top-level declarations ***************************/
205 
206 /* External compilation units. */
207 
208 static void pragma_use_hash_destructor(void *item, void *context)
209 {
210  ws_free(item);
211 }
212 
213 
215 {
217 }
218 
219 
220 void ws_pragma_use(WsCompilerPtr compiler, WsUInt32 line, char *identifier,
221  WsUtf8String *url)
222 {
223  WsPragmaUse *u = ws_calloc(1, sizeof(*u));
224  WsPragmaUse *uold;
225 
226  /* Do we already know this pragma? */
227  uold = ws_hash_get(compiler->pragma_use_hash, identifier);
228  if (uold) {
229  ws_src_error(compiler, line, "redefinition of pragma `%s'", identifier);
230  ws_src_error(compiler, uold->line, "`%s' previously defined here",
231  identifier);
232  goto error_cleanup;
233  }
234 
235  if (u == NULL)
236  goto error;
237 
238  u->line = line;
239 
240  /* Insert the URL to the byte-code module. */
241  if (!ws_bc_add_const_utf8_string(compiler->bc, &u->urlindex, url->data,
242  url->len))
243  goto error;
244 
245  /* Add it to the use pragma hash. */
246  if (!ws_hash_put(compiler->pragma_use_hash, identifier, u))
247  goto error;
248 
249  /* Cleanup. */
250 
251  ws_lexer_free_block(compiler, identifier);
252  ws_lexer_free_utf8(compiler, url);
253 
254  return;
255 
256  /* Error handling. */
257 
258 error:
259 
260  ws_error_memory(compiler);
261 
262 error_cleanup:
263 
264  ws_free(u);
265  ws_lexer_free_block(compiler, identifier);
266  ws_lexer_free_utf8(compiler, url);
267 }
268 
269 /* MetaBody of the `use meta' pragmas. */
270 
272  WsUtf8String *property_name,
274  WsUtf8String *scheme)
275 {
276  WsPragmaMetaBody *mb = ws_calloc(1, sizeof(*mb));
277 
278  if (mb == NULL) {
279  ws_error_memory(compiler);
280  return NULL;
281  }
282 
283  mb->property_name = property_name;
284  mb->content = content;
285  mb->scheme = scheme;
286 
287  return mb;
288 }
289 
290 
292 {
293  if (mb == NULL)
294  return;
295 
296  ws_lexer_free_utf8(compiler, mb->property_name);
297  ws_lexer_free_utf8(compiler, mb->content);
298  ws_lexer_free_utf8(compiler, mb->scheme);
299 
300  ws_free(mb);
301 }
302 
303 
304 /* Functions. */
305 
306 static void function_hash_destructor(void *item, void *context)
307 {
308  ws_free(item);
309 }
310 
311 
313 {
315 }
316 
317 
319 {
321 
322  if (i)
323  return i;
324 
325  /* Must create a new mapping. */
326 
327  i = ws_calloc(1, sizeof(*i));
328  if (i == NULL) {
329  ws_error_memory(compiler);
330  return NULL;
331  }
332 
333  if (!ws_hash_put(compiler->functions_hash, name, i)) {
334  ws_free(i);
335  ws_error_memory(compiler);
336  return NULL;
337  }
338 
339  return i;
340 }
341 
342 
343 void ws_function(WsCompiler *compiler, WsBool externp, char *name,
344  WsUInt32 line, WsList *params, WsList *block)
345 {
346  WsFunctionHash *hash;
347  WsFunction *f = ws_realloc(compiler->functions,
348  ((compiler->num_functions + 1)
349  * sizeof(WsFunction)));
350 
351  if (f == NULL) {
352  ws_free(name);
353  ws_error_memory(compiler);
354  return;
355  }
356 
357  if (externp)
358  compiler->num_extern_functions++;
359  else
360  compiler->num_local_functions++;
361 
362  compiler->functions = f;
363  f = &compiler->functions[compiler->num_functions];
364 
365  f->findex = compiler->num_functions++;
366 
367  f->externp = externp;
368  f->name = name;
369  f->line = line;
370  f->params = params;
371  f->block = block;
372 
373  /* Update the function name hash. */
374 
375  hash = ws_function_hash(compiler, name);
376  if (hash == NULL) {
377  ws_error_memory(compiler);
378  return;
379  }
380 
381  if (hash->defined) {
382  ws_src_error(compiler, line, "redefinition of `%s'", name);
383  ws_src_error(compiler,
384  compiler->functions[hash->findex].line,
385  "`%s' previously defined here", name);
386  return;
387  }
388 
389  hash->defined = WS_TRUE;
390  hash->findex = f->findex;
391 }
392 
393 /********************* Expressions **************************************/
394 
396 {
397  WsListItem *li;
398  WsAsmIns *ins;
399 
400  switch (expr->type) {
401  case WS_EXPR_COMMA:
402  /* Linearize left. */
403  ws_expr_linearize(compiler, expr->u.comma.left);
404 
405  /* Pop its result. */
406  ws_asm_link(compiler, ws_asm_ins(compiler, expr->line, WS_ASM_POP));
407 
408  /* Linearize right */
409  ws_expr_linearize(compiler, expr->u.comma.right);
410  break;
411 
412  case WS_EXPR_ASSIGN:
413  {
414  WsNamespace *ns = ws_variable_lookup(compiler,
415  expr->u.assign.identifier);
416 
417  if (ns == NULL) {
418  /* Unknown identifier. */
419  ws_src_error(compiler, expr->line, "unknown variable `%s'",
420  expr->u.symbol);
421  return;
422  }
423 
424  if (expr->u.assign.op == '=') {
425  /* Evaluate the expression. */
426  ws_expr_linearize(compiler, expr->u.assign.expr);
427 
428  /* Store the value to the variable. */
429  ws_asm_link(compiler,
430  ws_asm_variable(compiler, expr->line,
431  WS_ASM_P_STORE_VAR, ns->vindex));
432  } else if (expr->u.assign.op == tADDA) {
433  /* Linearize the expression. */
434  ws_expr_linearize(compiler, expr->u.assign.expr);
435 
436  /* Add it to the variable. */
437  ws_asm_link(compiler,
438  ws_asm_variable(compiler, expr->line,
439  WS_ASM_ADD_ASG, ns->vindex));
440  } else if (expr->u.assign.op == tSUBA) {
441  /* Linearize the expression. */
442  ws_expr_linearize(compiler, expr->u.assign.expr);
443 
444  /* Substract it from the variable. */
445  ws_asm_link(compiler,
446  ws_asm_variable(compiler, expr->line,
447  WS_ASM_SUB_ASG, ns->vindex));
448  } else {
449  /* Load the old value from the variable. */
450  ws_asm_link(compiler,
451  ws_asm_variable(compiler, expr->line,
452  WS_ASM_P_LOAD_VAR, ns->vindex));
453 
454  /* Evaluate the expression. */
455  ws_expr_linearize(compiler, expr->u.assign.expr);
456 
457  /* Perform the operand. */
458  ins = NULL;
459  switch (expr->u.assign.op) {
460  case tMULA:
461  ins = ws_asm_ins(compiler, expr->line, WS_ASM_MUL);
462  break;
463 
464  case tDIVA:
465  ins = ws_asm_ins(compiler, expr->line, WS_ASM_DIV);
466  break;
467 
468  case tREMA:
469  ins = ws_asm_ins(compiler, expr->line, WS_ASM_REM);
470  break;
471 
472  case tADDA:
473  ins = ws_asm_ins(compiler, expr->line, WS_ASM_ADD);
474  break;
475 
476  case tSUBA:
477  ins = ws_asm_ins(compiler, expr->line, WS_ASM_SUB);
478  break;
479 
480  case tLSHIFTA:
481  ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_LSHIFT);
482  break;
483 
484  case tRSSHIFTA:
485  ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_RSSHIFT);
486  break;
487 
488  case tRSZSHIFTA:
489  ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_RSZSHIFT);
490  break;
491 
492  case tANDA:
493  ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_AND);
494  break;
495 
496  case tXORA:
497  ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_XOR);
498  break;
499 
500  case tORA:
501  ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_OR);
502  break;
503 
504  case tIDIVA:
505  ins = ws_asm_ins(compiler, expr->line, WS_ASM_IDIV);
506  break;
507 
508  default:
509  ws_fatal("ws_expr_linearize(): unknown assignment operand %x",
510  expr->u.assign.op);
511  break;
512  }
513  ws_asm_link(compiler, ins);
514 
515  /* Store the value to the variable. */
516  ws_asm_link(compiler,
517  ws_asm_variable(compiler, expr->line,
518  WS_ASM_P_STORE_VAR, ns->vindex));
519  }
520  /* The value of the assignment expression is the value
521  assigned. So, we must load the value from the variable.
522  This would also be a good place for the `dup' operand but
523  we lose since we don't have it. */
524  ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
525  WS_ASM_P_LOAD_VAR, ns->vindex));
526  }
527  break;
528 
529  case WS_EXPR_CONDITIONAL:
530  {
531  WsAsmIns *l_else = ws_asm_label(compiler, expr->line);
532  WsAsmIns *l_end = ws_asm_label(compiler, expr->line);
533 
534  /* Linearize condition. */
535  ws_expr_linearize(compiler, expr->u.conditional.e_cond);
536 
537  /* If the result if false, jump to the else-branch. */
538  ws_asm_link(compiler, ws_asm_branch(compiler, expr->line,
539  WS_ASM_P_TJUMP, l_else));
540 
541  /* Linearize the then-expression and jump out. */
542  ws_expr_linearize(compiler, expr->u.conditional.e_then);
543  ws_asm_link(compiler, ws_asm_branch(compiler, expr->line,
544  WS_ASM_P_JUMP, l_end));
545 
546  /* The else-branch. */
547  ws_asm_link(compiler, l_else);
548  ws_expr_linearize(compiler, expr->u.conditional.e_else);
549 
550  /* Insert the end label. */
551  ws_asm_link(compiler, l_end);
552  }
553  break;
554 
555  case WS_EXPR_LOGICAL:
556  {
557  WsAsmIns *l_out = ws_asm_label(compiler, expr->line);
558 
559  /* Linearize the left-hand size expression. */
560  ws_expr_linearize(compiler, expr->u.logical.left);
561 
562  /* Short-circuit check. The type of the logical expression is
563  the short-circuit byte-code operand. */
564  ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
565  expr->u.logical.type));
566  ws_asm_link(compiler, ws_asm_branch(compiler, expr->line,
567  WS_ASM_P_TJUMP, l_out));
568 
569  /* Linearize the right-hand size expression. */
570  ws_expr_linearize(compiler, expr->u.logical.right);
571 
572  /* The result of a logical expression should be boolean.
573  * Control statements do automatic conversion, but typeof()
574  * does not. */
575  ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
576  WS_ASM_TOBOOL));
577 
578  /* Insert the end label. */
579  ws_asm_link(compiler, l_out);
580  }
581  break;
582 
583  case WS_EXPR_BINARY:
584  /* Linearize left and right. */
585  ws_expr_linearize(compiler, expr->u.binary.left);
586  ws_expr_linearize(compiler, expr->u.binary.right);
587 
588  /* The type of the binary expression is the byte-code opcode. */
589  ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
590  expr->u.binary.type));
591  break;
592 
593  case WS_EXPR_UNARY:
594  /* Linearize the expression. */
595  ws_expr_linearize(compiler, expr->u.unary.expr);
596 
597  /* The type of the unary expression is the byte-code opcode. */
598  ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
599  expr->u.unary.type));
600  break;
601 
602  case WS_EXPR_UNARY_VAR:
603  {
604  WsNamespace *ns = ws_variable_lookup(compiler,
605  expr->u.unary_var.variable);
606  if (ns == NULL) {
607  /* An unknown identifier. */
608  ws_src_error(compiler, expr->line, "unknown variable `%s'",
609  expr->u.unary_var.variable);
610  return;
611  }
612 
613  /* First, do the operation. */
614  if (expr->u.unary_var.addp)
615  ws_asm_link(compiler,
616  ws_asm_variable(compiler, expr->line, WS_ASM_P_INCR_VAR,
617  ns->vindex));
618  else
619  ws_asm_link(compiler,
620  ws_asm_variable(compiler, expr->line, WS_ASM_DECR_VAR,
621  ns->vindex));
622 
623  /* Second, load the new value of the variable. */
624  ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
625  WS_ASM_P_LOAD_VAR, ns->vindex));
626  }
627  break;
628 
629  case WS_EXPR_POSTFIX_VAR:
630  {
631  WsNamespace *ns = ws_variable_lookup(compiler,
632  expr->u.postfix_var.variable);
633  if (ns == NULL) {
634  /* An unknown identifier. */
635  ws_src_error(compiler, expr->line, "unknown variable `%s'",
636  expr->u.postfix_var.variable);
637  return;
638  }
639 
640  /* First, load the old value of the variable. */
641  ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
642  WS_ASM_P_LOAD_VAR, ns->vindex));
643 
644  /* Second, do the operation. */
645  if (expr->u.unary_var.addp)
646  ws_asm_link(compiler,
647  ws_asm_variable(compiler, expr->line, WS_ASM_P_INCR_VAR,
648  ns->vindex));
649  else
650  ws_asm_link(compiler,
651  ws_asm_variable(compiler, expr->line, WS_ASM_DECR_VAR,
652  ns->vindex));
653  }
654  break;
655 
656  case WS_EXPR_CALL:
657  /* First, evaluate the arguments. */
658  for (li = expr->u.call.arguments->head; li; li = li->next)
659  ws_expr_linearize(compiler, li->data);
660 
661  /* Second, emit the call instruction. */
662  switch (expr->u.call.type) {
663  case ' ': /* LocalScriptFunctionCall */
664  {
665  WsFunctionHash *f = ws_function_hash(compiler, expr->u.call.name);
666 
667  if (f == NULL || !f->defined)
668  {
669  ws_src_error(compiler, expr->line,
670  "unknown local function `%s'",
671  expr->u.call.name);
672  return;
673  }
674 
675  /* Check that the function is called with correct amount
676  of arguments. */
677  if (expr->u.call.arguments->num_items
678  != compiler->functions[f->findex].params->num_items)
679  {
680  ws_src_error(compiler, expr->line,
681  "invalid amount of arguments for `%s': "
682  "expected %u, got %u",
683  expr->u.call.name,
684  compiler->functions[f->findex].params->num_items,
685  expr->u.call.arguments->num_items);
686  return;
687  }
688 
689  /* Emit assembler. */
690  ws_asm_link(compiler, ws_asm_call(compiler, expr->line,
691  f->findex));
692  }
693  break;
694 
695  case '#': /* ExternalScriptFunctionCall */
696  {
697  WsPragmaUse *use = ws_hash_get(compiler->pragma_use_hash,
698  expr->u.call.base);
699  WsUInt16 findex;
700 
701  if (use == NULL)
702  {
703  ws_src_error(compiler, expr->line,
704  "unknown external compilation unit `%s'",
705  expr->u.call.base);
706  return;
707  }
708 
709  /* Insert the function name to the byte-code pool. */
711  compiler->bc, &findex,
712  (unsigned char *) expr->u.call.name,
713  strlen(expr->u.call.name)))
714  {
715  ws_error_memory(compiler);
716  return;
717  }
718 
719  /* Emit assembler. */
720  ws_asm_link(compiler,
721  ws_asm_call_url(compiler, expr->line,
722  findex, use->urlindex,
723  expr->u.call.arguments->num_items));
724  }
725  break;
726 
727  case '.': /* LibraryFunctionCall */
728  {
729  WsUInt16 lindex;
730  WsUInt8 findex;
731  WsUInt8 num_args;
732  WsBool lindex_found;
733  WsBool findex_found;
734 
735  if (!ws_stdlib_function(expr->u.call.base, expr->u.call.name,
736  &lindex, &findex, &num_args,
737  &lindex_found, &findex_found))
738  {
739  if (!lindex_found)
740  ws_src_error(compiler, expr->line,
741  "unknown system library `%s'",
742  expr->u.call.base);
743  else
744  ws_src_error(compiler, expr->line,
745  "unknown library function `%s.%s'",
746  expr->u.call.base, expr->u.call.name);
747 
748  return;
749  }
750  /* Check the argument count. */
751  if (expr->u.call.arguments->num_items != num_args)
752  {
753  ws_src_error(compiler, expr->line,
754  "invalid amount of arguments for `%s.%s': "
755  "expected %u, got %u",
756  expr->u.call.base, expr->u.call.name,
757  num_args, expr->u.call.arguments->num_items);
758  return;
759  }
760 
761  /* Emit assembler. */
762  ws_asm_link(compiler, ws_asm_call_lib(compiler, expr->line, findex,
763  lindex));
764  }
765  break;
766 
767  default:
768  ws_fatal("ws_expr_linearize(): unknown call expression type %x",
769  expr->u.call.type);
770  break;
771  }
772  break;
773 
774  case WS_EXPR_SYMBOL:
775  {
776  WsNamespace *ns = ws_variable_lookup(compiler, expr->u.symbol);
777 
778  if (ns == NULL) {
779  /* An unknown identifier. */
780  ws_src_error(compiler, expr->line, "unknown variable `%s'",
781  expr->u.symbol);
782  return;
783  }
784 
785  /* Create a load instruction for the variable. */
786  ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
787  WS_ASM_P_LOAD_VAR, ns->vindex));
788  }
789  break;
790 
792  ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
794  break;
795 
796  case WS_EXPR_CONST_TRUE:
797  ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
799  break;
800 
801  case WS_EXPR_CONST_FALSE:
802  ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
804  break;
805 
806 
808  if (expr->u.integer.ival == 0)
809  ins = ws_asm_ins(compiler, expr->line, WS_ASM_CONST_0);
810  else if (expr->u.integer.ival == 1 && expr->u.integer.sign == 1)
811  ins = ws_asm_ins(compiler, expr->line, WS_ASM_CONST_1);
812  else {
813  WsUInt16 cindex;
814  WsInt32 ival;
815 
816  if (expr->u.integer.sign >= 0) {
817  if (expr->u.integer.ival > (WsUInt32) WS_INT32_MAX)
818  ws_src_error(compiler, expr->line,
819  "integer literal too large");
820  ival = expr->u.integer.ival;
821  } else {
822  if (expr->u.integer.ival > (WsUInt32) WS_INT32_MAX + 1)
823  ws_src_error(compiler, expr->line, "integer too small");
824  ival = - (WsInt32) expr->u.integer.ival;
825  }
826 
827  if (!ws_bc_add_const_int(compiler->bc, &cindex, ival)) {
828  ws_error_memory(compiler);
829  return;
830  }
831  ins = ws_asm_load_const(compiler, expr->line, cindex);
832  }
833 
834  ws_asm_link(compiler, ins);
835  break;
836 
837  case WS_EXPR_CONST_FLOAT:
838  {
839  WsUInt16 cindex;
840 
841  if (!ws_bc_add_const_float(compiler->bc, &cindex, expr->u.fval)) {
842  ws_error_memory(compiler);
843  return;
844  }
845 
846  ws_asm_link(compiler, ws_asm_load_const(compiler, expr->line, cindex));
847  }
848  break;
849 
851  if (expr->u.string.len == 0)
852  ins = ws_asm_ins(compiler, expr->line, WS_ASM_CONST_ES);
853  else {
854  WsUInt16 cindex;
855 
856  if (!ws_bc_add_const_utf8_string(compiler->bc, &cindex,
857  expr->u.string.data,
858  expr->u.string.len)) {
859  ws_error_memory(compiler);
860  return;
861  }
862  ins = ws_asm_load_const(compiler, expr->line, cindex);
863  }
864 
865  ws_asm_link(compiler, ins);
866  break;
867  }
868 }
869 
870 
871 /* Constructors. */
872 
875 {
876  WsExpression *expr = ws_f_calloc(compiler->pool_stree, 1, sizeof(*expr));
877 
878  if (expr == NULL)
879  ws_error_memory(compiler);
880  else {
881  expr->type = type;
882  expr->line = line;
883  }
884 
885  return expr;
886 }
887 
888 
890  WsExpression *left, WsExpression *right)
891 {
892  WsExpression *expr = expr_alloc(compiler, WS_EXPR_COMMA, line);
893 
894  if (expr) {
895  expr->u.comma.left = left;
896  expr->u.comma.right = right;
897  }
898 
899  return expr;
900 }
901 
902 
904  char *identifier, int op, WsExpression *expr)
905 {
906  WsExpression *e = expr_alloc(compiler, WS_EXPR_ASSIGN, line);
907 
908  if (e) {
909  e->u.assign.identifier = ws_f_strdup(compiler->pool_stree, identifier);
910  if (e->u.assign.identifier == NULL)
911  ws_error_memory(compiler);
912 
913  e->u.assign.op = op;
914  e->u.assign.expr = expr;
915  }
916 
917  /* Free the identifier symbol since it allocated from the system
918  heap. */
919  ws_lexer_free_block(compiler, identifier);
920 
921  return e;
922 }
923 
924 
926  WsExpression *e_cond, WsExpression *e_then,
927  WsExpression *e_else)
928 {
929  WsExpression *e = expr_alloc(compiler, WS_EXPR_CONDITIONAL, line);
930 
931  if (e) {
932  e->u.conditional.e_cond = e_cond;
933  e->u.conditional.e_then = e_then;
934  e->u.conditional.e_else = e_else;
935  }
936 
937  return e;
938 }
939 
940 
942  int type, WsExpression *left, WsExpression *right)
943 {
944  WsExpression *expr = expr_alloc(compiler, WS_EXPR_LOGICAL, line);
945 
946  if (expr) {
947  expr->u.logical.type = type;
948  expr->u.logical.left = left;
949  expr->u.logical.right = right;
950  }
951 
952  return expr;
953 }
954 
955 
957  int type, WsExpression *left, WsExpression *right)
958 {
959  WsExpression *expr = expr_alloc(compiler, WS_EXPR_BINARY, line);
960 
961  if (expr) {
962  expr->u.binary.type = type;
963  expr->u.binary.left = left;
964  expr->u.binary.right = right;
965  }
966 
967  return expr;
968 }
969 
970 
972  WsExpression *expression)
973 {
974  WsExpression *expr;
975 
976  /* Handle negative integers here as a special case of constant folding,
977  * in order to get -2147483648 right. */
978  if (type == WS_ASM_UMINUS && expression->type == WS_EXPR_CONST_INTEGER) {
979  expression->u.integer.sign = - expression->u.integer.sign;
980  return expression;
981  }
982 
983  expr = expr_alloc(compiler, WS_EXPR_UNARY, line);
984  if (expr) {
985  expr->u.unary.type = type;
986  expr->u.unary.expr = expression;
987  }
988 
989  return expr;
990 }
991 
992 
994  WsBool addp, char *variable)
995 {
996  WsExpression *expr = expr_alloc(compiler, WS_EXPR_UNARY_VAR, line);
997 
998  if (expr) {
999  expr->u.unary_var.addp = addp;
1000  expr->u.unary_var.variable = ws_f_strdup(compiler->pool_stree, variable);
1001  if (expr->u.unary_var.variable == NULL)
1002  ws_error_memory(compiler);
1003  }
1004  ws_lexer_free_block(compiler, variable);
1005 
1006  return expr;
1007 }
1008 
1009 
1011  WsBool addp, char *variable)
1012 {
1013  WsExpression *expr = expr_alloc(compiler, WS_EXPR_POSTFIX_VAR, line);
1014 
1015  if (expr) {
1016  expr->u.postfix_var.addp = addp;
1017  expr->u.postfix_var.variable = ws_f_strdup(compiler->pool_stree,
1018  variable);
1019  if (expr->u.postfix_var.variable == NULL)
1020  ws_error_memory(compiler);
1021  }
1022  ws_lexer_free_block(compiler, variable);
1023 
1024  return expr;
1025 }
1026 
1027 
1029  int type, char *base, char *name, WsList *arguments)
1030 {
1031  WsExpression *expr = expr_alloc(compiler, WS_EXPR_CALL, line);
1032 
1033  if (expr) {
1034  expr->u.call.type = type;
1035  expr->u.call.base = ws_f_strdup(compiler->pool_stree, base);
1036  expr->u.call.name = ws_f_strdup(compiler->pool_stree, name);
1037  expr->u.call.arguments = arguments;
1038 
1039  if ((base && expr->u.call.base == NULL)
1040  || (name && expr->u.call.name == NULL))
1041  ws_error_memory(compiler);
1042  }
1043 
1044  ws_lexer_free_block(compiler, base);
1045  ws_lexer_free_block(compiler, name);
1046 
1047  return expr;
1048 }
1049 
1050 
1052  char *identifier)
1053 {
1054  WsExpression *expr = expr_alloc(compiler, WS_EXPR_SYMBOL, line);
1055 
1056  if (expr) {
1057  expr->u.symbol = ws_f_strdup(compiler->pool_stree, identifier);
1058  if (expr->u.symbol == NULL)
1059  ws_error_memory(compiler);
1060  }
1061 
1062  ws_lexer_free_block(compiler, identifier);
1063 
1064  return expr;
1065 }
1066 
1067 
1069 {
1070  return expr_alloc(compiler, WS_EXPR_CONST_INVALID, line);
1071 }
1072 
1073 
1075 {
1076  return expr_alloc(compiler, WS_EXPR_CONST_TRUE, line);
1077 }
1078 
1079 
1081 {
1082  return expr_alloc(compiler, WS_EXPR_CONST_FALSE, line);
1083 }
1084 
1085 
1087  WsUInt32 ival)
1088 {
1089  WsExpression *expr = expr_alloc(compiler, WS_EXPR_CONST_INTEGER, line);
1090 
1091  if (expr) {
1092  expr->u.integer.sign = 1;
1093  expr->u.integer.ival = ival;
1094  }
1095 
1096  return expr;
1097 }
1098 
1099 
1101  WsFloat fval)
1102 {
1103  WsExpression *expr = expr_alloc(compiler, WS_EXPR_CONST_FLOAT, line);
1104 
1105  if (expr)
1106  expr->u.fval = fval;
1107 
1108  return expr;
1109 }
1110 
1111 
1113  WsUtf8String *string)
1114 {
1115  WsExpression *expr = expr_alloc(compiler, WS_EXPR_CONST_STRING, line);
1116 
1117  if (expr) {
1118  expr->u.string.len = string->len;
1119  expr->u.string.data = ws_f_memdup(compiler->pool_stree,
1120  string->data, string->len);
1121  if (expr->u.string.data == NULL)
1122  ws_error_memory(compiler);
1123  }
1124 
1125  ws_lexer_free_utf8(compiler, string);
1126 
1127  return expr;
1128 }
1129 
1130 /********************* Statements ***************************************/
1131 
1132 /* Linearize the variable declaration list `list'. */
1133 static void linearize_variable_init(WsCompiler *compiler, WsList *list,
1134  WsUInt32 line)
1135 {
1136  WsNamespace *ns;
1137  WsListItem *li;
1138 
1139  /* For each variable, declared with this list. */
1140  for (li = list->head; li; li = li->next) {
1141  WsVarDec *vardec = li->data;
1142 
1143  ns = ws_variable_define(compiler, line, WS_TRUE, vardec->name);
1144  if (ns && vardec->expr) {
1145  ws_expr_linearize(compiler, vardec->expr);
1146 
1147  /* Emit an instruction to store the initialization
1148  value to the variable. */
1149  ws_asm_link(compiler,
1150  ws_asm_variable(compiler, line, WS_ASM_P_STORE_VAR,
1151  ns->vindex));
1152  }
1153  }
1154 }
1155 
1156 
1158 {
1159  WsListItem *li;
1160  WsAsmIns *ins;
1161 
1162  switch (stmt->type) {
1163  case WS_STMT_BLOCK:
1164  for (li = stmt->u.block->head; li; li = li->next)
1165  ws_stmt_linearize(compiler, li->data);
1166  break;
1167 
1168  case WS_STMT_VARIABLE:
1169  linearize_variable_init(compiler, stmt->u.var, stmt->first_line);
1170  break;
1171 
1172  case WS_STMT_EMPTY:
1173  /* Nothing here. */
1174  break;
1175 
1176  case WS_STMT_EXPR:
1177  ws_expr_linearize(compiler, stmt->u.expr);
1178 
1179  /* Pop the expressions result from the stack. Otherwise loops
1180  could eventually cause stack overflows. */
1181  ws_asm_link(compiler, ws_asm_ins(compiler, stmt->last_line, WS_ASM_POP));
1182  break;
1183 
1184  case WS_STMT_IF:
1185  {
1186  WsAsmIns *l_else = ws_asm_label(compiler,
1187  (stmt->u.s_if.s_else
1188  ? stmt->u.s_if.s_else->first_line
1189  : stmt->last_line));
1190  WsAsmIns *l_end = ws_asm_label(compiler, stmt->last_line);
1191 
1192  /* Linearize the expression. */
1193  ws_expr_linearize(compiler, stmt->u.s_if.expr);
1194 
1195  /* If the result is false, jump to the else-branch. */
1196  ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
1197  WS_ASM_P_TJUMP, l_else));
1198 
1199  /* Else, execute the then-branch and jump to the end. */
1200  ws_stmt_linearize(compiler, stmt->u.s_if.s_then);
1201  ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line,
1202  WS_ASM_P_JUMP, l_end));
1203 
1204  /* Then else-branch. */
1205  ws_asm_link(compiler, l_else);
1206 
1207  /* Linearize the else-branch if it is present. */
1208  if (stmt->u.s_if.s_else)
1209  ws_stmt_linearize(compiler, stmt->u.s_if.s_else);
1210 
1211  /* Insert the end label. */
1212  ws_asm_link(compiler, l_end);
1213  }
1214  break;
1215 
1216  case WS_STMT_FOR:
1217  {
1218  WsAsmIns *l_loop = ws_asm_label(compiler, stmt->first_line);
1219  WsAsmIns *l_cont = ws_asm_label(compiler, stmt->first_line);
1220  WsAsmIns *l_break = ws_asm_label(compiler, stmt->first_line);
1221  WsContBreak *cb;
1222 
1223  /* Store the labels to the compiler. */
1224 
1225  cb = ws_f_calloc(compiler->pool_stree, 1, sizeof(*cb));
1226  if (cb == NULL) {
1227  ws_error_memory(compiler);
1228  return;
1229  }
1230 
1231  cb->next = compiler->cont_break;
1232  compiler->cont_break = cb;
1233 
1234  cb->l_cont = l_cont;
1235  cb->l_break = l_break;
1236 
1237  /* Linearize the possible init code. */
1238  if (stmt->u.s_for.init)
1239  linearize_variable_init(compiler, stmt->u.s_for.init,
1240  stmt->first_line);
1241  else if (stmt->u.s_for.e1) {
1242  /* Linearize the init. */
1243  ws_expr_linearize(compiler, stmt->u.s_for.e1);
1244 
1245  /* Pop the result. */
1246  ws_asm_link(compiler, ws_asm_ins(compiler, stmt->first_line,
1247  WS_ASM_POP));
1248  }
1249 
1250  /* Insert the loop label. */
1251  ws_asm_link(compiler, l_loop);
1252 
1253  /* Linearize the condition. */
1254  if (stmt->u.s_for.e2) {
1255  ws_expr_linearize(compiler, stmt->u.s_for.e2);
1256 
1257  /* If false, jump out. */
1258  ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
1259  WS_ASM_P_TJUMP, l_break));
1260  }
1261 
1262  /* Linearize the body statement. */
1263  ws_stmt_linearize(compiler, stmt->u.s_for.stmt);
1264 
1265  /* Link the continue label. */
1266  ws_asm_link(compiler, l_cont);
1267 
1268  /* Linearize the update expression. */
1269  if (stmt->u.s_for.e3) {
1270  ws_expr_linearize(compiler, stmt->u.s_for.e3);
1271 
1272  /* Pop the result. */
1273  ws_asm_link(compiler, ws_asm_ins(compiler, stmt->first_line,
1274  WS_ASM_POP));
1275  }
1276 
1277  /* Jump to the loop label to check the condition. */
1278  ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line,
1279  WS_ASM_P_JUMP, l_loop));
1280 
1281  /* Insert the break label. */
1282  ws_asm_link(compiler, l_break);
1283 
1284  /* Pop the cont-break block. */
1285  compiler->cont_break = compiler->cont_break->next;
1286  }
1287  break;
1288 
1289  case WS_STMT_WHILE:
1290  {
1291  WsAsmIns *l_cont = ws_asm_label(compiler, stmt->first_line);
1292  WsAsmIns *l_break = ws_asm_label(compiler,
1293  stmt->u.s_while.stmt->last_line);
1294  WsContBreak *cb;
1295 
1296  /* Store the labels to the compiler. */
1297 
1298  cb = ws_f_calloc(compiler->pool_stree, 1, sizeof(*cb));
1299  if (cb == NULL) {
1300  ws_error_memory(compiler);
1301  return;
1302  }
1303 
1304  cb->next = compiler->cont_break;
1305  compiler->cont_break = cb;
1306 
1307  cb->l_cont = l_cont;
1308  cb->l_break = l_break;
1309 
1310  /* Insert the continue label. */
1311  ws_asm_link(compiler, l_cont);
1312 
1313  /* Linearize the expression. */
1314  ws_expr_linearize(compiler, stmt->u.s_while.expr);
1315 
1316  /* If false, jump out. */
1317  ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
1318  WS_ASM_P_TJUMP, l_break));
1319 
1320  /* Linearize the body statement. */
1321  ws_stmt_linearize(compiler, stmt->u.s_while.stmt);
1322 
1323  /* And jump to the continue label to check the expression. */
1324  ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line,
1325  WS_ASM_P_JUMP, l_cont));
1326 
1327  /* Insert the break label. */
1328  ws_asm_link(compiler, l_break);
1329 
1330  /* Pop the cont-break block. */
1331  compiler->cont_break = compiler->cont_break->next;
1332  }
1333  break;
1334 
1335  case WS_STMT_CONTINUE:
1336  if (compiler->cont_break == NULL)
1337  ws_src_error(compiler, stmt->first_line,
1338  "continue statement not within a loop");
1339 
1340  ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
1341  WS_ASM_P_JUMP,
1342  compiler->cont_break->l_cont));
1343  break;
1344 
1345  case WS_STMT_BREAK:
1346  if (compiler->cont_break == NULL)
1347  ws_src_error(compiler, stmt->first_line,
1348  "break statement not within a loop");
1349 
1350  ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
1351  WS_ASM_P_JUMP,
1352  compiler->cont_break->l_break));
1353  break;
1354 
1355  case WS_STMT_RETURN:
1356  if (stmt->u.expr) {
1357  /* Linearize the return value and return it. */
1358  ws_expr_linearize(compiler, stmt->u.expr);
1359  ins = ws_asm_ins(compiler, stmt->first_line, WS_ASM_RETURN);
1360  } else
1361  /* Return an empty string. */
1362  ins = ws_asm_ins(compiler, stmt->first_line, WS_ASM_RETURN_ES);
1363 
1364  ws_asm_link(compiler, ins);
1365  break;
1366  }
1367 }
1368 
1369 
1370 /* Constructors. */
1371 
1373  WsUInt32 first_line, WsUInt32 last_line)
1374 {
1375  WsStatement *stmt = ws_f_calloc(compiler->pool_stree, 1, sizeof(*stmt));
1376 
1377  if (stmt == NULL)
1378  ws_error_memory(compiler);
1379  else {
1380  stmt->type = type;
1381  stmt->first_line = first_line;
1382  stmt->last_line = last_line;
1383  }
1384 
1385  return stmt;
1386 }
1387 
1388 
1390  WsUInt32 lline, WsList *block)
1391 {
1392  WsStatement *stmt = stmt_alloc(compiler, WS_STMT_BLOCK, fline, lline);
1393 
1394  if (stmt)
1395  stmt->u.block = block;
1396 
1397  return stmt;
1398 }
1399 
1400 
1402  WsList *variables)
1403 {
1404  WsStatement *stmt = stmt_alloc(compiler, WS_STMT_VARIABLE, line, line);
1405 
1406  if (stmt)
1407  stmt->u.var = variables;
1408 
1409  return stmt;
1410 }
1411 
1412 
1414 {
1415  return stmt_alloc(compiler, WS_STMT_EMPTY, line, line);
1416 }
1417 
1418 
1420  WsExpression *expr)
1421 {
1422  WsStatement *stmt = stmt_alloc(compiler, WS_STMT_EXPR, line, line);
1423 
1424  if (stmt)
1425  stmt->u.expr = expr;
1426 
1427  return stmt;
1428 }
1429 
1430 
1432  WsExpression *expr, WsStatement *s_then,
1433  WsStatement *s_else)
1434 {
1435  WsStatement *stmt = stmt_alloc(compiler, WS_STMT_IF, line, line);
1436 
1437  if (stmt) {
1438  stmt->u.s_if.expr = expr;
1439  stmt->u.s_if.s_then = s_then;
1440  stmt->u.s_if.s_else = s_else;
1441  }
1442 
1443  return stmt;
1444 }
1445 
1446 
1448  WsExpression *e1, WsExpression *e2, WsExpression *e3,
1449  WsStatement *stmt_body)
1450 {
1451  WsStatement *stmt = stmt_alloc(compiler, WS_STMT_FOR, line, line);
1452 
1453  if (stmt) {
1454  stmt->u.s_for.init = init;
1455  stmt->u.s_for.e1 = e1;
1456  stmt->u.s_for.e2 = e2;
1457  stmt->u.s_for.e3 = e3;
1458  stmt->u.s_for.stmt = stmt_body;
1459  }
1460 
1461  return stmt;
1462 }
1463 
1464 
1466  WsExpression *expr, WsStatement *stmt_arg)
1467 {
1468  WsStatement *stmt = stmt_alloc(compiler, WS_STMT_WHILE, line, line);
1469 
1470  if (stmt) {
1471  stmt->u.s_while.expr = expr;
1472  stmt->u.s_while.stmt = stmt_arg;
1473  }
1474 
1475  return stmt;
1476 }
1477 
1478 
1480 {
1481  return stmt_alloc(compiler, WS_STMT_CONTINUE, line, line);
1482 }
1483 
1484 
1486 {
1487  return stmt_alloc(compiler, WS_STMT_BREAK, line, line);
1488 }
1489 
1490 
1492  WsExpression *expr)
1493 {
1494  WsStatement *stmt = stmt_alloc(compiler, WS_STMT_RETURN, line, line);
1495 
1496  if (stmt)
1497  stmt->u.expr = expr;
1498 
1499  return stmt;
1500 }
WsList * block
Definition: wsstree.h:202
void ws_function(WsCompiler *compiler, WsBool externp, char *name, WsUInt32 line, WsList *params, WsList *block)
Definition: wsstree.c:343
void ws_asm_link(WsCompiler *compiler, WsAsmIns *ins)
Definition: wsasm.c:93
void error(int err, const char *fmt,...)
Definition: log.c:648
void ws_fatal(char *fmt,...)
Definition: wserror.c:91
void * ws_calloc(size_t num, size_t size)
Definition: wsalloc.c:83
WsHashPtr functions_hash
Definition: wsint.h:242
#define WS_ASM_CONST_TRUE
Definition: wsasm.h:175
WsHashPtr pragma_use_hash
Definition: wsint.h:234
struct WsListItemRec * next
Definition: wsstree.h:79
WsStatement * ws_stmt_empty(WsCompiler *compiler, WsUInt32 line)
Definition: wsstree.c:1413
#define WS_ASM_B_RSSHIFT
Definition: wsasm.h:195
Definition: wsint.h:131
WsUInt32 line
Definition: wsstree.h:200
WsList * block
Definition: wsstree.h:529
WsUInt8 vindex
Definition: wsstree.h:119
struct WsStatementRec::@129::@130 s_if
WsUInt32 line
Definition: wsstree.h:116
static void function_hash_destructor(void *item, void *context)
Definition: wsstree.c:306
WsStatement * ws_stmt_for(WsCompilerPtr compiler, WsUInt32 line, WsList *init, WsExpression *e1, WsExpression *e2, WsExpression *e3, WsStatement *stmt_body)
Definition: wsstree.c:1447
WsExpression * ws_expr_postfix_var(WsCompilerPtr compiler, WsUInt32 line, WsBool addp, char *variable)
Definition: wsstree.c:1010
WsExpression * ws_expr_call(WsCompiler *compiler, WsUInt32 line, int type, char *base, char *name, WsList *arguments)
Definition: wsstree.c:1028
WsAsmIns * ws_asm_call_lib(WsCompiler *compiler, WsUInt32 line, WsUInt8 findex, WsUInt16 lindex)
Definition: wsasm.c:867
WsAsmIns * ws_asm_branch(WsCompiler *compiler, WsUInt32 line, WsUInt16 inst, WsAsmIns *label)
Definition: wsasm.c:842
size_t len
Definition: wsutf8.h:81
Definition: parse.c:65
unsigned long WsUInt32
Definition: wsint.h:122
#define tDIVA
Definition: wsgram.c:285
void ws_free(void *ptr)
Definition: wsalloc.c:139
WsStatement * ws_stmt_return(WsCompilerPtr compiler, WsUInt32 line, WsExpression *expr)
Definition: wsstree.c:1491
#define WS_ASM_ADD_ASG
Definition: wsasm.h:180
#define tRSZSHIFTA
Definition: wsgram.c:292
WsBool ws_stdlib_function(const char *library, const char *function, WsUInt16 *lindex_return, WsUInt8 *findex_return, WsUInt8 *num_args_return, WsBool *lindex_found_return, WsBool *findex_found_return)
Definition: wsstdlib.c:341
void ws_pragma_meta_body_free(WsCompilerPtr compiler, WsPragmaMetaBody *mb)
Definition: wsstree.c:291
static WsStatement * stmt_alloc(WsCompiler *compiler, WsStatementType type, WsUInt32 first_line, WsUInt32 last_line)
Definition: wsstree.c:1372
WsStatement * ws_stmt_continue(WsCompiler *compiler, WsUInt32 line)
Definition: wsstree.c:1479
WsUInt32 num_local_functions
Definition: wsint.h:257
WsAsmIns * ws_asm_label(WsCompiler *compiler, WsUInt32 line)
Definition: wsasm.c:831
double WsFloat
Definition: wsint.h:126
void ws_expr_linearize(WsCompiler *compiler, WsExpression *expr)
Definition: wsstree.c:395
unsigned char * data
Definition: wsutf8.h:84
WsUtf8String * scheme
Definition: wsstree.h:178
WsExpression * ws_expr_binary(WsCompilerPtr compiler, WsUInt32 line, int type, WsExpression *left, WsExpression *right)
Definition: wsstree.c:956
int type
Definition: smsc_cimd2.c:215
WsAsmIns * ws_asm_call_url(WsCompiler *compiler, WsUInt32 line, WsUInt16 findex, WsUInt16 urlindex, WsUInt8 args)
Definition: wsasm.c:881
#define WS_INT32_MAX
Definition: wsint.h:109
struct WsContBreakRec * next
Definition: wsint.h:178
#define WS_ASM_RETURN
Definition: wsasm.h:215
struct WsExpressionRec::@118::@123 binary
void * ws_realloc(void *ptr, size_t size)
Definition: wsalloc.c:89
WsExpression * expr
Definition: wsstree.h:531
#define WS_ASM_CONST_INVALID
Definition: wsasm.h:174
WsUInt16 urlindex
Definition: wsstree.h:153
WsUInt32 num_functions
Definition: wsint.h:237
#define tRSSHIFTA
Definition: wsgram.c:291
#define WS_ASM_DIV
Definition: wsasm.h:186
WsListItem * head
Definition: wsstree.h:88
WsUInt32 line
Definition: wsstree.h:149
#define tREMA
Definition: wsgram.c:289
WsList * params
Definition: wsstree.h:201
WsUtf8String * property_name
Definition: wsstree.h:176
WsList * var
Definition: wsstree.h:530
WsVarDec * ws_variable_declaration(WsCompilerPtr compiler, char *name, WsExpression *expr)
Definition: wsstree.c:78
#define WS_ASM_CONST_FALSE
Definition: wsasm.h:176
struct WsExpressionRec::@118::@124 unary
void * ws_f_memdup(WsFastMalloc *pool, const void *ptr, size_t size)
Definition: wsfalloc.c:163
#define tLSHIFTA
Definition: wsgram.c:290
WsStatement * ws_stmt_expr(WsCompiler *compiler, WsUInt32 line, WsExpression *expr)
Definition: wsstree.c:1419
WsStatement * ws_stmt_while(WsCompiler *compiler, WsUInt32 line, WsExpression *expr, WsStatement *stmt_arg)
Definition: wsstree.c:1465
static void linearize_variable_init(WsCompiler *compiler, WsList *list, WsUInt32 line)
Definition: wsstree.c:1133
#define WS_ASM_P_JUMP
Definition: wsasm.h:226
WsAsmIns * ws_asm_load_const(WsCompiler *compiler, WsUInt32 line, WsUInt16 cindex)
Definition: wsasm.c:908
unsigned char WsUInt8
Definition: wsint.h:116
#define WS_ASM_B_LSHIFT
Definition: wsasm.h:194
WsUInt32 last_line
Definition: wsstree.h:525
char * name
Definition: seewbmp.c:156
struct WsStatementRec::@129::@132 s_while
WsBool externp
Definition: wsstree.h:198
WsExpression * ws_expr_const_string(WsCompiler *compiler, WsUInt32 line, WsUtf8String *string)
Definition: wsstree.c:1112
WsAsmIns * l_cont
Definition: wsint.h:179
WsUInt32 next_vindex
Definition: wsint.h:245
#define tIDIVA
Definition: wsgram.c:222
WsPragmaMetaBody * ws_pragma_meta_body(WsCompilerPtr compiler, WsUtf8String *property_name, WsUtf8String *content, WsUtf8String *scheme)
Definition: wsstree.c:271
#define WS_ASM_P_TJUMP
Definition: wsasm.h:227
void ws_lexer_free_block(WsCompiler *compiler, void *ptr)
Definition: ws.c:281
WsExpression * ws_expr_const_float(WsCompiler *compiler, WsUInt32 line, WsFloat fval)
Definition: wsstree.c:1100
WsAsmIns * ws_asm_call(WsCompiler *compiler, WsUInt32 line, WsUInt8 findex)
Definition: wsasm.c:856
struct WsExpressionRec::@118::@126 postfix_var
#define WS_ASM_REM
Definition: wsasm.h:188
void * data
Definition: wsstree.h:80
WsHashPtr ws_pragma_use_hash_create(void)
Definition: wsstree.c:214
WsBc * bc
Definition: wsint.h:218
WsExpression * ws_expr_symbol(WsCompiler *compiler, WsUInt32 line, char *identifier)
Definition: wsstree.c:1051
WsFloat fval
Definition: wsstree.h:384
WsExpression * ws_expr_const_integer(WsCompiler *compiler, WsUInt32 line, WsUInt32 ival)
Definition: wsstree.c:1086
WsExpressionType
Definition: wsstree.h:251
unsigned short WsUInt16
Definition: wsint.h:119
struct WsExpressionRec::@118::@125 unary_var
WsNamespace * ws_variable_lookup(WsCompilerPtr compiler, char *name)
Definition: wsstree.c:199
WsUInt32 line
Definition: wsstree.h:275
WsContBreak * cont_break
Definition: wsint.h:249
WsListItem * tail
Definition: wsstree.h:89
WsFormalParm * ws_formal_parameter(WsCompilerPtr compiler, WsUInt32 line, char *name)
Definition: wsstree.c:93
WsStatement * ws_stmt_break(WsCompiler *compiler, WsUInt32 line)
Definition: wsstree.c:1485
WsStatement * ws_stmt_if(WsCompiler *compiler, WsUInt32 line, WsExpression *expr, WsStatement *s_then, WsStatement *s_else)
Definition: wsstree.c:1431
WsHashPtr ws_function_hash_create(void)
Definition: wsstree.c:312
void * ws_f_strdup(WsFastMalloc *pool, const char *str)
Definition: wsfalloc.c:177
char * name
Definition: smsc_cimd2.c:212
#define tMULA
Definition: wsgram.c:284
#define tSUBA
Definition: wsgram.c:283
struct WsExpressionRec::@118::@122 logical
WsExpression * ws_expr_const_true(WsCompiler *compiler, WsUInt32 line)
Definition: wsstree.c:1074
Definition: seewbmp.c:154
#define WS_ASM_P_LOAD_VAR
Definition: wsasm.h:231
void ws_pragma_use(WsCompilerPtr compiler, WsUInt32 line, char *identifier, WsUtf8String *url)
Definition: wsstree.c:220
WsBool ws_bc_add_const_float(WsBc *bc, WsUInt16 *index_return, WsFloat value)
Definition: wsbc.c:881
static void pragma_use_hash_destructor(void *item, void *context)
Definition: wsstree.c:208
WsAsmIns * ws_asm_variable(WsCompiler *compiler, WsUInt32 line, WsUInt16 inst, WsUInt8 vindex)
Definition: wsasm.c:896
struct WsExpressionRec::@118::@121 conditional
WsUInt32 first_line
Definition: wsstree.h:524
static int init
Definition: gwlib.c:69
WsStatement * ws_stmt_variable(WsCompilerPtr compiler, WsUInt32 line, WsList *variables)
Definition: wsstree.c:1401
WsExpression * ws_expr_unary(WsCompilerPtr compiler, WsUInt32 line, int type, WsExpression *expression)
Definition: wsstree.c:971
static void variable_hash_destructor(void *item, void *context)
Definition: wsstree.c:148
WsBool defined
Definition: wsstree.h:217
WsAsmIns * ws_asm_ins(WsCompiler *compiler, WsUInt32 line, WsUInt8 opcode)
Definition: wsasm.c:920
WsUtf8String string
Definition: wsstree.h:385
WsExpression * ws_expr_logical(WsCompilerPtr compiler, WsUInt32 line, int type, WsExpression *left, WsExpression *right)
Definition: wsstree.c:941
WsStatementType
Definition: wsstree.h:506
WsExpression * expr
Definition: wsstree.h:480
#define WS_ASM_TOBOOL
Definition: wsasm.h:208
WsExpression * ws_expr_const_false(WsCompiler *compiler, WsUInt32 line)
Definition: wsstree.c:1080
#define WS_ASM_B_OR
Definition: wsasm.h:191
WsBool ws_bc_add_const_int(WsBc *bc, WsUInt16 *index_return, WsInt32 value)
Definition: wsbc.c:850
WsHashPtr variables_hash
Definition: wsint.h:246
#define WS_ASM_POP
Definition: wsasm.h:210
WsList * ws_list_new(WsCompiler *compiler)
Definition: wsstree.c:110
#define WS_ASM_B_XOR
Definition: wsasm.h:192
WsFunctionHash * ws_function_hash(WsCompilerPtr compiler, char *name)
Definition: wsstree.c:318
WsBool
Definition: wsint.h:128
#define WS_ASM_CONST_1
Definition: wsasm.h:171
WsStatementType type
Definition: wsstree.h:523
static WsExpression * expr_alloc(WsCompiler *compiler, WsExpressionType type, WsUInt32 line)
Definition: wsstree.c:873
WsUtf8String * content
Definition: wsstree.h:177
WsHashPtr ws_variable_hash_create(void)
Definition: wsstree.c:154
WsFunction * functions
Definition: wsint.h:238
WsBool ws_bc_add_const_utf8_string(WsBc *bc, WsUInt16 *index_return, const unsigned char *data, size_t len)
Definition: wsbc.c:912
WsUInt8 findex
Definition: wsstree.h:197
#define WS_ASM_DECR_VAR
Definition: wsasm.h:164
#define tXORA
Definition: wsgram.c:288
#define WS_ASM_P_STORE_VAR
Definition: wsasm.h:232
#define tORA
Definition: wsgram.c:287
char * symbol
Definition: wsstree.h:379
void * ws_f_calloc(WsFastMalloc *pool, size_t num, size_t size)
Definition: wsfalloc.c:150
WsNamespace * ws_variable_define(WsCompilerPtr compiler, WsUInt32 line, WsBool variablep, char *name)
Definition: wsstree.c:160
WsUInt32 num_extern_functions
Definition: wsint.h:256
WsAsmIns * l_break
Definition: wsint.h:180
WsExpression * ws_expr_const_invalid(WsCompiler *compiler, WsUInt32 line)
Definition: wsstree.c:1068
WsExpression * ws_expr_conditional(WsCompilerPtr compiler, WsUInt32 line, WsExpression *e_cond, WsExpression *e_then, WsExpression *e_else)
Definition: wsstree.c:925
union WsStatementRec::@129 u
WsExpression * ws_expr_comma(WsCompilerPtr compiler, WsUInt32 line, WsExpression *left, WsExpression *right)
Definition: wsstree.c:889
unsigned char * data
Definition: octstr.c:120
#define WS_ASM_B_RSZSHIFT
Definition: wsasm.h:196
signed long WsInt32
Definition: wsint.h:121
union WsExpressionRec::@118 u
long len
Definition: octstr.c:121
#define WS_ASM_SUB_ASG
Definition: wsasm.h:181
WsFastMalloc * pool_stree
Definition: wsint.h:204
WsStatement * ws_stmt_block(WsCompiler *compiler, WsUInt32 fline, WsUInt32 lline, WsList *block)
Definition: wsstree.c:1389
#define WS_ASM_UMINUS
Definition: wsasm.h:182
struct WsExpressionRec::@118::@120 assign
struct WsExpressionRec::@118::@127 call
void ws_lexer_free_utf8(WsCompiler *compiler, WsUtf8String *string)
Definition: ws.c:305
void * ws_f_malloc(WsFastMalloc *pool, size_t size)
Definition: wsfalloc.c:102
#define WS_ASM_P_INCR_VAR
Definition: wsasm.h:233
struct WsExpressionRec::@118::@128 integer
#define tADDA
Definition: wsgram.c:282
static Octstr * content
Definition: mtbatch.c:87
#define WS_ASM_B_AND
Definition: wsasm.h:190
#define WS_ASM_IDIV
Definition: wsasm.h:187
struct WsExpressionRec::@118::@119 comma
#define tANDA
Definition: wsgram.c:286
#define WS_ASM_CONST_0
Definition: wsasm.h:170
#define WS_ASM_MUL
Definition: wsasm.h:185
WsExpression * ws_expr_unary_var(WsCompilerPtr compiler, WsUInt32 line, WsBool addp, char *variable)
Definition: wsstree.c:993
static Octstr * url
Definition: test_xmlrpc.c:84
void ws_src_error(WsCompilerPtr compiler, WsUInt32 line, char *message,...)
Definition: wserror.c:145
struct WsStatementRec::@129::@131 s_for
#define WS_ASM_ADD
Definition: wsasm.h:183
WsBool ws_hash_put(WsHashPtr hash, const char *name, void *data)
Definition: wshash.c:126
char * name
Definition: wsstree.h:199
void * ws_hash_get(WsHashPtr hash, const char *name)
Definition: wshash.c:167
WsExpression * ws_expr_assign(WsCompilerPtr compiler, WsUInt32 line, char *identifier, int op, WsExpression *expr)
Definition: wsstree.c:903
void ws_error_memory(WsCompilerPtr compiler)
Definition: wserror.c:107
#define WS_ASM_CONST_ES
Definition: wsasm.h:173
char * name
Definition: wsstree.h:479
void ws_list_append(WsCompiler *compiler, WsList *list, void *value)
Definition: wsstree.c:121
WsHashPtr ws_hash_create(WsHashItemDestructor destructor, void *context)
Definition: wshash.c:103
#define WS_ASM_RETURN_ES
Definition: wsasm.h:216
WsUInt8 findex
Definition: wsstree.h:220
WsExpressionType type
Definition: wsstree.h:274
void ws_stmt_linearize(WsCompiler *compiler, WsStatement *stmt)
Definition: wsstree.c:1157
#define WS_ASM_SUB
Definition: wsasm.h:184
WsUInt32 num_items
Definition: wsstree.h:90
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.