00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #include "wsint.h"
00072 #include "wsgram.h"
00073
00074
00075
00076
00077
00078 WsVarDec *ws_variable_declaration(WsCompilerPtr compiler,
00079 char *name, WsExpression *expr)
00080 {
00081 WsVarDec *vardec = ws_f_malloc(compiler->pool_stree, sizeof(*vardec));
00082
00083 if (vardec == NULL)
00084 ws_error_memory(compiler);
00085 else {
00086 vardec->name = name;
00087 vardec->expr = expr;
00088 }
00089
00090 return vardec;
00091 }
00092
00093 WsFormalParm *ws_formal_parameter(WsCompilerPtr compiler,
00094 WsUInt32 line, char *name)
00095 {
00096 WsFormalParm *parm = ws_f_malloc(compiler->pool_stree, sizeof(*parm));
00097
00098 if (parm == NULL)
00099 ws_error_memory(compiler);
00100 else {
00101 parm->line = line;
00102 parm->name = name;
00103 }
00104
00105 return parm;
00106 }
00107
00108
00109
00110 WsList *ws_list_new(WsCompiler *compiler)
00111 {
00112 WsList *list = ws_f_calloc(compiler->pool_stree, 1, sizeof(*list));
00113
00114 if (list == NULL)
00115 ws_error_memory(compiler);
00116
00117 return list;
00118 }
00119
00120
00121 void ws_list_append(WsCompiler *compiler, WsList *list, void *value)
00122 {
00123 WsListItem *item;
00124
00125 if (list == NULL)
00126
00127 return;
00128
00129 item = ws_f_calloc(compiler->pool_stree, 1, sizeof(*item));
00130 if (item == NULL) {
00131 ws_error_memory(compiler);
00132 return;
00133 }
00134
00135 item->data = value;
00136
00137 if (list->tail) {
00138 list->tail->next = item;
00139 list->tail = item;
00140 } else
00141 list->head = list->tail = item;
00142
00143 list->num_items++;
00144 }
00145
00146
00147
00148 static void variable_hash_destructor(void *item, void *context)
00149 {
00150 ws_free(item);
00151 }
00152
00153
00154 WsHashPtr ws_variable_hash_create(void)
00155 {
00156 return ws_hash_create(variable_hash_destructor, NULL);
00157 }
00158
00159
00160 WsNamespace *ws_variable_define(WsCompilerPtr compiler, WsUInt32 line,
00161 WsBool variablep, char *name)
00162 {
00163 WsNamespace *ns;
00164
00165
00166 ns = ws_hash_get(compiler->variables_hash, name);
00167 if (ns) {
00168 ws_src_error(compiler, line, "redeclaration of `%s'", name);
00169 ws_src_error(compiler, ns->line, "`%s' previously declared here", name);
00170 return NULL;
00171 }
00172
00173
00174 if (compiler->next_vindex > 255) {
00175
00176 ws_src_error(compiler, line, "too many local variables");
00177 return NULL;
00178 }
00179
00180 ns = ws_calloc(1, sizeof(*ns));
00181 if (ns == NULL) {
00182 ws_error_memory(compiler);
00183 return NULL;
00184 }
00185
00186 ns->line = line;
00187 ns->vindex = compiler->next_vindex++;
00188
00189 if (!ws_hash_put(compiler->variables_hash, name, ns)) {
00190 ws_free(ns);
00191 ws_error_memory(compiler);
00192 return NULL;
00193 }
00194
00195 return ns;
00196 }
00197
00198
00199 WsNamespace *ws_variable_lookup(WsCompilerPtr compiler, char *name)
00200 {
00201 return ws_hash_get(compiler->variables_hash, name);
00202 }
00203
00204
00205
00206
00207
00208 static void pragma_use_hash_destructor(void *item, void *context)
00209 {
00210 ws_free(item);
00211 }
00212
00213
00214 WsHashPtr ws_pragma_use_hash_create(void)
00215 {
00216 return ws_hash_create(pragma_use_hash_destructor, NULL);
00217 }
00218
00219
00220 void ws_pragma_use(WsCompilerPtr compiler, WsUInt32 line, char *identifier,
00221 WsUtf8String *url)
00222 {
00223 WsPragmaUse *u = ws_calloc(1, sizeof(*u));
00224 WsPragmaUse *uold;
00225
00226
00227 uold = ws_hash_get(compiler->pragma_use_hash, identifier);
00228 if (uold) {
00229 ws_src_error(compiler, line, "redefinition of pragma `%s'", identifier);
00230 ws_src_error(compiler, uold->line, "`%s' previously defined here",
00231 identifier);
00232 goto error_cleanup;
00233 }
00234
00235 if (u == NULL)
00236 goto error;
00237
00238 u->line = line;
00239
00240
00241 if (!ws_bc_add_const_utf8_string(compiler->bc, &u->urlindex, url->data,
00242 url->len))
00243 goto error;
00244
00245
00246 if (!ws_hash_put(compiler->pragma_use_hash, identifier, u))
00247 goto error;
00248
00249
00250
00251 ws_lexer_free_block(compiler, identifier);
00252 ws_lexer_free_utf8(compiler, url);
00253
00254 return;
00255
00256
00257
00258 error:
00259
00260 ws_error_memory(compiler);
00261
00262 error_cleanup:
00263
00264 ws_free(u);
00265 ws_lexer_free_block(compiler, identifier);
00266 ws_lexer_free_utf8(compiler, url);
00267 }
00268
00269
00270
00271 WsPragmaMetaBody *ws_pragma_meta_body(WsCompilerPtr compiler,
00272 WsUtf8String *property_name,
00273 WsUtf8String *content,
00274 WsUtf8String *scheme)
00275 {
00276 WsPragmaMetaBody *mb = ws_calloc(1, sizeof(*mb));
00277
00278 if (mb == NULL) {
00279 ws_error_memory(compiler);
00280 return NULL;
00281 }
00282
00283 mb->property_name = property_name;
00284 mb->content = content;
00285 mb->scheme = scheme;
00286
00287 return mb;
00288 }
00289
00290
00291 void ws_pragma_meta_body_free(WsCompilerPtr compiler, WsPragmaMetaBody *mb)
00292 {
00293 if (mb == NULL)
00294 return;
00295
00296 ws_lexer_free_utf8(compiler, mb->property_name);
00297 ws_lexer_free_utf8(compiler, mb->content);
00298 ws_lexer_free_utf8(compiler, mb->scheme);
00299
00300 ws_free(mb);
00301 }
00302
00303
00304
00305
00306 static void function_hash_destructor(void *item, void *context)
00307 {
00308 ws_free(item);
00309 }
00310
00311
00312 WsHashPtr ws_function_hash_create(void)
00313 {
00314 return ws_hash_create(function_hash_destructor, NULL);
00315 }
00316
00317
00318 WsFunctionHash *ws_function_hash(WsCompilerPtr compiler, char *name)
00319 {
00320 WsFunctionHash *i = ws_hash_get(compiler->functions_hash, name);
00321
00322 if (i)
00323 return i;
00324
00325
00326
00327 i = ws_calloc(1, sizeof(*i));
00328 if (i == NULL) {
00329 ws_error_memory(compiler);
00330 return NULL;
00331 }
00332
00333 if (!ws_hash_put(compiler->functions_hash, name, i)) {
00334 ws_free(i);
00335 ws_error_memory(compiler);
00336 return NULL;
00337 }
00338
00339 return i;
00340 }
00341
00342
00343 void ws_function(WsCompiler *compiler, WsBool externp, char *name,
00344 WsUInt32 line, WsList *params, WsList *block)
00345 {
00346 WsFunctionHash *hash;
00347 WsFunction *f = ws_realloc(compiler->functions,
00348 ((compiler->num_functions + 1)
00349 * sizeof(WsFunction)));
00350
00351 if (f == NULL) {
00352 ws_free(name);
00353 ws_error_memory(compiler);
00354 return;
00355 }
00356
00357 if (externp)
00358 compiler->num_extern_functions++;
00359 else
00360 compiler->num_local_functions++;
00361
00362 compiler->functions = f;
00363 f = &compiler->functions[compiler->num_functions];
00364
00365 f->findex = compiler->num_functions++;
00366
00367 f->externp = externp;
00368 f->name = name;
00369 f->line = line;
00370 f->params = params;
00371 f->block = block;
00372
00373
00374
00375 hash = ws_function_hash(compiler, name);
00376 if (hash == NULL) {
00377 ws_error_memory(compiler);
00378 return;
00379 }
00380
00381 if (hash->defined) {
00382 ws_src_error(compiler, line, "redefinition of `%s'", name);
00383 ws_src_error(compiler,
00384 compiler->functions[hash->findex].line,
00385 "`%s' previously defined here", name);
00386 return;
00387 }
00388
00389 hash->defined = WS_TRUE;
00390 hash->findex = f->findex;
00391 }
00392
00393
00394
00395 void ws_expr_linearize(WsCompiler *compiler, WsExpression *expr)
00396 {
00397 WsListItem *li;
00398 WsAsmIns *ins;
00399
00400 switch (expr->type) {
00401 case WS_EXPR_COMMA:
00402
00403 ws_expr_linearize(compiler, expr->u.comma.left);
00404
00405
00406 ws_asm_link(compiler, ws_asm_ins(compiler, expr->line, WS_ASM_POP));
00407
00408
00409 ws_expr_linearize(compiler, expr->u.comma.right);
00410 break;
00411
00412 case WS_EXPR_ASSIGN:
00413 {
00414 WsNamespace *ns = ws_variable_lookup(compiler,
00415 expr->u.assign.identifier);
00416
00417 if (ns == NULL) {
00418
00419 ws_src_error(compiler, expr->line, "unknown variable `%s'",
00420 expr->u.symbol);
00421 return;
00422 }
00423
00424 if (expr->u.assign.op == '=') {
00425
00426 ws_expr_linearize(compiler, expr->u.assign.expr);
00427
00428
00429 ws_asm_link(compiler,
00430 ws_asm_variable(compiler, expr->line,
00431 WS_ASM_P_STORE_VAR, ns->vindex));
00432 } else if (expr->u.assign.op == tADDA) {
00433
00434 ws_expr_linearize(compiler, expr->u.assign.expr);
00435
00436
00437 ws_asm_link(compiler,
00438 ws_asm_variable(compiler, expr->line,
00439 WS_ASM_ADD_ASG, ns->vindex));
00440 } else if (expr->u.assign.op == tSUBA) {
00441
00442 ws_expr_linearize(compiler, expr->u.assign.expr);
00443
00444
00445 ws_asm_link(compiler,
00446 ws_asm_variable(compiler, expr->line,
00447 WS_ASM_SUB_ASG, ns->vindex));
00448 } else {
00449
00450 ws_asm_link(compiler,
00451 ws_asm_variable(compiler, expr->line,
00452 WS_ASM_P_LOAD_VAR, ns->vindex));
00453
00454
00455 ws_expr_linearize(compiler, expr->u.assign.expr);
00456
00457
00458 ins = NULL;
00459 switch (expr->u.assign.op) {
00460 case tMULA:
00461 ins = ws_asm_ins(compiler, expr->line, WS_ASM_MUL);
00462 break;
00463
00464 case tDIVA:
00465 ins = ws_asm_ins(compiler, expr->line, WS_ASM_DIV);
00466 break;
00467
00468 case tREMA:
00469 ins = ws_asm_ins(compiler, expr->line, WS_ASM_REM);
00470 break;
00471
00472 case tADDA:
00473 ins = ws_asm_ins(compiler, expr->line, WS_ASM_ADD);
00474 break;
00475
00476 case tSUBA:
00477 ins = ws_asm_ins(compiler, expr->line, WS_ASM_SUB);
00478 break;
00479
00480 case tLSHIFTA:
00481 ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_LSHIFT);
00482 break;
00483
00484 case tRSSHIFTA:
00485 ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_RSSHIFT);
00486 break;
00487
00488 case tRSZSHIFTA:
00489 ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_RSZSHIFT);
00490 break;
00491
00492 case tANDA:
00493 ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_AND);
00494 break;
00495
00496 case tXORA:
00497 ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_XOR);
00498 break;
00499
00500 case tORA:
00501 ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_OR);
00502 break;
00503
00504 case tIDIVA:
00505 ins = ws_asm_ins(compiler, expr->line, WS_ASM_IDIV);
00506 break;
00507
00508 default:
00509 ws_fatal("ws_expr_linearize(): unknown assignment operand %x",
00510 expr->u.assign.op);
00511 break;
00512 }
00513 ws_asm_link(compiler, ins);
00514
00515
00516 ws_asm_link(compiler,
00517 ws_asm_variable(compiler, expr->line,
00518 WS_ASM_P_STORE_VAR, ns->vindex));
00519 }
00520
00521
00522
00523
00524 ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
00525 WS_ASM_P_LOAD_VAR, ns->vindex));
00526 }
00527 break;
00528
00529 case WS_EXPR_CONDITIONAL:
00530 {
00531 WsAsmIns *l_else = ws_asm_label(compiler, expr->line);
00532 WsAsmIns *l_end = ws_asm_label(compiler, expr->line);
00533
00534
00535 ws_expr_linearize(compiler, expr->u.conditional.e_cond);
00536
00537
00538 ws_asm_link(compiler, ws_asm_branch(compiler, expr->line,
00539 WS_ASM_P_TJUMP, l_else));
00540
00541
00542 ws_expr_linearize(compiler, expr->u.conditional.e_then);
00543 ws_asm_link(compiler, ws_asm_branch(compiler, expr->line,
00544 WS_ASM_P_JUMP, l_end));
00545
00546
00547 ws_asm_link(compiler, l_else);
00548 ws_expr_linearize(compiler, expr->u.conditional.e_else);
00549
00550
00551 ws_asm_link(compiler, l_end);
00552 }
00553 break;
00554
00555 case WS_EXPR_LOGICAL:
00556 {
00557 WsAsmIns *l_out = ws_asm_label(compiler, expr->line);
00558
00559
00560 ws_expr_linearize(compiler, expr->u.logical.left);
00561
00562
00563
00564 ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
00565 expr->u.logical.type));
00566 ws_asm_link(compiler, ws_asm_branch(compiler, expr->line,
00567 WS_ASM_P_TJUMP, l_out));
00568
00569
00570 ws_expr_linearize(compiler, expr->u.logical.right);
00571
00572
00573
00574
00575 ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
00576 WS_ASM_TOBOOL));
00577
00578
00579 ws_asm_link(compiler, l_out);
00580 }
00581 break;
00582
00583 case WS_EXPR_BINARY:
00584
00585 ws_expr_linearize(compiler, expr->u.binary.left);
00586 ws_expr_linearize(compiler, expr->u.binary.right);
00587
00588
00589 ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
00590 expr->u.binary.type));
00591 break;
00592
00593 case WS_EXPR_UNARY:
00594
00595 ws_expr_linearize(compiler, expr->u.unary.expr);
00596
00597
00598 ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
00599 expr->u.unary.type));
00600 break;
00601
00602 case WS_EXPR_UNARY_VAR:
00603 {
00604 WsNamespace *ns = ws_variable_lookup(compiler,
00605 expr->u.unary_var.variable);
00606 if (ns == NULL) {
00607
00608 ws_src_error(compiler, expr->line, "unknown variable `%s'",
00609 expr->u.unary_var.variable);
00610 return;
00611 }
00612
00613
00614 if (expr->u.unary_var.addp)
00615 ws_asm_link(compiler,
00616 ws_asm_variable(compiler, expr->line, WS_ASM_P_INCR_VAR,
00617 ns->vindex));
00618 else
00619 ws_asm_link(compiler,
00620 ws_asm_variable(compiler, expr->line, WS_ASM_DECR_VAR,
00621 ns->vindex));
00622
00623
00624 ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
00625 WS_ASM_P_LOAD_VAR, ns->vindex));
00626 }
00627 break;
00628
00629 case WS_EXPR_POSTFIX_VAR:
00630 {
00631 WsNamespace *ns = ws_variable_lookup(compiler,
00632 expr->u.postfix_var.variable);
00633 if (ns == NULL) {
00634
00635 ws_src_error(compiler, expr->line, "unknown variable `%s'",
00636 expr->u.postfix_var.variable);
00637 return;
00638 }
00639
00640
00641 ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
00642 WS_ASM_P_LOAD_VAR, ns->vindex));
00643
00644
00645 if (expr->u.unary_var.addp)
00646 ws_asm_link(compiler,
00647 ws_asm_variable(compiler, expr->line, WS_ASM_P_INCR_VAR,
00648 ns->vindex));
00649 else
00650 ws_asm_link(compiler,
00651 ws_asm_variable(compiler, expr->line, WS_ASM_DECR_VAR,
00652 ns->vindex));
00653 }
00654 break;
00655
00656 case WS_EXPR_CALL:
00657
00658 for (li = expr->u.call.arguments->head; li; li = li->next)
00659 ws_expr_linearize(compiler, li->data);
00660
00661
00662 switch (expr->u.call.type) {
00663 case ' ':
00664 {
00665 WsFunctionHash *f = ws_function_hash(compiler, expr->u.call.name);
00666
00667 if (f == NULL || !f->defined)
00668 {
00669 ws_src_error(compiler, expr->line,
00670 "unknown local function `%s'",
00671 expr->u.call.name);
00672 return;
00673 }
00674
00675
00676
00677 if (expr->u.call.arguments->num_items
00678 != compiler->functions[f->findex].params->num_items)
00679 {
00680 ws_src_error(compiler, expr->line,
00681 "invalid amount of arguments for `%s': "
00682 "expected %u, got %u",
00683 expr->u.call.name,
00684 compiler->functions[f->findex].params->num_items,
00685 expr->u.call.arguments->num_items);
00686 return;
00687 }
00688
00689
00690 ws_asm_link(compiler, ws_asm_call(compiler, expr->line,
00691 f->findex));
00692 }
00693 break;
00694
00695 case '#':
00696 {
00697 WsPragmaUse *use = ws_hash_get(compiler->pragma_use_hash,
00698 expr->u.call.base);
00699 WsUInt16 findex;
00700
00701 if (use == NULL)
00702 {
00703 ws_src_error(compiler, expr->line,
00704 "unknown external compilation unit `%s'",
00705 expr->u.call.base);
00706 return;
00707 }
00708
00709
00710 if (!ws_bc_add_const_utf8_string(
00711 compiler->bc, &findex,
00712 (unsigned char *) expr->u.call.name,
00713 strlen(expr->u.call.name)))
00714 {
00715 ws_error_memory(compiler);
00716 return;
00717 }
00718
00719
00720 ws_asm_link(compiler,
00721 ws_asm_call_url(compiler, expr->line,
00722 findex, use->urlindex,
00723 expr->u.call.arguments->num_items));
00724 }
00725 break;
00726
00727 case '.':
00728 {
00729 WsUInt16 lindex;
00730 WsUInt8 findex;
00731 WsUInt8 num_args;
00732 WsBool lindex_found;
00733 WsBool findex_found;
00734
00735 if (!ws_stdlib_function(expr->u.call.base, expr->u.call.name,
00736 &lindex, &findex, &num_args,
00737 &lindex_found, &findex_found))
00738 {
00739 if (!lindex_found)
00740 ws_src_error(compiler, expr->line,
00741 "unknown system library `%s'",
00742 expr->u.call.base);
00743 else
00744 ws_src_error(compiler, expr->line,
00745 "unknown library function `%s.%s'",
00746 expr->u.call.base, expr->u.call.name);
00747
00748 return;
00749 }
00750
00751 if (expr->u.call.arguments->num_items != num_args)
00752 {
00753 ws_src_error(compiler, expr->line,
00754 "invalid amount of arguments for `%s.%s': "
00755 "expected %u, got %u",
00756 expr->u.call.base, expr->u.call.name,
00757 num_args, expr->u.call.arguments->num_items);
00758 return;
00759 }
00760
00761
00762 ws_asm_link(compiler, ws_asm_call_lib(compiler, expr->line, findex,
00763 lindex));
00764 }
00765 break;
00766
00767 default:
00768 ws_fatal("ws_expr_linearize(): unknown call expression type %x",
00769 expr->u.call.type);
00770 break;
00771 }
00772 break;
00773
00774 case WS_EXPR_SYMBOL:
00775 {
00776 WsNamespace *ns = ws_variable_lookup(compiler, expr->u.symbol);
00777
00778 if (ns == NULL) {
00779
00780 ws_src_error(compiler, expr->line, "unknown variable `%s'",
00781 expr->u.symbol);
00782 return;
00783 }
00784
00785
00786 ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
00787 WS_ASM_P_LOAD_VAR, ns->vindex));
00788 }
00789 break;
00790
00791 case WS_EXPR_CONST_INVALID:
00792 ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
00793 WS_ASM_CONST_INVALID));
00794 break;
00795
00796 case WS_EXPR_CONST_TRUE:
00797 ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
00798 WS_ASM_CONST_TRUE));
00799 break;
00800
00801 case WS_EXPR_CONST_FALSE:
00802 ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
00803 WS_ASM_CONST_FALSE));
00804 break;
00805
00806
00807 case WS_EXPR_CONST_INTEGER:
00808 if (expr->u.integer.ival == 0)
00809 ins = ws_asm_ins(compiler, expr->line, WS_ASM_CONST_0);
00810 else if (expr->u.integer.ival == 1 && expr->u.integer.sign == 1)
00811 ins = ws_asm_ins(compiler, expr->line, WS_ASM_CONST_1);
00812 else {
00813 WsUInt16 cindex;
00814 WsInt32 ival;
00815
00816 if (expr->u.integer.sign >= 0) {
00817 if (expr->u.integer.ival > (WsUInt32) WS_INT32_MAX)
00818 ws_src_error(compiler, expr->line,
00819 "integer literal too large");
00820 ival = expr->u.integer.ival;
00821 } else {
00822 if (expr->u.integer.ival > (WsUInt32) WS_INT32_MAX + 1)
00823 ws_src_error(compiler, expr->line, "integer too small");
00824 ival = - (WsInt32) expr->u.integer.ival;
00825 }
00826
00827 if (!ws_bc_add_const_int(compiler->bc, &cindex, ival)) {
00828 ws_error_memory(compiler);
00829 return;
00830 }
00831 ins = ws_asm_load_const(compiler, expr->line, cindex);
00832 }
00833
00834 ws_asm_link(compiler, ins);
00835 break;
00836
00837 case WS_EXPR_CONST_FLOAT:
00838 {
00839 WsUInt16 cindex;
00840
00841 if (!ws_bc_add_const_float(compiler->bc, &cindex, expr->u.fval)) {
00842 ws_error_memory(compiler);
00843 return;
00844 }
00845
00846 ws_asm_link(compiler, ws_asm_load_const(compiler, expr->line, cindex));
00847 }
00848 break;
00849
00850 case WS_EXPR_CONST_STRING:
00851 if (expr->u.string.len == 0)
00852 ins = ws_asm_ins(compiler, expr->line, WS_ASM_CONST_ES);
00853 else {
00854 WsUInt16 cindex;
00855
00856 if (!ws_bc_add_const_utf8_string(compiler->bc, &cindex,
00857 expr->u.string.data,
00858 expr->u.string.len)) {
00859 ws_error_memory(compiler);
00860 return;
00861 }
00862 ins = ws_asm_load_const(compiler, expr->line, cindex);
00863 }
00864
00865 ws_asm_link(compiler, ins);
00866 break;
00867 }
00868 }
00869
00870
00871
00872
00873 static WsExpression *expr_alloc(WsCompiler *compiler,
00874 WsExpressionType type, WsUInt32 line)
00875 {
00876 WsExpression *expr = ws_f_calloc(compiler->pool_stree, 1, sizeof(*expr));
00877
00878 if (expr == NULL)
00879 ws_error_memory(compiler);
00880 else {
00881 expr->type = type;
00882 expr->line = line;
00883 }
00884
00885 return expr;
00886 }
00887
00888
00889 WsExpression *ws_expr_comma(WsCompilerPtr compiler, WsUInt32 line,
00890 WsExpression *left, WsExpression *right)
00891 {
00892 WsExpression *expr = expr_alloc(compiler, WS_EXPR_COMMA, line);
00893
00894 if (expr) {
00895 expr->u.comma.left = left;
00896 expr->u.comma.right = right;
00897 }
00898
00899 return expr;
00900 }
00901
00902
00903 WsExpression *ws_expr_assign(WsCompilerPtr compiler, WsUInt32 line,
00904 char *identifier, int op, WsExpression *expr)
00905 {
00906 WsExpression *e = expr_alloc(compiler, WS_EXPR_ASSIGN, line);
00907
00908 if (e) {
00909 e->u.assign.identifier = ws_f_strdup(compiler->pool_stree, identifier);
00910 if (e->u.assign.identifier == NULL)
00911 ws_error_memory(compiler);
00912
00913 e->u.assign.op = op;
00914 e->u.assign.expr = expr;
00915 }
00916
00917
00918
00919 ws_lexer_free_block(compiler, identifier);
00920
00921 return e;
00922 }
00923
00924
00925 WsExpression *ws_expr_conditional(WsCompilerPtr compiler, WsUInt32 line,
00926 WsExpression *e_cond, WsExpression *e_then,
00927 WsExpression *e_else)
00928 {
00929 WsExpression *e = expr_alloc(compiler, WS_EXPR_CONDITIONAL, line);
00930
00931 if (e) {
00932 e->u.conditional.e_cond = e_cond;
00933 e->u.conditional.e_then = e_then;
00934 e->u.conditional.e_else = e_else;
00935 }
00936
00937 return e;
00938 }
00939
00940
00941 WsExpression *ws_expr_logical(WsCompilerPtr compiler, WsUInt32 line,
00942 int type, WsExpression *left, WsExpression *right)
00943 {
00944 WsExpression *expr = expr_alloc(compiler, WS_EXPR_LOGICAL, line);
00945
00946 if (expr) {
00947 expr->u.logical.type = type;
00948 expr->u.logical.left = left;
00949 expr->u.logical.right = right;
00950 }
00951
00952 return expr;
00953 }
00954
00955
00956 WsExpression *ws_expr_binary(WsCompilerPtr compiler, WsUInt32 line,
00957 int type, WsExpression *left, WsExpression *right)
00958 {
00959 WsExpression *expr = expr_alloc(compiler, WS_EXPR_BINARY, line);
00960
00961 if (expr) {
00962 expr->u.binary.type = type;
00963 expr->u.binary.left = left;
00964 expr->u.binary.right = right;
00965 }
00966
00967 return expr;
00968 }
00969
00970
00971 WsExpression *ws_expr_unary(WsCompilerPtr compiler, WsUInt32 line, int type,
00972 WsExpression *expression)
00973 {
00974 WsExpression *expr;
00975
00976
00977
00978 if (type == WS_ASM_UMINUS && expression->type == WS_EXPR_CONST_INTEGER) {
00979 expression->u.integer.sign = - expression->u.integer.sign;
00980 return expression;
00981 }
00982
00983 expr = expr_alloc(compiler, WS_EXPR_UNARY, line);
00984 if (expr) {
00985 expr->u.unary.type = type;
00986 expr->u.unary.expr = expression;
00987 }
00988
00989 return expr;
00990 }
00991
00992
00993 WsExpression *ws_expr_unary_var(WsCompilerPtr compiler, WsUInt32 line,
00994 WsBool addp, char *variable)
00995 {
00996 WsExpression *expr = expr_alloc(compiler, WS_EXPR_UNARY_VAR, line);
00997
00998 if (expr) {
00999 expr->u.unary_var.addp = addp;
01000 expr->u.unary_var.variable = ws_f_strdup(compiler->pool_stree, variable);
01001 if (expr->u.unary_var.variable == NULL)
01002 ws_error_memory(compiler);
01003 }
01004 ws_lexer_free_block(compiler, variable);
01005
01006 return expr;
01007 }
01008
01009
01010 WsExpression *ws_expr_postfix_var(WsCompilerPtr compiler, WsUInt32 line,
01011 WsBool addp, char *variable)
01012 {
01013 WsExpression *expr = expr_alloc(compiler, WS_EXPR_POSTFIX_VAR, line);
01014
01015 if (expr) {
01016 expr->u.postfix_var.addp = addp;
01017 expr->u.postfix_var.variable = ws_f_strdup(compiler->pool_stree,
01018 variable);
01019 if (expr->u.postfix_var.variable == NULL)
01020 ws_error_memory(compiler);
01021 }
01022 ws_lexer_free_block(compiler, variable);
01023
01024 return expr;
01025 }
01026
01027
01028 WsExpression *ws_expr_call(WsCompiler *compiler, WsUInt32 line,
01029 int type, char *base, char *name, WsList *arguments)
01030 {
01031 WsExpression *expr = expr_alloc(compiler, WS_EXPR_CALL, line);
01032
01033 if (expr) {
01034 expr->u.call.type = type;
01035 expr->u.call.base = ws_f_strdup(compiler->pool_stree, base);
01036 expr->u.call.name = ws_f_strdup(compiler->pool_stree, name);
01037 expr->u.call.arguments = arguments;
01038
01039 if ((base && expr->u.call.base == NULL)
01040 || (name && expr->u.call.name == NULL))
01041 ws_error_memory(compiler);
01042 }
01043
01044 ws_lexer_free_block(compiler, base);
01045 ws_lexer_free_block(compiler, name);
01046
01047 return expr;
01048 }
01049
01050
01051 WsExpression *ws_expr_symbol(WsCompiler *compiler, WsUInt32 line,
01052 char *identifier)
01053 {
01054 WsExpression *expr = expr_alloc(compiler, WS_EXPR_SYMBOL, line);
01055
01056 if (expr) {
01057 expr->u.symbol = ws_f_strdup(compiler->pool_stree, identifier);
01058 if (expr->u.symbol == NULL)
01059 ws_error_memory(compiler);
01060 }
01061
01062 ws_lexer_free_block(compiler, identifier);
01063
01064 return expr;
01065 }
01066
01067
01068 WsExpression *ws_expr_const_invalid(WsCompiler *compiler, WsUInt32 line)
01069 {
01070 return expr_alloc(compiler, WS_EXPR_CONST_INVALID, line);
01071 }
01072
01073
01074 WsExpression *ws_expr_const_true(WsCompiler *compiler, WsUInt32 line)
01075 {
01076 return expr_alloc(compiler, WS_EXPR_CONST_TRUE, line);
01077 }
01078
01079
01080 WsExpression *ws_expr_const_false(WsCompiler *compiler, WsUInt32 line)
01081 {
01082 return expr_alloc(compiler, WS_EXPR_CONST_FALSE, line);
01083 }
01084
01085
01086 WsExpression *ws_expr_const_integer(WsCompiler *compiler, WsUInt32 line,
01087 WsUInt32 ival)
01088 {
01089 WsExpression *expr = expr_alloc(compiler, WS_EXPR_CONST_INTEGER, line);
01090
01091 if (expr) {
01092 expr->u.integer.sign = 1;
01093 expr->u.integer.ival = ival;
01094 }
01095
01096 return expr;
01097 }
01098
01099
01100 WsExpression *ws_expr_const_float(WsCompiler *compiler, WsUInt32 line,
01101 WsFloat fval)
01102 {
01103 WsExpression *expr = expr_alloc(compiler, WS_EXPR_CONST_FLOAT, line);
01104
01105 if (expr)
01106 expr->u.fval = fval;
01107
01108 return expr;
01109 }
01110
01111
01112 WsExpression *ws_expr_const_string(WsCompiler *compiler, WsUInt32 line,
01113 WsUtf8String *string)
01114 {
01115 WsExpression *expr = expr_alloc(compiler, WS_EXPR_CONST_STRING, line);
01116
01117 if (expr) {
01118 expr->u.string.len = string->len;
01119 expr->u.string.data = ws_f_memdup(compiler->pool_stree,
01120 string->data, string->len);
01121 if (expr->u.string.data == NULL)
01122 ws_error_memory(compiler);
01123 }
01124
01125 ws_lexer_free_utf8(compiler, string);
01126
01127 return expr;
01128 }
01129
01130
01131
01132
01133 static void linearize_variable_init(WsCompiler *compiler, WsList *list,
01134 WsUInt32 line)
01135 {
01136 WsNamespace *ns;
01137 WsListItem *li;
01138
01139
01140 for (li = list->head; li; li = li->next) {
01141 WsVarDec *vardec = li->data;
01142
01143 ns = ws_variable_define(compiler, line, WS_TRUE, vardec->name);
01144 if (ns && vardec->expr) {
01145 ws_expr_linearize(compiler, vardec->expr);
01146
01147
01148
01149 ws_asm_link(compiler,
01150 ws_asm_variable(compiler, line, WS_ASM_P_STORE_VAR,
01151 ns->vindex));
01152 }
01153 }
01154 }
01155
01156
01157 void ws_stmt_linearize(WsCompiler *compiler, WsStatement *stmt)
01158 {
01159 WsListItem *li;
01160 WsAsmIns *ins;
01161
01162 switch (stmt->type) {
01163 case WS_STMT_BLOCK:
01164 for (li = stmt->u.block->head; li; li = li->next)
01165 ws_stmt_linearize(compiler, li->data);
01166 break;
01167
01168 case WS_STMT_VARIABLE:
01169 linearize_variable_init(compiler, stmt->u.var, stmt->first_line);
01170 break;
01171
01172 case WS_STMT_EMPTY:
01173
01174 break;
01175
01176 case WS_STMT_EXPR:
01177 ws_expr_linearize(compiler, stmt->u.expr);
01178
01179
01180
01181 ws_asm_link(compiler, ws_asm_ins(compiler, stmt->last_line, WS_ASM_POP));
01182 break;
01183
01184 case WS_STMT_IF:
01185 {
01186 WsAsmIns *l_else = ws_asm_label(compiler,
01187 (stmt->u.s_if.s_else
01188 ? stmt->u.s_if.s_else->first_line
01189 : stmt->last_line));
01190 WsAsmIns *l_end = ws_asm_label(compiler, stmt->last_line);
01191
01192
01193 ws_expr_linearize(compiler, stmt->u.s_if.expr);
01194
01195
01196 ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
01197 WS_ASM_P_TJUMP, l_else));
01198
01199
01200 ws_stmt_linearize(compiler, stmt->u.s_if.s_then);
01201 ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line,
01202 WS_ASM_P_JUMP, l_end));
01203
01204
01205 ws_asm_link(compiler, l_else);
01206
01207
01208 if (stmt->u.s_if.s_else)
01209 ws_stmt_linearize(compiler, stmt->u.s_if.s_else);
01210
01211
01212 ws_asm_link(compiler, l_end);
01213 }
01214 break;
01215
01216 case WS_STMT_FOR:
01217 {
01218 WsAsmIns *l_loop = ws_asm_label(compiler, stmt->first_line);
01219 WsAsmIns *l_cont = ws_asm_label(compiler, stmt->first_line);
01220 WsAsmIns *l_break = ws_asm_label(compiler, stmt->first_line);
01221 WsContBreak *cb;
01222
01223
01224
01225 cb = ws_f_calloc(compiler->pool_stree, 1, sizeof(*cb));
01226 if (cb == NULL) {
01227 ws_error_memory(compiler);
01228 return;
01229 }
01230
01231 cb->next = compiler->cont_break;
01232 compiler->cont_break = cb;
01233
01234 cb->l_cont = l_cont;
01235 cb->l_break = l_break;
01236
01237
01238 if (stmt->u.s_for.init)
01239 linearize_variable_init(compiler, stmt->u.s_for.init,
01240 stmt->first_line);
01241 else if (stmt->u.s_for.e1) {
01242
01243 ws_expr_linearize(compiler, stmt->u.s_for.e1);
01244
01245
01246 ws_asm_link(compiler, ws_asm_ins(compiler, stmt->first_line,
01247 WS_ASM_POP));
01248 }
01249
01250
01251 ws_asm_link(compiler, l_loop);
01252
01253
01254 if (stmt->u.s_for.e2) {
01255 ws_expr_linearize(compiler, stmt->u.s_for.e2);
01256
01257
01258 ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
01259 WS_ASM_P_TJUMP, l_break));
01260 }
01261
01262
01263 ws_stmt_linearize(compiler, stmt->u.s_for.stmt);
01264
01265
01266 ws_asm_link(compiler, l_cont);
01267
01268
01269 if (stmt->u.s_for.e3) {
01270 ws_expr_linearize(compiler, stmt->u.s_for.e3);
01271
01272
01273 ws_asm_link(compiler, ws_asm_ins(compiler, stmt->first_line,
01274 WS_ASM_POP));
01275 }
01276
01277
01278 ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line,
01279 WS_ASM_P_JUMP, l_loop));
01280
01281
01282 ws_asm_link(compiler, l_break);
01283
01284
01285 compiler->cont_break = compiler->cont_break->next;
01286 }
01287 break;
01288
01289 case WS_STMT_WHILE:
01290 {
01291 WsAsmIns *l_cont = ws_asm_label(compiler, stmt->first_line);
01292 WsAsmIns *l_break = ws_asm_label(compiler,
01293 stmt->u.s_while.stmt->last_line);
01294 WsContBreak *cb;
01295
01296
01297
01298 cb = ws_f_calloc(compiler->pool_stree, 1, sizeof(*cb));
01299 if (cb == NULL) {
01300 ws_error_memory(compiler);
01301 return;
01302 }
01303
01304 cb->next = compiler->cont_break;
01305 compiler->cont_break = cb;
01306
01307 cb->l_cont = l_cont;
01308 cb->l_break = l_break;
01309
01310
01311 ws_asm_link(compiler, l_cont);
01312
01313
01314 ws_expr_linearize(compiler, stmt->u.s_while.expr);
01315
01316
01317 ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
01318 WS_ASM_P_TJUMP, l_break));
01319
01320
01321 ws_stmt_linearize(compiler, stmt->u.s_while.stmt);
01322
01323
01324 ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line,
01325 WS_ASM_P_JUMP, l_cont));
01326
01327
01328 ws_asm_link(compiler, l_break);
01329
01330
01331 compiler->cont_break = compiler->cont_break->next;
01332 }
01333 break;
01334
01335 case WS_STMT_CONTINUE:
01336 if (compiler->cont_break == NULL)
01337 ws_src_error(compiler, stmt->first_line,
01338 "continue statement not within a loop");
01339
01340 ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
01341 WS_ASM_P_JUMP,
01342 compiler->cont_break->l_cont));
01343 break;
01344
01345 case WS_STMT_BREAK:
01346 if (compiler->cont_break == NULL)
01347 ws_src_error(compiler, stmt->first_line,
01348 "break statement not within a loop");
01349
01350 ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,
01351 WS_ASM_P_JUMP,
01352 compiler->cont_break->l_break));
01353 break;
01354
01355 case WS_STMT_RETURN:
01356 if (stmt->u.expr) {
01357
01358 ws_expr_linearize(compiler, stmt->u.expr);
01359 ins = ws_asm_ins(compiler, stmt->first_line, WS_ASM_RETURN);
01360 } else
01361
01362 ins = ws_asm_ins(compiler, stmt->first_line, WS_ASM_RETURN_ES);
01363
01364 ws_asm_link(compiler, ins);
01365 break;
01366 }
01367 }
01368
01369
01370
01371
01372 static WsStatement *stmt_alloc(WsCompiler *compiler, WsStatementType type,
01373 WsUInt32 first_line, WsUInt32 last_line)
01374 {
01375 WsStatement *stmt = ws_f_calloc(compiler->pool_stree, 1, sizeof(*stmt));
01376
01377 if (stmt == NULL)
01378 ws_error_memory(compiler);
01379 else {
01380 stmt->type = type;
01381 stmt->first_line = first_line;
01382 stmt->last_line = last_line;
01383 }
01384
01385 return stmt;
01386 }
01387
01388
01389 WsStatement *ws_stmt_block(WsCompiler *compiler, WsUInt32 fline,
01390 WsUInt32 lline, WsList *block)
01391 {
01392 WsStatement *stmt = stmt_alloc(compiler, WS_STMT_BLOCK, fline, lline);
01393
01394 if (stmt)
01395 stmt->u.block = block;
01396
01397 return stmt;
01398 }
01399
01400
01401 WsStatement *ws_stmt_variable(WsCompilerPtr compiler, WsUInt32 line,
01402 WsList *variables)
01403 {
01404 WsStatement *stmt = stmt_alloc(compiler, WS_STMT_VARIABLE, line, line);
01405
01406 if (stmt)
01407 stmt->u.var = variables;
01408
01409 return stmt;
01410 }
01411
01412
01413 WsStatement *ws_stmt_empty(WsCompiler *compiler, WsUInt32 line)
01414 {
01415 return stmt_alloc(compiler, WS_STMT_EMPTY, line, line);
01416 }
01417
01418
01419 WsStatement *ws_stmt_expr(WsCompiler *compiler, WsUInt32 line,
01420 WsExpression *expr)
01421 {
01422 WsStatement *stmt = stmt_alloc(compiler, WS_STMT_EXPR, line, line);
01423
01424 if (stmt)
01425 stmt->u.expr = expr;
01426
01427 return stmt;
01428 }
01429
01430
01431 WsStatement *ws_stmt_if(WsCompiler *compiler, WsUInt32 line,
01432 WsExpression *expr, WsStatement *s_then,
01433 WsStatement *s_else)
01434 {
01435 WsStatement *stmt = stmt_alloc(compiler, WS_STMT_IF, line, line);
01436
01437 if (stmt) {
01438 stmt->u.s_if.expr = expr;
01439 stmt->u.s_if.s_then = s_then;
01440 stmt->u.s_if.s_else = s_else;
01441 }
01442
01443 return stmt;
01444 }
01445
01446
01447 WsStatement *ws_stmt_for(WsCompilerPtr compiler, WsUInt32 line, WsList *init,
01448 WsExpression *e1, WsExpression *e2, WsExpression *e3,
01449 WsStatement *stmt_body)
01450 {
01451 WsStatement *stmt = stmt_alloc(compiler, WS_STMT_FOR, line, line);
01452
01453 if (stmt) {
01454 stmt->u.s_for.init = init;
01455 stmt->u.s_for.e1 = e1;
01456 stmt->u.s_for.e2 = e2;
01457 stmt->u.s_for.e3 = e3;
01458 stmt->u.s_for.stmt = stmt_body;
01459 }
01460
01461 return stmt;
01462 }
01463
01464
01465 WsStatement *ws_stmt_while(WsCompiler *compiler, WsUInt32 line,
01466 WsExpression *expr, WsStatement *stmt_arg)
01467 {
01468 WsStatement *stmt = stmt_alloc(compiler, WS_STMT_WHILE, line, line);
01469
01470 if (stmt) {
01471 stmt->u.s_while.expr = expr;
01472 stmt->u.s_while.stmt = stmt_arg;
01473 }
01474
01475 return stmt;
01476 }
01477
01478
01479 WsStatement *ws_stmt_continue(WsCompiler *compiler, WsUInt32 line)
01480 {
01481 return stmt_alloc(compiler, WS_STMT_CONTINUE, line, line);
01482 }
01483
01484
01485 WsStatement *ws_stmt_break(WsCompiler *compiler, WsUInt32 line)
01486 {
01487 return stmt_alloc(compiler, WS_STMT_BREAK, line, line);
01488 }
01489
01490
01491 WsStatement *ws_stmt_return(WsCompilerPtr compiler, WsUInt32 line,
01492 WsExpression *expr)
01493 {
01494 WsStatement *stmt = stmt_alloc(compiler, WS_STMT_RETURN, line, line);
01495
01496 if (stmt)
01497 stmt->u.expr = expr;
01498
01499 return stmt;
01500 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.