22 |
#include "instrument-js.h" |
#include "instrument-js.h" |
23 |
|
|
24 |
#include <assert.h> |
#include <assert.h> |
25 |
|
#include <math.h> |
26 |
#include <stdlib.h> |
#include <stdlib.h> |
27 |
#include <string.h> |
#include <string.h> |
28 |
|
|
268 |
} |
} |
269 |
} |
} |
270 |
|
|
271 |
static void instrument_expression(JSParseNode * node, Stream * f); |
static void output_expression(JSParseNode * node, Stream * f, bool parenthesize_object_literals); |
272 |
static void instrument_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if); |
static void instrument_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if); |
273 |
static void output_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if); |
static void output_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if); |
274 |
|
|
285 |
Stream_write_string(f, "each "); |
Stream_write_string(f, "each "); |
286 |
} |
} |
287 |
Stream_write_char(f, '('); |
Stream_write_char(f, '('); |
288 |
instrument_expression(node->pn_left, f); |
output_expression(node->pn_left, f, false); |
289 |
Stream_write_char(f, ')'); |
Stream_write_char(f, ')'); |
290 |
} |
} |
291 |
|
|
312 |
p = p->pn_kid; |
p = p->pn_kid; |
313 |
} |
} |
314 |
|
|
315 |
instrument_expression(p, f); |
output_expression(p, f, false); |
316 |
p = for_node; |
p = for_node; |
317 |
while (p->pn_type == TOK_FOR) { |
while (p->pn_type == TOK_FOR) { |
318 |
Stream_write_char(f, ' '); |
Stream_write_char(f, ' '); |
321 |
} |
} |
322 |
if (if_node) { |
if (if_node) { |
323 |
Stream_write_string(f, " if ("); |
Stream_write_string(f, " if ("); |
324 |
instrument_expression(if_node->pn_kid1, f); |
output_expression(if_node->pn_kid1, f, false); |
325 |
Stream_write_char(f, ')'); |
Stream_write_char(f, ')'); |
326 |
} |
} |
327 |
} |
} |
382 |
} |
} |
383 |
} |
} |
384 |
assert(expression != NULL); |
assert(expression != NULL); |
385 |
instrument_expression(expression, f); |
output_expression(expression, f, false); |
386 |
} |
} |
387 |
else { |
else { |
388 |
print_string_atom(param, f); |
print_string_atom(param, f); |
415 |
} |
} |
416 |
} |
} |
417 |
|
|
418 |
Stream_write_string(f, "}\n"); |
Stream_write_char(f, '}'); |
419 |
} |
} |
420 |
|
|
421 |
static void instrument_function_call(JSParseNode * node, Stream * f) { |
static void instrument_function_call(JSParseNode * node, Stream * f) { |
434 |
Stream_write_char(f, ')'); |
Stream_write_char(f, ')'); |
435 |
return; |
return; |
436 |
} |
} |
|
else { |
|
|
Stream_write_char(f, '('); |
|
|
instrument_expression(function_node, f); |
|
|
Stream_write_char(f, ')'); |
|
|
} |
|
|
} |
|
|
else { |
|
|
instrument_expression(function_node, f); |
|
437 |
} |
} |
438 |
|
output_expression(function_node, f, false); |
439 |
Stream_write_char(f, '('); |
Stream_write_char(f, '('); |
440 |
for (struct JSParseNode * p = function_node->pn_next; p != NULL; p = p->pn_next) { |
for (struct JSParseNode * p = function_node->pn_next; p != NULL; p = p->pn_next) { |
441 |
if (p != node->pn_head->pn_next) { |
if (p != node->pn_head->pn_next) { |
442 |
Stream_write_string(f, ", "); |
Stream_write_string(f, ", "); |
443 |
} |
} |
444 |
instrument_expression(p, f); |
output_expression(p, f, false); |
445 |
} |
} |
446 |
Stream_write_char(f, ')'); |
Stream_write_char(f, ')'); |
447 |
} |
} |
449 |
static void instrument_declarations(JSParseNode * list, Stream * f) { |
static void instrument_declarations(JSParseNode * list, Stream * f) { |
450 |
assert(list->pn_arity == PN_LIST); |
assert(list->pn_arity == PN_LIST); |
451 |
for (JSParseNode * p = list->pn_head; p != NULL; p = p->pn_next) { |
for (JSParseNode * p = list->pn_head; p != NULL; p = p->pn_next) { |
452 |
switch (p->pn_type) { |
if (p != list->pn_head) { |
453 |
case TOK_NAME: |
Stream_write_string(f, ", "); |
|
assert(p->pn_arity == PN_NAME); |
|
|
if (p != list->pn_head) { |
|
|
Stream_write_string(f, ", "); |
|
|
} |
|
|
print_string_atom(p->pn_atom, f); |
|
|
if (p->pn_expr != NULL) { |
|
|
Stream_write_string(f, " = "); |
|
|
instrument_expression(p->pn_expr, f); |
|
|
} |
|
|
break; |
|
|
case TOK_ASSIGN: |
|
|
case TOK_RB: |
|
|
case TOK_RC: |
|
|
/* destructuring */ |
|
|
instrument_expression(p, f); |
|
|
break; |
|
|
default: |
|
|
abort(); |
|
|
break; |
|
454 |
} |
} |
455 |
|
output_expression(p, f, false); |
456 |
} |
} |
457 |
} |
} |
458 |
|
|
469 |
TOK_INSTANCEOF binary |
TOK_INSTANCEOF binary |
470 |
TOK_IN binary |
TOK_IN binary |
471 |
*/ |
*/ |
472 |
static void instrument_expression(JSParseNode * node, Stream * f) { |
static void output_expression(JSParseNode * node, Stream * f, bool parenthesize_object_literals) { |
473 |
switch (node->pn_type) { |
switch (node->pn_type) { |
474 |
case TOK_FUNCTION: |
case TOK_FUNCTION: |
475 |
|
Stream_write_char(f, '('); |
476 |
instrument_function(node, f, 0, FUNCTION_NORMAL); |
instrument_function(node, f, 0, FUNCTION_NORMAL); |
477 |
|
Stream_write_char(f, ')'); |
478 |
break; |
break; |
479 |
case TOK_COMMA: |
case TOK_COMMA: |
480 |
for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) { |
for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) { |
481 |
if (p != node->pn_head) { |
if (p != node->pn_head) { |
482 |
Stream_write_string(f, ", "); |
Stream_write_string(f, ", "); |
483 |
} |
} |
484 |
instrument_expression(p, f); |
output_expression(p, f, parenthesize_object_literals); |
485 |
} |
} |
486 |
break; |
break; |
487 |
case TOK_ASSIGN: |
case TOK_ASSIGN: |
488 |
instrument_expression(node->pn_left, f); |
output_expression(node->pn_left, f, parenthesize_object_literals); |
489 |
Stream_write_char(f, ' '); |
Stream_write_char(f, ' '); |
490 |
switch (node->pn_op) { |
switch (node->pn_op) { |
491 |
case JSOP_ADD: |
case JSOP_ADD: |
506 |
break; |
break; |
507 |
} |
} |
508 |
Stream_write_string(f, "= "); |
Stream_write_string(f, "= "); |
509 |
instrument_expression(node->pn_right, f); |
output_expression(node->pn_right, f, false); |
510 |
break; |
break; |
511 |
case TOK_HOOK: |
case TOK_HOOK: |
512 |
instrument_expression(node->pn_kid1, f); |
output_expression(node->pn_kid1, f, parenthesize_object_literals); |
513 |
Stream_write_string(f, "? "); |
Stream_write_string(f, "? "); |
514 |
instrument_expression(node->pn_kid2, f); |
output_expression(node->pn_kid2, f, false); |
515 |
Stream_write_string(f, ": "); |
Stream_write_string(f, ": "); |
516 |
instrument_expression(node->pn_kid3, f); |
output_expression(node->pn_kid3, f, false); |
517 |
break; |
break; |
518 |
case TOK_OR: |
case TOK_OR: |
519 |
case TOK_AND: |
case TOK_AND: |
529 |
case TOK_DIVOP: |
case TOK_DIVOP: |
530 |
switch (node->pn_arity) { |
switch (node->pn_arity) { |
531 |
case PN_BINARY: |
case PN_BINARY: |
532 |
instrument_expression(node->pn_left, f); |
output_expression(node->pn_left, f, parenthesize_object_literals); |
533 |
Stream_printf(f, " %s ", get_op(node->pn_op)); |
Stream_printf(f, " %s ", get_op(node->pn_op)); |
534 |
instrument_expression(node->pn_right, f); |
output_expression(node->pn_right, f, false); |
535 |
break; |
break; |
536 |
case PN_LIST: |
case PN_LIST: |
537 |
for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) { |
for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) { |
538 |
if (p != node->pn_head) { |
if (p == node->pn_head) { |
539 |
|
output_expression(p, f, parenthesize_object_literals); |
540 |
|
} |
541 |
|
else { |
542 |
Stream_printf(f, " %s ", get_op(node->pn_op)); |
Stream_printf(f, " %s ", get_op(node->pn_op)); |
543 |
|
output_expression(p, f, false); |
544 |
} |
} |
|
instrument_expression(p, f); |
|
545 |
} |
} |
546 |
break; |
break; |
547 |
default: |
default: |
551 |
case TOK_UNARYOP: |
case TOK_UNARYOP: |
552 |
switch (node->pn_op) { |
switch (node->pn_op) { |
553 |
case JSOP_NEG: |
case JSOP_NEG: |
554 |
Stream_write_char(f, '-'); |
Stream_write_string(f, "- "); |
555 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
556 |
break; |
break; |
557 |
case JSOP_POS: |
case JSOP_POS: |
558 |
Stream_write_char(f, '+'); |
Stream_write_string(f, "+ "); |
559 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
560 |
break; |
break; |
561 |
case JSOP_NOT: |
case JSOP_NOT: |
562 |
Stream_write_char(f, '!'); |
Stream_write_string(f, "! "); |
563 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
564 |
break; |
break; |
565 |
case JSOP_BITNOT: |
case JSOP_BITNOT: |
566 |
Stream_write_char(f, '~'); |
Stream_write_string(f, "~ "); |
567 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
568 |
break; |
break; |
569 |
case JSOP_TYPEOF: |
case JSOP_TYPEOF: |
570 |
Stream_write_string(f, "typeof "); |
Stream_write_string(f, "typeof "); |
571 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
572 |
break; |
break; |
573 |
case JSOP_VOID: |
case JSOP_VOID: |
574 |
Stream_write_string(f, "void "); |
Stream_write_string(f, "void "); |
575 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
576 |
break; |
break; |
577 |
default: |
default: |
578 |
fatal_source(file_id, node->pn_pos.begin.lineno, "unknown operator (%d)", node->pn_op); |
fatal_source(file_id, node->pn_pos.begin.lineno, "unknown operator (%d)", node->pn_op); |
589 |
case JSOP_INCPROP: |
case JSOP_INCPROP: |
590 |
case JSOP_INCELEM: |
case JSOP_INCELEM: |
591 |
Stream_write_string(f, "++"); |
Stream_write_string(f, "++"); |
592 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
593 |
break; |
break; |
594 |
case JSOP_DECNAME: |
case JSOP_DECNAME: |
595 |
case JSOP_DECPROP: |
case JSOP_DECPROP: |
596 |
case JSOP_DECELEM: |
case JSOP_DECELEM: |
597 |
Stream_write_string(f, "--"); |
Stream_write_string(f, "--"); |
598 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
599 |
break; |
break; |
600 |
case JSOP_NAMEINC: |
case JSOP_NAMEINC: |
601 |
case JSOP_PROPINC: |
case JSOP_PROPINC: |
602 |
case JSOP_ELEMINC: |
case JSOP_ELEMINC: |
603 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, parenthesize_object_literals); |
604 |
Stream_write_string(f, "++"); |
Stream_write_string(f, "++"); |
605 |
break; |
break; |
606 |
case JSOP_NAMEDEC: |
case JSOP_NAMEDEC: |
607 |
case JSOP_PROPDEC: |
case JSOP_PROPDEC: |
608 |
case JSOP_ELEMDEC: |
case JSOP_ELEMDEC: |
609 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, parenthesize_object_literals); |
610 |
Stream_write_string(f, "--"); |
Stream_write_string(f, "--"); |
611 |
break; |
break; |
612 |
default: |
default: |
620 |
break; |
break; |
621 |
case TOK_DELETE: |
case TOK_DELETE: |
622 |
Stream_write_string(f, "delete "); |
Stream_write_string(f, "delete "); |
623 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
624 |
break; |
break; |
625 |
case TOK_DOT: |
case TOK_DOT: |
626 |
|
/* numeric literals must be parenthesized */ |
627 |
|
switch (node->pn_expr->pn_type) { |
628 |
|
case TOK_NUMBER: |
629 |
|
Stream_write_char(f, '('); |
630 |
|
output_expression(node->pn_expr, f, false); |
631 |
|
Stream_write_char(f, ')'); |
632 |
|
break; |
633 |
|
default: |
634 |
|
output_expression(node->pn_expr, f, true); |
635 |
|
break; |
636 |
|
} |
637 |
/* |
/* |
638 |
This may have originally been x['foo-bar']. Because the string 'foo-bar' |
This may have originally been x['foo-bar']. Because the string 'foo-bar' |
639 |
contains illegal characters, we have to use the subscript syntax instead of |
contains illegal characters, we have to use the subscript syntax instead of |
640 |
the dot syntax. |
the dot syntax. |
641 |
*/ |
*/ |
|
instrument_expression(node->pn_expr, f); |
|
642 |
assert(ATOM_IS_STRING(node->pn_atom)); |
assert(ATOM_IS_STRING(node->pn_atom)); |
643 |
{ |
{ |
644 |
JSString * s = ATOM_TO_STRING(node->pn_atom); |
JSString * s = ATOM_TO_STRING(node->pn_atom); |
667 |
} |
} |
668 |
break; |
break; |
669 |
case TOK_LB: |
case TOK_LB: |
670 |
instrument_expression(node->pn_left, f); |
output_expression(node->pn_left, f, false); |
671 |
Stream_write_char(f, '['); |
Stream_write_char(f, '['); |
672 |
instrument_expression(node->pn_right, f); |
output_expression(node->pn_right, f, false); |
673 |
Stream_write_char(f, ']'); |
Stream_write_char(f, ']'); |
674 |
break; |
break; |
675 |
case TOK_LP: |
case TOK_LP: |
683 |
} |
} |
684 |
/* TOK_COMMA is a special case: a hole in the array */ |
/* TOK_COMMA is a special case: a hole in the array */ |
685 |
if (p->pn_type != TOK_COMMA) { |
if (p->pn_type != TOK_COMMA) { |
686 |
instrument_expression(p, f); |
output_expression(p, f, false); |
687 |
} |
} |
688 |
} |
} |
689 |
if (node->pn_extra == PNX_ENDCOMMA) { |
if (node->pn_extra == PNX_ENDCOMMA) { |
692 |
Stream_write_char(f, ']'); |
Stream_write_char(f, ']'); |
693 |
break; |
break; |
694 |
case TOK_RC: |
case TOK_RC: |
695 |
|
if (parenthesize_object_literals) { |
696 |
|
Stream_write_char(f, '('); |
697 |
|
} |
698 |
Stream_write_char(f, '{'); |
Stream_write_char(f, '{'); |
699 |
for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) { |
for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) { |
700 |
if (p->pn_type != TOK_COLON) { |
if (p->pn_type != TOK_COLON) { |
714 |
else { |
else { |
715 |
Stream_write_string(f, "set "); |
Stream_write_string(f, "set "); |
716 |
} |
} |
717 |
instrument_expression(p->pn_left, f); |
output_expression(p->pn_left, f, false); |
718 |
if (p->pn_right->pn_type != TOK_FUNCTION) { |
if (p->pn_right->pn_type != TOK_FUNCTION) { |
719 |
fatal_source(file_id, p->pn_pos.begin.lineno, "expected function"); |
fatal_source(file_id, p->pn_pos.begin.lineno, "expected function"); |
720 |
} |
} |
721 |
instrument_function(p->pn_right, f, 0, FUNCTION_GETTER_OR_SETTER); |
instrument_function(p->pn_right, f, 0, FUNCTION_GETTER_OR_SETTER); |
722 |
break; |
break; |
723 |
default: |
default: |
724 |
instrument_expression(p->pn_left, f); |
output_expression(p->pn_left, f, false); |
725 |
Stream_write_string(f, ": "); |
Stream_write_string(f, ": "); |
726 |
instrument_expression(p->pn_right, f); |
output_expression(p->pn_right, f, false); |
727 |
break; |
break; |
728 |
} |
} |
729 |
} |
} |
730 |
Stream_write_char(f, '}'); |
Stream_write_char(f, '}'); |
731 |
|
if (parenthesize_object_literals) { |
732 |
|
Stream_write_char(f, ')'); |
733 |
|
} |
734 |
break; |
break; |
735 |
case TOK_RP: |
case TOK_RP: |
736 |
Stream_write_char(f, '('); |
Stream_write_char(f, '('); |
737 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, false); |
738 |
Stream_write_char(f, ')'); |
Stream_write_char(f, ')'); |
739 |
break; |
break; |
740 |
case TOK_NAME: |
case TOK_NAME: |
741 |
print_string_atom(node->pn_atom, f); |
print_string_atom(node->pn_atom, f); |
742 |
|
if (node->pn_expr != NULL) { |
743 |
|
Stream_write_string(f, " = "); |
744 |
|
output_expression(node->pn_expr, f, false); |
745 |
|
} |
746 |
break; |
break; |
747 |
case TOK_STRING: |
case TOK_STRING: |
748 |
print_quoted_string_atom(node->pn_atom, f); |
print_quoted_string_atom(node->pn_atom, f); |
766 |
if (node->pn_dval == 0.0) { |
if (node->pn_dval == 0.0) { |
767 |
Stream_write_string(f, "0"); |
Stream_write_string(f, "0"); |
768 |
} |
} |
769 |
|
else if (node->pn_dval == INFINITY) { |
770 |
|
Stream_write_string(f, "Number.POSITIVE_INFINITY"); |
771 |
|
} |
772 |
|
else if (node->pn_dval == -INFINITY) { |
773 |
|
Stream_write_string(f, "Number.NEGATIVE_INFINITY"); |
774 |
|
} |
775 |
|
else if (node->pn_dval == NAN) { |
776 |
|
Stream_write_string(f, "Number.NaN"); |
777 |
|
} |
778 |
else { |
else { |
779 |
Stream_printf(f, "%.15g", node->pn_dval); |
Stream_printf(f, "%.15g", node->pn_dval); |
780 |
} |
} |
799 |
} |
} |
800 |
break; |
break; |
801 |
case TOK_INSTANCEOF: |
case TOK_INSTANCEOF: |
802 |
instrument_expression(node->pn_left, f); |
output_expression(node->pn_left, f, parenthesize_object_literals); |
803 |
Stream_write_string(f, " instanceof "); |
Stream_write_string(f, " instanceof "); |
804 |
instrument_expression(node->pn_right, f); |
output_expression(node->pn_right, f, false); |
805 |
break; |
break; |
806 |
case TOK_IN: |
case TOK_IN: |
807 |
instrument_expression(node->pn_left, f); |
output_expression(node->pn_left, f, false); |
808 |
Stream_write_string(f, " in "); |
Stream_write_string(f, " in "); |
809 |
instrument_expression(node->pn_right, f); |
output_expression(node->pn_right, f, false); |
810 |
break; |
break; |
811 |
case TOK_LEXICALSCOPE: |
case TOK_LEXICALSCOPE: |
812 |
assert(node->pn_arity == PN_NAME); |
assert(node->pn_arity == PN_NAME); |
817 |
assert(node->pn_expr->pn_left->pn_arity == PN_LIST); |
assert(node->pn_expr->pn_left->pn_arity == PN_LIST); |
818 |
instrument_declarations(node->pn_expr->pn_left, f); |
instrument_declarations(node->pn_expr->pn_left, f); |
819 |
Stream_write_string(f, ") "); |
Stream_write_string(f, ") "); |
820 |
instrument_expression(node->pn_expr->pn_right, f); |
output_expression(node->pn_expr->pn_right, f, true); |
821 |
break; |
break; |
822 |
case TOK_YIELD: |
case TOK_YIELD: |
823 |
assert(node->pn_arity == PN_UNARY); |
assert(node->pn_arity == PN_UNARY); |
824 |
Stream_write_string(f, "yield"); |
Stream_write_string(f, "yield"); |
825 |
if (node->pn_kid != NULL) { |
if (node->pn_kid != NULL) { |
826 |
Stream_write_char(f, ' '); |
Stream_write_char(f, ' '); |
827 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, true); |
828 |
} |
} |
829 |
break; |
break; |
830 |
case TOK_ARRAYCOMP: |
case TOK_ARRAYCOMP: |
866 |
switch (node->pn_type) { |
switch (node->pn_type) { |
867 |
case TOK_FUNCTION: |
case TOK_FUNCTION: |
868 |
instrument_function(node, f, indent, FUNCTION_NORMAL); |
instrument_function(node, f, indent, FUNCTION_NORMAL); |
869 |
|
Stream_write_char(f, '\n'); |
870 |
break; |
break; |
871 |
case TOK_LC: |
case TOK_LC: |
872 |
assert(node->pn_arity == PN_LIST); |
assert(node->pn_arity == PN_LIST); |
897 |
|
|
898 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
899 |
Stream_write_string(f, "if ("); |
Stream_write_string(f, "if ("); |
900 |
instrument_expression(node->pn_kid1, f); |
output_expression(node->pn_kid1, f, false); |
901 |
Stream_write_string(f, ") {\n"); |
Stream_write_string(f, ") {\n"); |
902 |
if (is_jscoverage_if && node->pn_kid3) { |
if (is_jscoverage_if && node->pn_kid3) { |
903 |
uint16_t else_start = node->pn_kid3->pn_pos.begin.lineno; |
uint16_t else_start = node->pn_kid3->pn_pos.begin.lineno; |
934 |
assert(node->pn_arity == PN_BINARY); |
assert(node->pn_arity == PN_BINARY); |
935 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
936 |
Stream_write_string(f, "switch ("); |
Stream_write_string(f, "switch ("); |
937 |
instrument_expression(node->pn_left, f); |
output_expression(node->pn_left, f, false); |
938 |
Stream_write_string(f, ") {\n"); |
Stream_write_string(f, ") {\n"); |
939 |
{ |
{ |
940 |
JSParseNode * list = node->pn_right; |
JSParseNode * list = node->pn_right; |
946 |
switch (p->pn_type) { |
switch (p->pn_type) { |
947 |
case TOK_CASE: |
case TOK_CASE: |
948 |
Stream_write_string(f, "case "); |
Stream_write_string(f, "case "); |
949 |
instrument_expression(p->pn_left, f); |
output_expression(p->pn_left, f, false); |
950 |
Stream_write_string(f, ":\n"); |
Stream_write_string(f, ":\n"); |
951 |
break; |
break; |
952 |
case TOK_DEFAULT: |
case TOK_DEFAULT: |
970 |
assert(node->pn_arity == PN_BINARY); |
assert(node->pn_arity == PN_BINARY); |
971 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
972 |
Stream_write_string(f, "while ("); |
Stream_write_string(f, "while ("); |
973 |
instrument_expression(node->pn_left, f); |
output_expression(node->pn_left, f, false); |
974 |
Stream_write_string(f, ") {\n"); |
Stream_write_string(f, ") {\n"); |
975 |
instrument_statement(node->pn_right, f, indent + 2, false); |
instrument_statement(node->pn_right, f, indent + 2, false); |
976 |
Stream_write_string(f, "}\n"); |
Stream_write_string(f, "}\n"); |
983 |
Stream_write_string(f, "}\n"); |
Stream_write_string(f, "}\n"); |
984 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
985 |
Stream_write_string(f, "while ("); |
Stream_write_string(f, "while ("); |
986 |
instrument_expression(node->pn_right, f); |
output_expression(node->pn_right, f, false); |
987 |
Stream_write_string(f, ");\n"); |
Stream_write_string(f, ");\n"); |
988 |
break; |
break; |
989 |
case TOK_FOR: |
case TOK_FOR: |
1000 |
assert(node->pn_left->pn_arity == PN_TERNARY); |
assert(node->pn_left->pn_arity == PN_TERNARY); |
1001 |
Stream_write_string(f, "for ("); |
Stream_write_string(f, "for ("); |
1002 |
if (node->pn_left->pn_kid1) { |
if (node->pn_left->pn_kid1) { |
1003 |
instrument_expression(node->pn_left->pn_kid1, f); |
output_expression(node->pn_left->pn_kid1, f, false); |
1004 |
} |
} |
1005 |
Stream_write_string(f, ";"); |
Stream_write_string(f, ";"); |
1006 |
if (node->pn_left->pn_kid2) { |
if (node->pn_left->pn_kid2) { |
1007 |
Stream_write_char(f, ' '); |
Stream_write_char(f, ' '); |
1008 |
instrument_expression(node->pn_left->pn_kid2, f); |
output_expression(node->pn_left->pn_kid2, f, false); |
1009 |
} |
} |
1010 |
Stream_write_string(f, ";"); |
Stream_write_string(f, ";"); |
1011 |
if (node->pn_left->pn_kid3) { |
if (node->pn_left->pn_kid3) { |
1012 |
Stream_write_char(f, ' '); |
Stream_write_char(f, ' '); |
1013 |
instrument_expression(node->pn_left->pn_kid3, f); |
output_expression(node->pn_left->pn_kid3, f, false); |
1014 |
} |
} |
1015 |
Stream_write_char(f, ')'); |
Stream_write_char(f, ')'); |
1016 |
break; |
break; |
1026 |
assert(node->pn_arity == PN_UNARY); |
assert(node->pn_arity == PN_UNARY); |
1027 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
1028 |
Stream_write_string(f, "throw "); |
Stream_write_string(f, "throw "); |
1029 |
instrument_expression(node->pn_u.unary.kid, f); |
output_expression(node->pn_u.unary.kid, f, false); |
1030 |
Stream_write_string(f, ";\n"); |
Stream_write_string(f, ";\n"); |
1031 |
break; |
break; |
1032 |
case TOK_TRY: |
case TOK_TRY: |
1043 |
assert(catch->pn_type == TOK_CATCH); |
assert(catch->pn_type == TOK_CATCH); |
1044 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
1045 |
Stream_write_string(f, "catch ("); |
Stream_write_string(f, "catch ("); |
1046 |
/* this may not be a name - destructuring assignment */ |
output_expression(catch->pn_kid1, f, false); |
|
/* |
|
|
assert(catch->pn_kid1->pn_arity == PN_NAME); |
|
|
print_string_atom(catch->pn_kid1->pn_atom, f); |
|
|
*/ |
|
|
instrument_expression(catch->pn_kid1, f); |
|
1047 |
if (catch->pn_kid2) { |
if (catch->pn_kid2) { |
1048 |
Stream_write_string(f, " if "); |
Stream_write_string(f, " if "); |
1049 |
instrument_expression(catch->pn_kid2, f); |
output_expression(catch->pn_kid2, f, false); |
1050 |
} |
} |
1051 |
Stream_write_string(f, ") {\n"); |
Stream_write_string(f, ") {\n"); |
1052 |
instrument_statement(catch->pn_kid3, f, indent + 2, false); |
instrument_statement(catch->pn_kid3, f, indent + 2, false); |
1081 |
assert(node->pn_arity == PN_BINARY); |
assert(node->pn_arity == PN_BINARY); |
1082 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
1083 |
Stream_write_string(f, "with ("); |
Stream_write_string(f, "with ("); |
1084 |
instrument_expression(node->pn_left, f); |
output_expression(node->pn_left, f, false); |
1085 |
Stream_write_string(f, ") {\n"); |
Stream_write_string(f, ") {\n"); |
1086 |
instrument_statement(node->pn_right, f, indent + 2, false); |
instrument_statement(node->pn_right, f, indent + 2, false); |
1087 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
1089 |
break; |
break; |
1090 |
case TOK_VAR: |
case TOK_VAR: |
1091 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
1092 |
instrument_expression(node, f); |
output_expression(node, f, false); |
1093 |
Stream_write_string(f, ";\n"); |
Stream_write_string(f, ";\n"); |
1094 |
break; |
break; |
1095 |
case TOK_RETURN: |
case TOK_RETURN: |
1098 |
Stream_write_string(f, "return"); |
Stream_write_string(f, "return"); |
1099 |
if (node->pn_kid != NULL) { |
if (node->pn_kid != NULL) { |
1100 |
Stream_write_char(f, ' '); |
Stream_write_char(f, ' '); |
1101 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, true); |
1102 |
} |
} |
1103 |
Stream_write_string(f, ";\n"); |
Stream_write_string(f, ";\n"); |
1104 |
break; |
break; |
1106 |
assert(node->pn_arity == PN_UNARY); |
assert(node->pn_arity == PN_UNARY); |
1107 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
1108 |
if (node->pn_kid != NULL) { |
if (node->pn_kid != NULL) { |
1109 |
instrument_expression(node->pn_kid, f); |
output_expression(node->pn_kid, f, true); |
1110 |
} |
} |
1111 |
Stream_write_string(f, ";\n"); |
Stream_write_string(f, ";\n"); |
1112 |
break; |
break; |
1113 |
case TOK_COLON: |
case TOK_COLON: |
1114 |
|
{ |
1115 |
assert(node->pn_arity == PN_NAME); |
assert(node->pn_arity == PN_NAME); |
|
/* |
|
|
This one is tricky: can't output instrumentation between the label and the |
|
|
statement it's supposed to label ... |
|
|
*/ |
|
1116 |
Stream_printf(f, "%*s", indent < 2? 0: indent - 2, ""); |
Stream_printf(f, "%*s", indent < 2? 0: indent - 2, ""); |
1117 |
print_string_atom(node->pn_atom, f); |
print_string_atom(node->pn_atom, f); |
1118 |
Stream_write_string(f, ":\n"); |
Stream_write_string(f, ":\n"); |
1119 |
/* |
JSParseNode * labelled = node->pn_expr; |
1120 |
... use output_statement instead of instrument_statement. |
if (labelled->pn_type == TOK_LEXICALSCOPE) { |
1121 |
*/ |
labelled = labelled->pn_expr; |
1122 |
output_statement(node->pn_expr, f, indent, false); |
} |
1123 |
|
if (labelled->pn_type == TOK_LC) { |
1124 |
|
/* labelled block */ |
1125 |
|
Stream_printf(f, "%*s", indent, ""); |
1126 |
|
Stream_write_string(f, "{\n"); |
1127 |
|
instrument_statement(labelled, f, indent + 2, false); |
1128 |
|
Stream_printf(f, "%*s", indent, ""); |
1129 |
|
Stream_write_string(f, "}\n"); |
1130 |
|
} |
1131 |
|
else { |
1132 |
|
/* |
1133 |
|
This one is tricky: can't output instrumentation between the label and the |
1134 |
|
statement it's supposed to label, so use output_statement instead of |
1135 |
|
instrument_statement. |
1136 |
|
*/ |
1137 |
|
output_statement(labelled, f, indent, false); |
1138 |
|
} |
1139 |
break; |
break; |
1140 |
|
} |
1141 |
case TOK_LEXICALSCOPE: |
case TOK_LEXICALSCOPE: |
1142 |
/* let statement */ |
/* let statement */ |
1143 |
assert(node->pn_arity == PN_NAME); |
assert(node->pn_arity == PN_NAME); |
1180 |
case PN_LIST: |
case PN_LIST: |
1181 |
/* let definition */ |
/* let definition */ |
1182 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
1183 |
instrument_expression(node, f); |
output_expression(node, f, false); |
1184 |
Stream_write_string(f, ";\n"); |
Stream_write_string(f, ";\n"); |
1185 |
break; |
break; |
1186 |
default: |
default: |