352 |
} |
} |
353 |
} |
} |
354 |
|
|
355 |
|
static void output_for_in(JSParseNode * node, Stream * f) { |
356 |
|
assert(node->pn_type == TOK_FOR); |
357 |
|
assert(node->pn_arity == PN_BINARY); |
358 |
|
Stream_write_string(f, "for "); |
359 |
|
if (node->pn_iflags & JSITER_FOREACH) { |
360 |
|
Stream_write_string(f, "each "); |
361 |
|
} |
362 |
|
Stream_write_char(f, '('); |
363 |
|
instrument_expression(node->pn_left, f); |
364 |
|
Stream_write_char(f, ')'); |
365 |
|
} |
366 |
|
|
367 |
/* |
/* |
368 |
See <Expressions> in jsparse.h. |
See <Expressions> in jsparse.h. |
369 |
TOK_FUNCTION is handled as a statement and as an expression. |
TOK_FUNCTION is handled as a statement and as an expression. |
684 |
Stream_write_string(f, "yield "); |
Stream_write_string(f, "yield "); |
685 |
instrument_expression(node->pn_kid, f); |
instrument_expression(node->pn_kid, f); |
686 |
break; |
break; |
687 |
|
case TOK_ARRAYCOMP: |
688 |
|
assert(node->pn_arity == PN_LIST); |
689 |
|
{ |
690 |
|
JSParseNode * block_node; |
691 |
|
switch (node->pn_count) { |
692 |
|
case 1: |
693 |
|
block_node = node->pn_head; |
694 |
|
break; |
695 |
|
case 2: |
696 |
|
block_node = node->pn_head->pn_next; |
697 |
|
break; |
698 |
|
default: |
699 |
|
abort(); |
700 |
|
break; |
701 |
|
} |
702 |
|
assert(block_node->pn_type == TOK_LEXICALSCOPE); |
703 |
|
assert(block_node->pn_arity == PN_NAME); |
704 |
|
JSParseNode * for_node = block_node->pn_expr; |
705 |
|
assert(for_node->pn_type == TOK_FOR); |
706 |
|
assert(for_node->pn_arity == PN_BINARY); |
707 |
|
JSParseNode * push_node; |
708 |
|
JSParseNode * if_node = NULL; |
709 |
|
switch (for_node->pn_right->pn_type) { |
710 |
|
case TOK_ARRAYPUSH: |
711 |
|
push_node = for_node->pn_right; |
712 |
|
assert(push_node->pn_arity == PN_UNARY); |
713 |
|
break; |
714 |
|
case TOK_IF: |
715 |
|
if_node = for_node->pn_right; |
716 |
|
assert(if_node->pn_arity == PN_TERNARY); |
717 |
|
push_node = if_node->pn_kid2; |
718 |
|
break; |
719 |
|
default: |
720 |
|
abort(); |
721 |
|
break; |
722 |
|
} |
723 |
|
Stream_write_char(f, '['); |
724 |
|
instrument_expression(push_node->pn_kid, f); |
725 |
|
Stream_write_char(f, ' '); |
726 |
|
output_for_in(for_node, f); |
727 |
|
if (if_node) { |
728 |
|
Stream_write_string(f, " if ("); |
729 |
|
instrument_expression(if_node->pn_kid1, f); |
730 |
|
Stream_write_char(f, ')'); |
731 |
|
} |
732 |
|
Stream_write_char(f, ']'); |
733 |
|
} |
734 |
|
break; |
735 |
|
case TOK_VAR: |
736 |
|
assert(node->pn_arity == PN_LIST); |
737 |
|
Stream_write_string(f, "var "); |
738 |
|
instrument_declarations(node, f); |
739 |
|
break; |
740 |
|
case TOK_LET: |
741 |
|
assert(node->pn_arity == PN_LIST); |
742 |
|
Stream_write_string(f, "let "); |
743 |
|
instrument_declarations(node, f); |
744 |
|
break; |
745 |
default: |
default: |
746 |
fatal("unsupported node type in file %s: %d", file_id, node->pn_type); |
fatal("unsupported node type in file %s: %d", file_id, node->pn_type); |
747 |
} |
} |
748 |
} |
} |
749 |
|
|
|
static void instrument_var_statement(JSParseNode * node, Stream * f, int indent) { |
|
|
assert(node->pn_arity == PN_LIST); |
|
|
Stream_printf(f, "%*s", indent, ""); |
|
|
Stream_write_string(f, "var "); |
|
|
instrument_declarations(node, f); |
|
|
} |
|
|
|
|
|
static void instrument_let_definition(JSParseNode * node, Stream * f, int indent) { |
|
|
assert(node->pn_arity == PN_LIST); |
|
|
Stream_printf(f, "%*s", indent, ""); |
|
|
Stream_write_string(f, "let "); |
|
|
instrument_declarations(node, f); |
|
|
} |
|
|
|
|
750 |
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) { |
751 |
switch (node->pn_type) { |
switch (node->pn_type) { |
752 |
case TOK_FUNCTION: |
case TOK_FUNCTION: |
867 |
case TOK_FOR: |
case TOK_FOR: |
868 |
assert(node->pn_arity == PN_BINARY); |
assert(node->pn_arity == PN_BINARY); |
869 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
|
Stream_write_string(f, "for "); |
|
|
if (node->pn_iflags & JSITER_FOREACH) { |
|
|
Stream_write_string(f, "each "); |
|
|
} |
|
|
Stream_write_char(f, '('); |
|
870 |
switch (node->pn_left->pn_type) { |
switch (node->pn_left->pn_type) { |
871 |
case TOK_IN: |
case TOK_IN: |
872 |
/* for/in */ |
/* for/in */ |
873 |
assert(node->pn_left->pn_arity == PN_BINARY); |
assert(node->pn_left->pn_arity == PN_BINARY); |
874 |
switch (node->pn_left->pn_left->pn_type) { |
output_for_in(node, f); |
|
case TOK_VAR: |
|
|
instrument_var_statement(node->pn_left->pn_left, f, 0); |
|
|
break; |
|
|
case TOK_LET: |
|
|
instrument_let_definition(node->pn_left->pn_left, f, 0); |
|
|
break; |
|
|
case TOK_NAME: |
|
|
instrument_expression(node->pn_left->pn_left, f); |
|
|
break; |
|
|
default: |
|
|
/* this is undocumented: for (x.value in y) */ |
|
|
instrument_expression(node->pn_left->pn_left, f); |
|
|
break; |
|
|
/* |
|
|
default: |
|
|
fprintf(stderr, "unexpected node type: %d\n", node->pn_left->pn_left->pn_type); |
|
|
abort(); |
|
|
break; |
|
|
*/ |
|
|
} |
|
|
Stream_write_string(f, " in "); |
|
|
instrument_expression(node->pn_left->pn_right, f); |
|
875 |
break; |
break; |
876 |
case TOK_RESERVED: |
case TOK_RESERVED: |
877 |
/* for (;;) */ |
/* for (;;) */ |
878 |
assert(node->pn_left->pn_arity == PN_TERNARY); |
assert(node->pn_left->pn_arity == PN_TERNARY); |
879 |
|
Stream_write_string(f, "for ("); |
880 |
if (node->pn_left->pn_kid1) { |
if (node->pn_left->pn_kid1) { |
881 |
switch (node->pn_left->pn_kid1->pn_type) { |
instrument_expression(node->pn_left->pn_kid1, f); |
|
case TOK_VAR: |
|
|
instrument_var_statement(node->pn_left->pn_kid1, f, 0); |
|
|
break; |
|
|
case TOK_LET: |
|
|
instrument_let_definition(node->pn_left->pn_kid1, f, 0); |
|
|
break; |
|
|
default: |
|
|
instrument_expression(node->pn_left->pn_kid1, f); |
|
|
break; |
|
|
} |
|
882 |
} |
} |
883 |
Stream_write_string(f, ";"); |
Stream_write_string(f, ";"); |
884 |
if (node->pn_left->pn_kid2) { |
if (node->pn_left->pn_kid2) { |
890 |
Stream_write_char(f, ' '); |
Stream_write_char(f, ' '); |
891 |
instrument_expression(node->pn_left->pn_kid3, f); |
instrument_expression(node->pn_left->pn_kid3, f); |
892 |
} |
} |
893 |
|
Stream_write_char(f, ')'); |
894 |
break; |
break; |
895 |
default: |
default: |
896 |
abort(); |
abort(); |
897 |
break; |
break; |
898 |
} |
} |
899 |
Stream_write_string(f, ") {\n"); |
Stream_write_string(f, " {\n"); |
900 |
instrument_statement(node->pn_right, f, indent + 2, false); |
instrument_statement(node->pn_right, f, indent + 2, false); |
901 |
Stream_write_string(f, "}\n"); |
Stream_write_string(f, "}\n"); |
902 |
break; |
break; |
971 |
Stream_write_string(f, "}\n"); |
Stream_write_string(f, "}\n"); |
972 |
break; |
break; |
973 |
case TOK_VAR: |
case TOK_VAR: |
974 |
instrument_var_statement(node, f, indent); |
Stream_printf(f, "%*s", indent, ""); |
975 |
|
instrument_expression(node, f); |
976 |
Stream_write_string(f, ";\n"); |
Stream_write_string(f, ";\n"); |
977 |
break; |
break; |
978 |
case TOK_RETURN: |
case TOK_RETURN: |
1048 |
break; |
break; |
1049 |
case PN_LIST: |
case PN_LIST: |
1050 |
/* let definition */ |
/* let definition */ |
1051 |
instrument_let_definition(node, f, indent); |
Stream_printf(f, "%*s", indent, ""); |
1052 |
|
instrument_expression(node, f); |
1053 |
Stream_write_string(f, ";\n"); |
Stream_write_string(f, ";\n"); |
1054 |
break; |
break; |
1055 |
default: |
default: |