325 |
} |
} |
326 |
} |
} |
327 |
|
|
328 |
|
static void output_destructuring_expression(JSParseNode * node, Stream * f) { |
329 |
|
switch (node->pn_type) { |
330 |
|
case TOK_NAME: |
331 |
|
assert(node->pn_arity == PN_NAME); |
332 |
|
print_string_atom(node->pn_atom, f); |
333 |
|
if (node->pn_expr != NULL) { |
334 |
|
Stream_write_string(f, " = "); |
335 |
|
instrument_expression(node->pn_expr, f); |
336 |
|
} |
337 |
|
break; |
338 |
|
case TOK_RB: |
339 |
|
Stream_write_char(f, '['); |
340 |
|
for (JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) { |
341 |
|
if (p != node->pn_head) { |
342 |
|
Stream_write_string(f, ", "); |
343 |
|
} |
344 |
|
/* TOK_COMMA is a special case: a hole in the array */ |
345 |
|
if (p->pn_type != TOK_COMMA) { |
346 |
|
output_destructuring_expression(p, f); |
347 |
|
} |
348 |
|
} |
349 |
|
if (node->pn_extra == PNX_ENDCOMMA) { |
350 |
|
Stream_write_char(f, ','); |
351 |
|
} |
352 |
|
Stream_write_char(f, ']'); |
353 |
|
break; |
354 |
|
case TOK_RC: |
355 |
|
Stream_write_char(f, '{'); |
356 |
|
for (JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) { |
357 |
|
if (p != node->pn_head) { |
358 |
|
Stream_write_string(f, ", "); |
359 |
|
} |
360 |
|
if (p->pn_type != TOK_COLON) { |
361 |
|
fatal_source(file_id, p->pn_pos.begin.lineno, "unsupported node type (%d)", p->pn_type); |
362 |
|
} |
363 |
|
instrument_expression(p->pn_left, f); |
364 |
|
Stream_write_string(f, ": "); |
365 |
|
output_destructuring_expression(p->pn_right, f); |
366 |
|
} |
367 |
|
Stream_write_char(f, '}'); |
368 |
|
break; |
369 |
|
case TOK_ASSIGN: |
370 |
|
output_destructuring_expression(node->pn_left, f); |
371 |
|
Stream_write_string(f, " = "); |
372 |
|
instrument_expression(node->pn_right, f); |
373 |
|
break; |
374 |
|
default: |
375 |
|
fatal_source(file_id, node->pn_pos.begin.lineno, "unsupported node type (%d)", node->pn_type); |
376 |
|
break; |
377 |
|
} |
378 |
|
} |
379 |
|
|
380 |
static void instrument_function(JSParseNode * node, Stream * f, int indent, enum FunctionType type) { |
static void instrument_function(JSParseNode * node, Stream * f, int indent, enum FunctionType type) { |
381 |
assert(node->pn_type == TOK_FUNCTION); |
assert(node->pn_type == TOK_FUNCTION); |
382 |
assert(node->pn_arity == PN_FUNC); |
assert(node->pn_arity == PN_FUNC); |
433 |
} |
} |
434 |
} |
} |
435 |
assert(expression != NULL); |
assert(expression != NULL); |
436 |
instrument_expression(expression, f); |
output_destructuring_expression(expression, f); |
437 |
} |
} |
438 |
else { |
else { |
439 |
print_string_atom(param, f); |
print_string_atom(param, f); |
507 |
static void instrument_declarations(JSParseNode * list, Stream * f) { |
static void instrument_declarations(JSParseNode * list, Stream * f) { |
508 |
assert(list->pn_arity == PN_LIST); |
assert(list->pn_arity == PN_LIST); |
509 |
for (JSParseNode * p = list->pn_head; p != NULL; p = p->pn_next) { |
for (JSParseNode * p = list->pn_head; p != NULL; p = p->pn_next) { |
510 |
switch (p->pn_type) { |
if (p != list->pn_head) { |
511 |
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; |
|
512 |
} |
} |
513 |
|
output_destructuring_expression(p, f); |
514 |
} |
} |
515 |
} |
} |
516 |
|
|
541 |
} |
} |
542 |
break; |
break; |
543 |
case TOK_ASSIGN: |
case TOK_ASSIGN: |
544 |
instrument_expression(node->pn_left, f); |
switch (node->pn_left->pn_type) { |
545 |
|
case TOK_RB: |
546 |
|
output_destructuring_expression(node->pn_left, f); |
547 |
|
break; |
548 |
|
case TOK_RC: |
549 |
|
Stream_write_char(f, '('); |
550 |
|
output_destructuring_expression(node->pn_left, f); |
551 |
|
Stream_write_char(f, ')'); |
552 |
|
break; |
553 |
|
default: |
554 |
|
instrument_expression(node->pn_left, f); |
555 |
|
break; |
556 |
|
} |
557 |
Stream_write_char(f, ' '); |
Stream_write_char(f, ' '); |
558 |
switch (node->pn_op) { |
switch (node->pn_op) { |
559 |
case JSOP_ADD: |
case JSOP_ADD: |
688 |
instrument_expression(node->pn_kid, f); |
instrument_expression(node->pn_kid, f); |
689 |
break; |
break; |
690 |
case TOK_DOT: |
case TOK_DOT: |
691 |
|
/* numeric literals must be parenthesized */ |
692 |
|
switch (node->pn_expr->pn_type) { |
693 |
|
case TOK_NUMBER: |
694 |
|
Stream_write_char(f, '('); |
695 |
|
instrument_expression(node->pn_expr, f); |
696 |
|
Stream_write_char(f, ')'); |
697 |
|
break; |
698 |
|
default: |
699 |
|
instrument_expression(node->pn_expr, f); |
700 |
|
break; |
701 |
|
} |
702 |
/* |
/* |
703 |
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' |
704 |
contains illegal characters, we have to use the subscript syntax instead of |
contains illegal characters, we have to use the subscript syntax instead of |
705 |
the dot syntax. |
the dot syntax. |
706 |
*/ |
*/ |
|
instrument_expression(node->pn_expr, f); |
|
707 |
assert(ATOM_IS_STRING(node->pn_atom)); |
assert(ATOM_IS_STRING(node->pn_atom)); |
708 |
{ |
{ |
709 |
JSString * s = ATOM_TO_STRING(node->pn_atom); |
JSString * s = ATOM_TO_STRING(node->pn_atom); |
757 |
Stream_write_char(f, ']'); |
Stream_write_char(f, ']'); |
758 |
break; |
break; |
759 |
case TOK_RC: |
case TOK_RC: |
760 |
|
Stream_write_char(f, '('); |
761 |
Stream_write_char(f, '{'); |
Stream_write_char(f, '{'); |
762 |
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) { |
763 |
if (p->pn_type != TOK_COLON) { |
if (p->pn_type != TOK_COLON) { |
791 |
} |
} |
792 |
} |
} |
793 |
Stream_write_char(f, '}'); |
Stream_write_char(f, '}'); |
794 |
|
Stream_write_char(f, ')'); |
795 |
break; |
break; |
796 |
case TOK_RP: |
case TOK_RP: |
797 |
Stream_write_char(f, '('); |
Stream_write_char(f, '('); |
1090 |
assert(catch->pn_type == TOK_CATCH); |
assert(catch->pn_type == TOK_CATCH); |
1091 |
Stream_printf(f, "%*s", indent, ""); |
Stream_printf(f, "%*s", indent, ""); |
1092 |
Stream_write_string(f, "catch ("); |
Stream_write_string(f, "catch ("); |
1093 |
/* this may not be a name - destructuring assignment */ |
output_destructuring_expression(catch->pn_kid1, f); |
|
/* |
|
|
assert(catch->pn_kid1->pn_arity == PN_NAME); |
|
|
print_string_atom(catch->pn_kid1->pn_atom, f); |
|
|
*/ |
|
|
instrument_expression(catch->pn_kid1, f); |
|
1094 |
if (catch->pn_kid2) { |
if (catch->pn_kid2) { |
1095 |
Stream_write_string(f, " if "); |
Stream_write_string(f, " if "); |
1096 |
instrument_expression(catch->pn_kid2, f); |
instrument_expression(catch->pn_kid2, f); |
1158 |
Stream_write_string(f, ";\n"); |
Stream_write_string(f, ";\n"); |
1159 |
break; |
break; |
1160 |
case TOK_COLON: |
case TOK_COLON: |
1161 |
|
{ |
1162 |
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 ... |
|
|
*/ |
|
1163 |
Stream_printf(f, "%*s", indent < 2? 0: indent - 2, ""); |
Stream_printf(f, "%*s", indent < 2? 0: indent - 2, ""); |
1164 |
print_string_atom(node->pn_atom, f); |
print_string_atom(node->pn_atom, f); |
1165 |
Stream_write_string(f, ":\n"); |
Stream_write_string(f, ":\n"); |
1166 |
/* |
JSParseNode * labelled = node->pn_expr; |
1167 |
... use output_statement instead of instrument_statement. |
if (labelled->pn_type == TOK_LEXICALSCOPE) { |
1168 |
*/ |
labelled = labelled->pn_expr; |
1169 |
output_statement(node->pn_expr, f, indent, false); |
} |
1170 |
|
if (labelled->pn_type == TOK_LC) { |
1171 |
|
/* labelled block */ |
1172 |
|
Stream_printf(f, "%*s", indent, ""); |
1173 |
|
Stream_write_string(f, "{\n"); |
1174 |
|
instrument_statement(labelled, f, indent + 2, false); |
1175 |
|
Stream_printf(f, "%*s", indent, ""); |
1176 |
|
Stream_write_string(f, "}\n"); |
1177 |
|
} |
1178 |
|
else { |
1179 |
|
/* |
1180 |
|
This one is tricky: can't output instrumentation between the label and the |
1181 |
|
statement it's supposed to label, so use output_statement instead of |
1182 |
|
instrument_statement. |
1183 |
|
*/ |
1184 |
|
output_statement(labelled, f, indent, false); |
1185 |
|
} |
1186 |
break; |
break; |
1187 |
|
} |
1188 |
case TOK_LEXICALSCOPE: |
case TOK_LEXICALSCOPE: |
1189 |
/* let statement */ |
/* let statement */ |
1190 |
assert(node->pn_arity == PN_NAME); |
assert(node->pn_arity == PN_NAME); |