2 * Internal definitions.
3 * Copyright (c) 1998 New Generation Software (NGS) Oy
5 * Author: Markku Rossi <mtr@ngs.fi>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/jsc/compiler.js,v $
40 JSC
$tIDENTIFIER
= 132;
87 JSC
$tMINUSMINUS
= 175;
109 JSC
$EXPR_ASSIGNMENT
= 1;
110 JSC
$EXPR_QUEST_COLON
= 2;
111 JSC
$EXPR_LOGICAL
= 3;
112 JSC
$EXPR_BITWISE
= 4;
113 JSC
$EXPR_EQUALITY
= 5;
114 JSC
$EXPR_RELATIONAL
= 6;
116 JSC
$EXPR_MULTIPLICATIVE
= 8;
117 JSC
$EXPR_ADDITIVE
= 9;
122 JSC
$EXPR_IDENTIFIER
= 14;
124 JSC
$EXPR_INTEGER
= 16;
125 JSC
$EXPR_STRING
= 17;
127 JSC
$EXPR_OBJECT_PROPERTY
= 19;
128 JSC
$EXPR_OBJECT_ARRAY
= 20;
130 JSC
$EXPR_DELETE
= 22;
132 JSC
$EXPR_TYPEOF
= 24;
133 JSC
$EXPR_PREFIX
= 25;
134 JSC
$EXPR_POSTFIX
= 26;
136 JSC
$EXPR_REGEXP
= 28;
137 JSC
$EXPR_ARRAY_INITIALIZER
= 29;
138 JSC
$EXPR_OBJECT_INITIALIZER
= 30;
143 JSC
$STMT_FUNCTION_DECLARATION
= 1;
144 JSC
$STMT_VARIABLE
= 2;
151 JSC
$STMT_CONTINUE
= 9;
153 JSC
$STMT_RETURN
= 11;
157 JSC
$STMT_DO_WHILE
= 15;
158 JSC
$STMT_SWITCH
= 16;
159 JSC
$STMT_LABELED_STMT
= 17;
161 /* JavaScript types. */
163 JSC
$JS_UNDEFINED
= 0;
181 * Copyright (c) 1998-1999 New Generation Software (NGS) Oy
183 * Author: Markku Rossi <mtr@ngs.fi>
187 * This library is free software; you can redistribute it and/or
188 * modify it under the terms of the GNU Library General Public
189 * License as published by the Free Software Foundation; either
190 * version 2 of the License, or (at your option) any later version.
192 * This library is distributed in the hope that it will be useful,
193 * but WITHOUT ANY WARRANTY; without even the implied warranty of
194 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
195 * Library General Public License for more details.
197 * You should have received a copy of the GNU Library General Public
198 * License along with this library; if not, write to the Free
199 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
204 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/jsc/compiler.js,v $
212 function JSC
$lexer (stream
)
216 JSC
$token_value
= null;
218 while ((ch
= stream
.readByte ()) != -1)
226 if (JSC
$lexer_is_white_space (ch
))
229 JSC
$token_linenum
= JSC
$linenum
;
231 if (ch
== #'/' && JSC
$lexer_peek_char (stream
) == #'*')
233 /* Multi line comment. */
235 while ((ch
= stream
.readByte ()) != -1
236 && (ch
!= #'*' || JSC
$lexer_peek_char (stream
) != #'/'))
240 /* Consume the peeked #'/' character. */
243 else if ((ch == #'/' && JSC$lexer_peek_char (stream) == #'/')
244 || (ch == #'#' && JSC$lexer_peek_char (stream) == #'!'))
246 /* Single line comment. */
247 while ((ch
= stream
.readByte ()) != -1 && ch
!= #'\n')
252 else if (ch
== #'"' || ch
== #'\'')
254 /* String constant. */
255 JSC
$token_value
= JSC
$lexer_read_string (stream
, "string", ch
);
260 else if (ch
== #'=' && JSC
$lexer_peek_char (stream
) == #'=')
263 if (JSC
$lexer_peek_char (stream
) == #'=')
270 else if (ch
== #'!' && JSC
$lexer_peek_char (stream
) == #'=')
273 if (JSC
$lexer_peek_char (stream
) == #'=')
280 else if (ch
== #'<' && JSC
$lexer_peek_char (stream
) == #'=')
285 else if (ch
== #'>' && JSC
$lexer_peek_char (stream
) == #'=')
290 else if (ch
== #'&' && JSC
$lexer_peek_char (stream
) == #'&')
295 else if (ch
== #'|' && JSC
$lexer_peek_char (stream
) == #'|')
300 else if (ch
== #'+' && JSC
$lexer_peek_char (stream
) == #'+')
303 return JSC
$tPLUSPLUS
;
305 else if (ch
== #'-' && JSC
$lexer_peek_char (stream
) == #'-')
308 return JSC
$tMINUSMINUS
;
310 else if (ch
== #'*' && JSC
$lexer_peek_char (stream
) == #'=')
315 else if (ch
== #'/' && JSC
$lexer_peek_char (stream
) == #'=')
320 else if (ch
== #'%' && JSC
$lexer_peek_char (stream
) == #'=')
325 else if (ch
== #'+' && JSC
$lexer_peek_char (stream
) == #'=')
330 else if (ch
== #'-' && JSC
$lexer_peek_char (stream
) == #'=')
335 else if (ch
== #'&' && JSC
$lexer_peek_char (stream
) == #'=')
340 else if (ch
== #'^' && JSC
$lexer_peek_char (stream
) == #'=')
345 else if (ch
== #'|' && JSC
$lexer_peek_char (stream
) == #'=')
350 else if (ch
== #'<' && JSC
$lexer_peek_char (stream
) == #'<')
353 if (JSC
$lexer_peek_char (stream
) == #'=')
361 else if (ch
== #'>' && JSC
$lexer_peek_char (stream
) == #'>')
364 ch2
= JSC
$lexer_peek_char (stream
);
370 else if (ch2
== #'>')
373 if (JSC
$lexer_peek_char (stream
) == #'=')
385 /* Identifiers and keywords. */
386 else if (JSC
$lexer_is_identifier_letter (ch
))
389 var id
= String
.fromCharCode (ch
);
391 while ((ch
= stream
.readByte ()) != -1
392 && (JSC
$lexer_is_identifier_letter (ch
)
393 || JSC
$lexer_is_decimal_digit (ch
)))
394 id
.append (File
.byteToString (ch
));
395 stream
.ungetByte (ch
);
400 else if (id
== "continue")
401 return JSC
$tCONTINUE
;
402 else if (id
== "delete")
404 else if (id
== "else")
406 else if (id
== "for")
408 else if (id
== "function")
409 return JSC
$tFUNCTION
;
414 else if (id
== "new")
416 else if (id
== "return")
418 else if (id
== "this")
420 else if (id
== "typeof")
422 else if (id
== "var")
424 else if (id
== "void")
426 else if (id
== "while")
428 else if (id
== "with")
432 * Future reserved keywords (some of these is already in use
433 * in this implementation).
435 else if (id
== "case")
437 else if (id
== "catch")
439 else if (id
== "class")
441 else if (id
== "const")
443 else if (id
== "debugger")
444 return JSC
$tDEBUGGER
;
445 else if (id
== "default")
449 else if (id
== "enum")
451 else if (id
== "export")
453 else if (id
== "extends")
455 else if (id
== "finally")
457 else if (id
== "import")
459 else if (id
== "super")
461 else if (id
== "switch")
463 else if (id
== "throw")
465 else if (id
== "try")
468 /* Null and boolean literals. */
469 else if (id
== "null")
471 else if (id
== "true")
473 else if (id
== "false")
477 /* It really is an identifier. */
478 JSC
$token_value
= id
;
479 return JSC
$tIDENTIFIER
;
483 /* Character constants. */
484 else if (ch
== #'#' && JSC
$lexer_peek_char (stream
) == #'\'')
486 /* Skip the starting #'\'' and read more. */
489 ch
= stream
.readByte ();
493 = JSC
$lexer_read_backslash_escape (stream
, 0, "character");
495 if (stream
.readByte () != #'\'')
496 error (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
497 + ": malformed character constant");
499 else if (JSC
$lexer_peek_char (stream
) == #'\'')
502 JSC
$token_value
= ch
;
505 error (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
506 + ": malformed character constant");
511 /* Octal and hex numbers. */
513 && JSC
$lexer_peek_char (stream
) != #'.'
514 && JSC
$lexer_peek_char (stream
) != #'e'
515 && JSC
$lexer_peek_char (stream
) != #'E')
518 ch
= stream
.readByte ();
519 if (ch
== #'x' || ch
== #'X')
521 ch
= stream
.readByte ();
522 while (JSC
$lexer_is_hex_digit (ch
))
524 JSC
$token_value
*= 16;
525 JSC
$token_value
+= JSC
$lexer_hex_to_dec (ch
);
526 ch
= stream
.readByte ();
528 stream
.ungetByte (ch
);
532 while (JSC
$lexer_is_octal_digit (ch
))
534 JSC
$token_value
*= 8;
535 JSC
$token_value
+= ch
- #'0';
536 ch
= stream
.readByte ();
538 stream
.ungetByte (ch
);
544 /* Decimal numbers. */
545 else if (JSC
$lexer_is_decimal_digit (ch
)
547 && JSC
$lexer_is_decimal_digit (
548 JSC
$lexer_peek_char (stream
))))
550 var is_float
= false;
551 var buf
= new String (File
.byteToString (ch
));
552 var accept_dot
= true;
557 * We started with #'.' and we know that the next character
558 * is a decimal digit (we peeked it).
562 ch
= stream
.readByte ();
563 while (JSC
$lexer_is_decimal_digit (ch
))
565 buf
.append (File
.byteToString (ch
));
566 ch
= stream
.readByte ();
572 /* We did start with a decimal digit. */
573 ch
= stream
.readByte ();
574 while (JSC
$lexer_is_decimal_digit (ch
))
576 buf
.append (File
.byteToString (ch
));
577 ch
= stream
.readByte ();
581 if ((accept_dot
&& ch
== #'.')
582 || ch
== #'e' || ch
== #'E')
588 buf
.append (File
.byteToString (ch
));
589 ch
= stream
.readByte ();
590 while (JSC
$lexer_is_decimal_digit (ch
))
592 buf
.append (File
.byteToString (ch
));
593 ch
= stream
.readByte ();
597 if (ch
== #'e' || ch
== #'E')
599 buf
.append (File
.byteToString (ch
));
600 ch
= stream
.readByte ();
601 if (ch
== #'+' || ch
== #'-')
603 buf
.append (File
.byteToString (ch
));
604 ch
= stream
.readByte ();
606 if (!JSC
$lexer_is_decimal_digit (ch
))
607 error (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
608 + ": malformed exponent part in a decimal literal");
610 while (JSC
$lexer_is_decimal_digit (ch
))
612 buf
.append (File
.byteToString (ch
));
613 ch
= stream
.readByte ();
618 /* Finally, we put the last character pack to the stream. */
619 stream
.ungetByte (ch
);
623 JSC
$token_value
= parseFloat (buf
);
627 JSC
$token_value
= parseInt (buf
);
631 /* Just return the character as-is. */
645 function JSC
$lexer_peek_char (stream
)
647 var ch2
= stream
.readByte ();
648 stream
.ungetByte (ch2
);
654 function JSC
$lexer_is_identifier_letter (ch
)
656 return ((#'a' <= ch
&& ch
<= #'z') || (#'A' <= ch
&& ch
<= #'Z')
657 || ch
== #'$' || ch
== #'_');
661 function JSC
$lexer_is_octal_digit (ch
)
663 return (#'0' <= ch
&& ch
<= #'7');
667 function JSC
$lexer_is_decimal_digit (ch
)
669 return #'0' <= ch
&& ch
<= #'9';
673 function JSC
$lexer_is_hex_digit (ch
)
675 return ((#'0' <= ch
&& ch
<= #'9')
676 || (#'a' <= ch
&& ch
<= #'f')
677 || (#'A' <= ch
&& ch
<= #'F'));
681 function JSC
$lexer_is_white_space (ch
)
683 return (ch
== #' ' || ch
== #'\t' || ch
== #'\v' || ch
== #'\r'
684 || ch
== #'\f' || ch
== #'\n');
688 function JSC
$lexer_hex_to_dec (ch
)
690 return ((#'0' <= ch
&& ch
<= #'9')
692 : ((#'a' <= ch
&& ch
<= #'f')
698 function JSC
$lexer_read_backslash_escape (stream
, possible_start
, name
)
700 var ch
= stream
.readByte ();
716 else if (ch
== #'\\')
720 else if (ch
== #'\'')
726 /* HexEscapeSequence. */
729 c1
= stream
.readByte ();
730 c2
= stream
.readByte ();
732 if (c1
== -1 || c2
== -1)
733 JSC
$lexer_eof_in_constant (possible_start
, name
);
735 if (!JSC
$lexer_is_hex_digit (c1
) || !JSC
$lexer_is_hex_digit (c2
))
736 error (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
737 + ": \\x used with no following hex digits");
739 ch
= (JSC
$lexer_hex_to_dec (c1
) << 4) + JSC
$lexer_hex_to_dec (c2
);
743 /* UnicodeEscapeSequence. */
746 c1
= stream
.readByte ();
747 c2
= stream
.readByte ();
748 c3
= stream
.readByte ();
749 c4
= stream
.readByte ();
751 if (c1
== -1 || c2
== -1 || c3
== -1 || c4
== -1)
752 JSC
$lexer_eof_in_constant (possible_start
, name
);
754 if (!JSC
$lexer_is_hex_digit (c1
) || !JSC
$lexer_is_hex_digit (c2
)
755 || !JSC
$lexer_is_hex_digit (c3
) || !JSC
$lexer_is_hex_digit (c4
))
756 error (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
757 + ": \\u used with no following hex digits");
759 ch
= ((JSC
$lexer_hex_to_dec (c1
) << 12)
760 + (JSC
$lexer_hex_to_dec (c2
) << 8)
761 + (JSC
$lexer_hex_to_dec (c3
) << 4)
762 + JSC
$lexer_hex_to_dec (c4
));
764 else if (JSC
$lexer_is_octal_digit (ch
))
766 var result
= ch
- #'0';
770 /* Allow three octal digits after '0'. */
773 ch
= stream
.readByte ();
774 while (i
< 3 && JSC
$lexer_is_octal_digit (ch
))
778 ch
= stream
.readByte ();
781 stream
.ungetByte (ch
);
787 error (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
788 + ": unterminated " + name
);
790 JSC
$warning (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
791 + ": warning: unknown escape sequence `\\"
792 + File
.byteToString (ch
) + "'");
799 function JSC
$lexer_read_string (stream
, name
, ender
)
801 var str
= new String ("");
802 var done
= false, ch
;
803 var possible_start_ln
= JSC
$linenum
;
804 var warned_line_terminator
= false;
808 ch
= stream
.readByte ();
811 if (JSC
$warn_strict_ecma
&& !warned_line_terminator
)
813 JSC
$warning (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
814 + ": warning: ECMAScript don't allow line terminators in "
815 + name
+ " constants");
816 warned_line_terminator
= true;
822 JSC
$lexer_eof_in_constant (possible_start_ln
, name
);
824 else if (ch
== ender
)
830 if (JSC
$lexer_peek_char (stream
) == #'\n')
833 * Backslash followed by a newline character. Ignore
840 ch
= JSC
$lexer_read_backslash_escape (stream
, possible_start_ln
,
851 function JSC
$lexer_read_regexp_constant (stream
)
853 /* Regexp literal. */
854 var source
= JSC
$lexer_read_regexp_source (stream
);
856 /* Check the possible flags. */
857 var flags
= new String ("");
858 while ((ch
= JSC
$lexer_peek_char (stream
)) == #'g' || ch
== #'i')
861 flags
.append (File
.byteToString (ch
));
864 /* Try to compile it. */
869 result
= new RegExp (source
, flags
);
873 var start
= msg
.lastIndexOf (":");
874 msg
= (JSC
$filename
+ ":" + JSC
$token_linenum
.toString ()
875 + ": malformed regular expression constant:"
876 + msg
.substr (start
+ 1));
887 function JSC
$lexer_read_regexp_source (stream
)
889 var str
= new String ("");
890 var done
= false, ch
;
891 var possible_start_ln
= JSC
$linenum
;
892 var warned_line_terminator
= false;
893 var name
= "regular expression";
897 ch
= stream
.readByte ();
900 if (JSC
$warn_strict_ecma
&& !warned_line_terminator
)
902 JSC
$warning (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
903 + ": warning: ECMAScript don't allow line "
904 + "terminators in " + name
+ " constants");
905 warned_line_terminator
= true;
911 JSC
$lexer_eof_in_constant (possible_start_ln
, name
);
919 ch
= stream
.readByte ();
923 * Backslash followed by a newline character. Ignore
930 JSC
$lexer_eof_in_constant (possible_start_ln
, name
);
932 /* Handle the backslash escapes. */
945 /* SourceCharacter. */
946 ch
= stream
.readByte ();
948 JSC
$lexer_eof_in_constant (possible_start_ln
, name
);
950 if (ch
== #'\n' && JSC
$warn_strict_ecma
)
951 JSC
$warning (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
952 + ": warning: ECMAScript don't allow line termiantor after \\c in regular expression constants");
955 * Append the source-character escape start. The ch
956 * will be appended later.
960 else if (ch
== #'u' || ch
== #'x' || ch
== #'0')
962 /* These can be handled with the read_backslash_escape(). */
963 stream
.ungetByte (ch
);
964 ch
= JSC
$lexer_read_backslash_escape (stream
);
969 * Nothing special. Leave it to the result as-is.
970 * The regular expression backage will handle it.
972 stream
.ungetByte (ch
);
976 str
.append (File
.byteToString (ch
));
984 function JSC
$lexer_eof_in_constant (possible_start
, name
)
986 var msg
= (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
987 + ": unterminated " + name
+ " constant");
989 if (possible_start
> 0)
990 msg
+= (System
.lineBreakSequence
991 + JSC
$filename
+ ":" + possible_start
.toString ()
992 + ": possible real start of unterminated " + name
+ " constant");
1005 * Copyright (c) 1998 New Generation Software (NGS) Oy
1007 * Author: Markku Rossi <mtr@ngs.fi>
1011 * This library is free software; you can redistribute it and/or
1012 * modify it under the terms of the GNU Library General Public
1013 * License as published by the Free Software Foundation; either
1014 * version 2 of the License, or (at your option) any later version.
1016 * This library is distributed in the hope that it will be useful,
1017 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1019 * Library General Public License for more details.
1021 * You should have received a copy of the GNU Library General Public
1022 * License along with this library; if not, write to the Free
1023 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
1024 * MA 02111-1307, USA
1028 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/jsc/compiler.js,v $
1036 function JSC
$parser_reset ()
1038 JSC
$function = null;
1039 JSC
$global_stmts
= null;
1040 JSC
$nested_function_declarations
= null;
1044 function JSC
$parser_parse (stream
)
1047 JSC
$filename
= stream
.name
;
1048 JSC
$functions
= new Array ();
1049 JSC
$global_stmts
= new Array ();
1050 JSC
$nested_function_declarations
= new Array ();
1051 JSC
$anonymous_function_count
= 0;
1052 JSC
$parser_peek_token_valid
= false;
1054 JSC
$num_arguments_identifiers
= 0;
1055 JSC
$num_missing_semicolons
= 0;
1058 JSC
$message ("jsc: parsing");
1060 while (JSC
$parser_peek_token (stream
) != JSC
$tEOF
)
1061 if (!JSC
$parser_parse_source_element (stream
))
1062 JSC
$parser_syntax_error ();
1066 var msg
= ("jsc: input stream had " + (JSC
$linenum
- 1).toString ()
1067 + " lines, " + JSC
$num_tokens
.toString () + " tokens");
1069 if (JSC
$num_missing_semicolons
> 0)
1070 msg
+= (", " + JSC
$num_missing_semicolons
.toString ()
1071 + " missing semicolons");
1079 * General help functions.
1082 function JSC
$parser_syntax_error ()
1084 error (JSC
$filename
+ ":" + JSC
$linenum
.toString () + ": syntax error");
1087 /* All warnings are reported through this function. */
1088 function JSC
$warning (line
)
1090 System
.stderr
.writeln (line
);
1093 /* All messages are reported throught this function. */
1094 function JSC
$message (line
)
1096 System
.stderr
.writeln (line
);
1100 function JSC
$parser_get_token (stream
)
1105 if (JSC
$parser_peek_token_valid
)
1107 JSC
$parser_peek_token_valid
= false;
1108 JSC
$parser_token_value
= JSC
$parser_peek_token_value
;
1109 JSC
$parser_token_linenum
= JSC
$parser_peek_token_linenum
;
1110 token
= JSC
$parser_peek_token_token
;
1114 token
= JSC
$lexer (stream
);
1115 JSC
$parser_token_value
= JSC
$token_value
;
1116 JSC
$parser_token_linenum
= JSC
$token_linenum
;
1119 if (token
== JSC
$tIDENTIFIER
&& JSC
$parser_token_value
== "arguments")
1120 JSC
$num_arguments_identifiers
++;
1126 function JSC
$parser_peek_token (stream
)
1128 if (JSC
$parser_peek_token_valid
)
1129 return JSC
$parser_peek_token_token
;
1132 JSC
$parser_peek_token_token
= JSC
$lexer (stream
);
1133 JSC
$parser_peek_token_value
= JSC
$token_value
;
1134 JSC
$parser_peek_token_linenum
= JSC
$token_linenum
;
1135 JSC
$parser_peek_token_valid
= true;
1136 return JSC
$parser_peek_token_token
;
1141 function JSC
$parser_get_semicolon_asci (stream
)
1143 var token
= JSC
$parser_peek_token (stream
);
1147 /* Everything ok. It was there. */
1148 return JSC
$parser_get_token (stream
);
1151 /* No semicolon. Let's see if we can insert it there. */
1153 || JSC
$parser_token_linenum
< JSC
$parser_peek_token_linenum
1154 || token
== JSC
$tEOF
)
1156 /* Ok, do the automatic semicolon insertion. */
1157 if (JSC
$warn_missing_semicolon
)
1158 JSC
$warning (JSC
$filename
+ ":" + JSC
$parser_token_linenum
.toString ()
1159 + ": warning: missing semicolon");
1160 JSC
$num_missing_semicolons
++;
1164 /* Sorry, no can do. */
1165 JSC
$parser_syntax_error ();
1169 function JSC
$parser_expr_is_left_hand_side (expr
)
1171 return (expr
.etype
== JSC
$EXPR_CALL
1172 || expr
.etype
== JSC
$EXPR_OBJECT_PROPERTY
1173 || expr
.etype
== JSC
$EXPR_OBJECT_ARRAY
1174 || expr
.etype
== JSC
$EXPR_NEW
1175 || expr
.etype
== JSC
$EXPR_THIS
1176 || expr
.etype
== JSC
$EXPR_IDENTIFIER
1177 || expr
.etype
== JSC
$EXPR_FLOAT
1178 || expr
.etype
== JSC
$EXPR_INTEGER
1179 || expr
.etype
== JSC
$EXPR_STRING
1180 || expr
.etype
== JSC
$EXPR_REGEXP
1181 || expr
.etype
== JSC
$EXPR_ARRAY_INITIALIZER
1182 || expr
.etype
== JSC
$EXPR_NULL
1183 || expr
.etype
== JSC
$EXPR_TRUE
1184 || expr
.etype
== JSC
$EXPR_FALSE
);
1188 function JSC
$parser_parse_source_element (stream
)
1190 if (JSC
$parser_parse_function_declaration (stream
))
1193 var stmt
= JSC
$parser_parse_stmt (stream
);
1197 if (stmt
.stype
== JSC
$STMT_VARIABLE
)
1199 * This is a variable declaration at the global level. These
1200 * are actually global variables.
1202 stmt
.global_level
= true;
1204 JSC
$global_stmts
.push (stmt
);
1210 function JSC
$parser_parse_function_declaration (stream
)
1212 var id
, args
, block
;
1214 if (JSC
$parser_peek_token (stream
) != JSC
$tFUNCTION
)
1217 /* Record how many `arguments' identifiers have been seen so far. */
1218 var num_arguments_identifiers
= JSC
$num_arguments_identifiers
;
1220 JSC
$parser_get_token (stream
);
1221 if (JSC
$parser_get_token (stream
) != JSC
$tIDENTIFIER
)
1222 JSC
$parser_syntax_error ();
1224 id
= JSC
$parser_token_value
;
1225 var ln
= JSC
$parser_token_linenum
;
1228 if (JSC
$nested_function_declarations
.length
> 0)
1230 /* This is a nested function declaration. */
1231 id
= ".F:" + (JSC
$anonymous_function_count
++).toString ();
1233 JSC
$nested_function_declarations
.push (id
);
1235 if (JSC
$parser_get_token (stream
) != #'(')
1236 JSC
$parser_syntax_error ();
1238 /* Formal parameter list opt. */
1239 args
= new Array ();
1240 while (JSC
$parser_peek_token (stream
) != #')')
1242 if (JSC
$parser_get_token (stream
) != JSC
$tIDENTIFIER
)
1243 JSC
$parser_syntax_error ();
1244 args
.push (JSC
$parser_token_value
);
1246 var token
= JSC
$parser_peek_token (stream
);
1249 JSC
$parser_get_token (stream
);
1250 if (JSC
$parser_peek_token (stream
) != JSC
$tIDENTIFIER
)
1251 JSC
$parser_syntax_error ();
1253 else if (token
!= #')')
1254 JSC
$parser_syntax_error ();
1257 if (JSC
$parser_get_token (stream
) != #')')
1258 JSC
$parser_syntax_error ();
1260 JSC
$parser_peek_token (stream
);
1261 var lbrace_ln
= JSC
$parser_peek_token_linenum
;
1263 block
= JSC
$parser_parse_block (stream
);
1264 if (typeof block
== "boolean")
1265 JSC
$parser_syntax_error ();
1267 /* Did the function use the `arguments' identifier? */
1268 var use_arguments
= false;
1269 if (JSC
$num_arguments_identifiers
> num_arguments_identifiers
)
1271 use_arguments
= true;
1272 if (JSC
$warn_deprecated
)
1273 JSC
$warning (JSC
$filename
+ ":" + ln
.toString ()
1274 + ": warning: the `arguments' property of Function "
1275 + "instance is deprecated");
1278 JSC
$functions
.push (new JSC
$function_declaration (ln
, lbrace_ln
, id
,
1280 block
, use_arguments
));
1282 JSC
$nested_function_declarations
.pop ();
1288 function JSC
$parser_parse_block (stream
)
1292 if (JSC
$parser_peek_token (stream
) != #'{')
1295 JSC
$parser_get_token (stream
) != #'{';
1296 var ln
= JSC
$parser_peek_token_linenum
;
1298 /* Do we have a statement list? */
1299 if (JSC
$parser_peek_token (stream
) != #'}')
1301 block
= JSC
$parser_parse_stmt_list (stream
);
1304 block
= new Array ();
1306 if (JSC
$parser_get_token (stream
) != #'}')
1307 JSC
$parser_syntax_error ();
1315 function JSC
$parser_parse_stmt_list (stream
)
1317 var list
, done
, item
;
1319 list
= new Array ();
1324 item
= JSC
$parser_parse_stmt (stream
);
1325 if (typeof item
== "boolean")
1327 /* Can't parse more statements. We'r done. */
1338 function JSC
$parser_parse_stmt (stream
)
1342 if (typeof (item
= JSC
$parser_parse_block (stream
)) != "boolean")
1343 return new JSC
$stmt_block (item
.linenum
, item
);
1344 else if (JSC
$parser_parse_function_declaration (stream
))
1346 /* XXX The function declaration as statement might be incomplete. */
1348 if (JSC
$nested_function_declarations
.length
== 0)
1349 /* Function declaration at top-level statements. */
1350 return new JSC
$stmt_empty (JSC
$parser_token_linenum
);
1352 /* Function declaration inside another function. */
1354 var container_id
= JSC
$nested_function_declarations
.pop ();
1355 JSC
$nested_function_declarations
.push (container_id
);
1357 var f
= JSC
$functions
[JSC
$functions
.length
- 1];
1358 var function_id
= f
.name
;
1359 var given_id
= f
.name_given
;
1361 return new JSC
$stmt_function_declaration (JSC
$parser_token_linenum
,
1362 container_id
, function_id
,
1365 else if (typeof (item
= JSC
$parser_parse_variable_stmt (stream
))
1368 else if (typeof (item
= JSC
$parser_parse_if_stmt (stream
))
1371 else if (typeof (item
= JSC
$parser_parse_iteration_stmt (stream
))
1374 else if (typeof (item
= JSC
$parser_parse_expr (stream
))
1377 if (item
.etype
== JSC
$EXPR_IDENTIFIER
)
1379 /* Possible `Labeled Statement'. */
1380 token
= JSC
$parser_peek_token (stream
);
1381 if (token
== #':' && item
.linenum
== JSC
$parser_peek_token_linenum
)
1384 JSC
$parser_get_token (stream
);
1385 var stmt
= JSC
$parser_parse_stmt (stream
);
1387 JSC
$parser_syntax_error
;
1389 return new JSC
$stmt_labeled_stmt (item
.linenum
, item
.value
,
1395 JSC
$parser_get_semicolon_asci (stream
);
1396 return new JSC
$stmt_expr (item
);
1400 token
= JSC
$parser_peek_token (stream
);
1403 JSC
$parser_get_token (stream
);
1404 return new JSC
$stmt_empty (JSC
$parser_token_linenum
);
1406 else if (token
== JSC
$tCONTINUE
)
1408 JSC
$parser_get_token (stream
);
1410 /* Check the possible label. */
1412 token
= JSC
$parser_peek_token (stream
);
1413 if (token
== JSC
$tIDENTIFIER
1414 && JSC
$parser_token_linenum
== JSC
$parser_peek_token_linenum
)
1416 JSC
$parser_get_token (stream
);
1417 label
= JSC
$parser_token_value
;
1420 item
= new JSC
$stmt_continue (JSC
$parser_token_linenum
, label
);
1422 JSC
$parser_get_semicolon_asci (stream
);
1426 else if (token
== JSC
$tBREAK
)
1428 JSC
$parser_get_token (stream
);
1430 /* Check the possible label. */
1432 token
= JSC
$parser_peek_token (stream
);
1433 if (token
== JSC
$tIDENTIFIER
1434 && JSC
$parser_token_linenum
== JSC
$parser_peek_token_linenum
)
1436 JSC
$parser_get_token (stream
);
1437 label
= JSC
$parser_token_value
;
1440 item
= new JSC
$stmt_break (JSC
$parser_token_linenum
, label
);
1442 JSC
$parser_get_semicolon_asci (stream
);
1446 else if (token
== JSC
$tRETURN
)
1448 JSC
$parser_get_token (stream
);
1449 var linenum
= JSC
$parser_token_linenum
;
1451 if (JSC
$parser_peek_token (stream
) == #';')
1453 /* Consume the semicolon. */
1454 JSC
$parser_get_token (stream
);
1459 if (JSC
$parser_peek_token_linenum
> linenum
)
1462 * A line terminator between tRETURN and the next
1463 * token that is not a semicolon. ASCI here.
1465 if (JSC
$warn_missing_semicolon
)
1466 JSC
$warning (JSC
$filename
+ ":" + linenum
.toString ()
1467 + ": warning: missing semicolon");
1469 JSC
$num_missing_semicolons
++;
1474 item
= JSC
$parser_parse_expr (stream
);
1475 if (typeof item
== "boolean")
1476 JSC
$parser_syntax_error ();
1478 JSC
$parser_get_semicolon_asci (stream
);
1482 return new JSC
$stmt_return (linenum
, item
);
1484 else if (token
== JSC
$tSWITCH
)
1486 JSC
$parser_get_token (stream
);
1487 return JSC
$parser_parse_switch (stream
);
1489 else if (token
== JSC
$tWITH
)
1491 JSC
$parser_get_token (stream
);
1492 var linenum
= JSC
$parser_token_linenum
;
1494 if (JSC
$parser_get_token (stream
) != #'(')
1495 JSC
$parser_syntax_error ();
1497 var expr
= JSC
$parser_parse_expr (stream
);
1498 if (typeof expr
== "boolean")
1499 JSC
$parser_syntax_error ();
1501 if (JSC
$parser_get_token (stream
) != #')')
1502 JSC
$parser_syntax_error ();
1504 var stmt
= JSC
$parser_parse_stmt (stream
);
1505 if (typeof stmt
== "boolean")
1506 JSC
$parser_syntax_error ();
1508 return new JSC
$stmt_with (linenum
, expr
, stmt
);
1510 else if (token
== JSC
$tTRY
)
1512 JSC
$parser_get_token (stream
);
1513 return JSC
$parser_parse_try (stream
);
1515 else if (token
== JSC
$tTHROW
)
1517 JSC
$parser_get_token (stream
);
1518 var linenum
= JSC
$parser_token_linenum
;
1521 * Get the next token's linenum. We need it for strict_ecma
1524 JSC
$parser_peek_token (stream
);
1525 var peek_linenum
= JSC
$parser_peek_token_linenum
;
1527 /* The expression to throw. */
1528 var expr
= JSC
$parser_parse_expr (stream
);
1529 if (typeof expr
== "boolean")
1530 JSC
$parser_syntax_error ();
1532 if (JSC
$warn_strict_ecma
&& peek_linenum
> linenum
)
1533 JSC
$warning (JSC
$filename
+ ":" + JSC
$linenum
.toString ()
1534 + ": warning: ECMAScript don't allow line terminators"
1535 + " between `throw' and expression");
1537 JSC
$parser_get_semicolon_asci (stream
);
1539 return new JSC
$stmt_throw (linenum
, expr
);
1542 /* Can't parse more. We'r done. */
1548 function JSC
$parser_parse_switch (stream
)
1550 var linenum
= JSC
$parser_token_linenum
;
1552 if (JSC
$parser_get_token (stream
) != #'(')
1553 JSC
$parser_syntax_error ();
1555 var expr
= JSC
$parser_parse_expr (stream
);
1557 JSC
$parser_syntax_error ();
1559 if (JSC
$parser_get_token (stream
) != #')')
1560 JSC
$parser_syntax_error ();
1562 if (JSC
$parser_get_token (stream
) != #'{')
1563 JSC
$parser_syntax_error ();
1565 /* Parse case clauses. */
1566 var clauses
= new Array ();
1569 var token
= JSC
$parser_get_token (stream
);
1573 else if (token
== JSC
$tCASE
|| token
== JSC
$tDEFAULT
)
1575 var stmts
= new Array ();
1578 if (token
== JSC
$tCASE
)
1580 stmts
.expr
= JSC
$parser_parse_expr (stream
);
1582 JSC
$parser_syntax_error ();
1584 if (JSC
$parser_get_token (stream
) != #':')
1585 JSC
$parser_syntax_error ();
1587 stmts
.linenum
= JSC
$parser_token_linenum
;
1589 /* Read the statement list. */
1592 token
= JSC
$parser_peek_token (stream
);
1593 if (token
== #'}' || token
== JSC
$tCASE
|| token
== JSC
$tDEFAULT
)
1594 /* Done with this branch. */
1597 var stmt
= JSC
$parser_parse_stmt (stream
);
1599 JSC
$parser_syntax_error ();
1604 stmts
.last_linenum
= JSC
$parser_token_linenum
;
1606 /* One clause parsed. */
1607 clauses
.push (stmts
);
1610 JSC
$parser_syntax_error ();
1613 return new JSC
$stmt_switch (linenum
, JSC
$parser_token_linenum
, expr
,
1618 function JSC
$parser_parse_try (stream
)
1620 var linenum
= JSC
$parser_token_linenum
;
1622 var block
= JSC
$parser_parse_stmt (stream
);
1624 JSC
$parser_syntax_error ();
1626 var try_block_last_linenum
= JSC
$parser_token_linenum
;
1628 /* Now we must see `catch' or `finally'. */
1629 var token
= JSC
$parser_peek_token (stream
);
1630 if (token
!= JSC
$tCATCH
&& token
!= JSC
$tFINALLY
)
1631 JSC
$parser_syntax_error ();
1633 var catch_list
= false;
1634 if (token
== JSC
$tCATCH
)
1636 /* Parse catch list. */
1638 catch_list
= new Array ();
1639 catch_list
.linenum
= JSC
$parser_peek_token_linenum
;
1641 while (token
== JSC
$tCATCH
)
1643 JSC
$parser_get_token (stream
);
1644 var c
= new Object ();
1645 c
.linenum
= JSC
$parser_token_linenum
;
1647 if (JSC
$parser_get_token (stream
) != #'(')
1648 JSC
$parser_syntax_error ();
1650 if (JSC
$parser_get_token (stream
) != JSC
$tIDENTIFIER
)
1651 JSC
$parser_syntax_error ();
1652 c
.id
= JSC
$parser_token_value
;
1655 if (JSC
$parser_peek_token (stream
) == JSC
$tIF
)
1657 JSC
$parser_get_token (stream
);
1658 c
.guard
= JSC
$parser_parse_expr (stream
);
1660 JSC
$parser_syntax_error ();
1663 if (JSC
$parser_get_token (stream
) != #')')
1664 JSC
$parser_syntax_error ();
1666 c
.stmt
= JSC
$parser_parse_stmt (stream
);
1668 JSC
$parser_syntax_error ();
1670 catch_list
.push (c
);
1672 token
= JSC
$parser_peek_token (stream
);
1675 catch_list
.last_linenum
= JSC
$parser_token_linenum
;
1679 if (token
== JSC
$tFINALLY
)
1681 /* Parse the finally. */
1682 JSC
$parser_get_token (stream
);
1684 fin
= JSC
$parser_parse_stmt (stream
);
1686 JSC
$parser_syntax_error ();
1689 return new JSC
$stmt_try (linenum
, try_block_last_linenum
,
1690 JSC
$parser_token_linenum
, block
, catch_list
,
1695 function JSC
$parser_parse_variable_stmt (stream
)
1697 var list
, id
, expr
, token
;
1699 if (JSC
$parser_peek_token (stream
) != JSC
$tVAR
)
1701 JSC
$parser_get_token (stream
);
1702 var ln
= JSC
$parser_token_linenum
;
1704 list
= new Array ();
1708 token
= JSC
$parser_peek_token (stream
);
1709 if (token
== JSC
$tIDENTIFIER
)
1711 JSC
$parser_get_token ();
1712 id
= JSC
$parser_token_value
;
1714 if (JSC
$parser_peek_token (stream
) == #'=')
1716 JSC
$parser_get_token (stream
);
1717 expr
= JSC
$parser_parse_assignment_expr (stream
);
1718 if (typeof expr
== "boolean")
1719 JSC
$parser_syntax_error ();
1724 list
.push (new JSC
$var_declaration (id
, expr
));
1726 /* Check if we have more input. */
1727 if (JSC
$parser_peek_token (stream
) == #',')
1730 JSC
$parser_get_token (stream
);
1732 /* The next token must be tIDENTIFIER. */
1733 if (JSC
$parser_peek_token (stream
) != JSC
$tIDENTIFIER
)
1734 JSC
$parser_syntax_error ();
1739 JSC
$parser_get_semicolon_asci (stream
);
1746 JSC
$parser_get_semicolon_asci (stream
);
1751 /* There must be at least one variable declaration. */
1752 if (list
.length
== 0)
1753 JSC
$parser_syntax_error ();
1755 return new JSC
$stmt_variable (ln
, list
);
1759 function JSC
$parser_parse_if_stmt (stream
)
1761 var expr
, stmt
, stmt2
;
1763 if (JSC
$parser_peek_token (stream
) != JSC
$tIF
)
1765 JSC
$parser_get_token (stream
);
1766 var ln
= JSC
$parser_token_linenum
;
1768 if (JSC
$parser_get_token (stream
) != #'(')
1769 JSC
$parser_syntax_error ();
1771 expr
= JSC
$parser_parse_expr (stream
);
1772 if (typeof expr
== "boolean")
1773 JSC
$parser_syntax_error ();
1775 if (JSC
$parser_get_token (stream
) != #')')
1776 JSC
$parser_syntax_error ();
1778 stmt
= JSC
$parser_parse_stmt (stream
);
1779 if (typeof stmt
== "boolean")
1780 JSC
$parser_syntax_error ();
1782 if (JSC
$parser_peek_token (stream
) == JSC
$tELSE
)
1784 JSC
$parser_get_token (stream
);
1785 stmt2
= JSC
$parser_parse_stmt (stream
);
1786 if (typeof stmt2
== "boolean")
1787 JSC
$parser_syntax_error ();
1792 return new JSC
$stmt_if (ln
, expr
, stmt
, stmt2
);
1796 function JSC
$parser_parse_iteration_stmt (stream
)
1798 var token
, expr1
, expr2
, expr3
, stmt
;
1800 token
= JSC
$parser_peek_token (stream
);
1801 if (token
== JSC
$tDO
)
1803 /* do Statement while (Expression); */
1804 JSC
$parser_get_token (stream
);
1805 var ln
= JSC
$parser_token_linenum
;
1807 stmt
= JSC
$parser_parse_stmt (stream
);
1808 if (typeof stmt
== "boolean")
1809 JSC
$parser_syntax_error ();
1811 if (JSC
$parser_get_token (stream
) != JSC
$tWHILE
)
1812 JSC
$parser_syntax_error ();
1814 if (JSC
$parser_get_token (stream
) != #'(')
1815 JSC
$parser_syntax_error ();
1817 expr1
= JSC
$parser_parse_expr (stream
);
1818 if (typeof expr1
== "boolean")
1819 JSC
$parser_syntax_error ();
1821 if (JSC
$parser_get_token (stream
) != #')')
1822 JSC
$parser_syntax_error ();
1824 JSC
$parser_get_semicolon_asci (stream
);
1826 return new JSC
$stmt_do_while (ln
, expr1
, stmt
);
1828 else if (token
== JSC
$tWHILE
)
1830 /* while (Expression) Statement */
1831 JSC
$parser_get_token (stream
);
1832 var ln
= JSC
$parser_token_linenum
;
1834 if (JSC
$parser_get_token (stream
) != #'(')
1835 JSC
$parser_syntax_error ();
1837 expr1
= JSC
$parser_parse_expr (stream
);
1838 if (typeof expr1
== "boolean")
1839 JSC
$parser_syntax_error ();
1841 if (JSC
$parser_get_token (stream
) != #')')
1842 JSC
$parser_syntax_error ();
1844 stmt
= JSC
$parser_parse_stmt (stream
);
1845 if (typeof stmt
== "boolean")
1846 JSC
$parser_syntax_error ();
1848 return new JSC
$stmt_while (ln
, expr1
, stmt
);
1850 else if (token
== JSC
$tFOR
)
1852 JSC
$parser_get_token (stream
);
1853 var ln
= JSC
$parser_token_linenum
;
1855 if (JSC
$parser_get_token (stream
) != #'(')
1856 JSC
$parser_syntax_error ();
1862 token
= JSC
$parser_peek_token (stream
);
1863 if (token
== JSC
$tVAR
)
1865 JSC
$parser_get_token (stream
);
1866 vars
= new Array ();
1870 /* The identifier. */
1871 token
= JSC
$parser_peek_token (stream
);
1872 if (token
!= JSC
$tIDENTIFIER
)
1875 JSC
$parser_get_token (stream
);
1876 var id
= JSC
$parser_token_value
;
1878 /* Possible initializer. */
1880 if (JSC
$parser_peek_token (stream
) == #'=')
1882 JSC
$parser_get_token (stream
);
1883 expr
= JSC
$parser_parse_assignment_expr (stream
);
1885 JSC
$parser_syntax_error ();
1888 vars
.push (new JSC
$var_declaration (id
, expr
));
1890 /* Check if we have more input. */
1891 if (JSC
$parser_peek_token (stream
) == #',')
1894 JSC
$parser_get_token (stream
);
1896 /* The next token must be tIDENTIFIER. */
1897 if (JSC
$parser_peek_token (stream
) != JSC
$tIDENTIFIER
)
1898 JSC
$parser_syntax_error ();
1901 /* No more input. */
1905 /* Must have at least one variable declaration. */
1906 if (vars
.length
== 0)
1907 JSC
$parser_syntax_error ();
1909 else if (token
!= #';')
1911 expr1
= JSC
$parser_parse_expr (stream
);
1912 if (typeof expr1
== "boolean")
1913 JSC
$parser_syntax_error ();
1918 token
= JSC
$parser_get_token (stream
);
1923 /* Normal for-statement. */
1926 if (JSC
$parser_peek_token (stream
) != #';')
1928 expr2
= JSC
$parser_parse_expr (stream
);
1929 if (typeof expr2
== "boolean")
1930 JSC
$parser_syntax_error ();
1935 if (JSC
$parser_get_token (stream
) != #';')
1936 JSC
$parser_syntax_error ();
1939 if (JSC
$parser_peek_token (stream
) != #')')
1941 expr3
= JSC
$parser_parse_expr (stream
);
1942 if (typeof expr3
== "boolean")
1943 JSC
$parser_syntax_error ();
1948 else if (token
== JSC
$tIN
)
1950 /* The `for (VAR in EXPR)'-statement. */
1956 /* The first expression must be an identifier. */
1957 if (expr1
.etype
!= JSC
$EXPR_IDENTIFIER
)
1958 JSC
$parser_syntax_error ();
1962 /* We must have only one variable declaration. */
1963 if (vars
.length
!= 1)
1964 JSC
$parser_syntax_error ();
1967 /* The second expressions. */
1968 expr2
= JSC
$parser_parse_expr (stream
);
1969 if (typeof expr2
== "boolean")
1970 JSC
$parser_syntax_error ();
1973 JSC
$parser_syntax_error ();
1975 if (JSC
$parser_get_token (stream
) != #')')
1976 JSC
$parser_syntax_error ();
1979 stmt
= JSC
$parser_parse_stmt (stream
);
1980 if (typeof stmt
== "boolean")
1981 JSC
$parser_syntax_error ();
1984 return new JSC
$stmt_for_in (ln
, vars
, expr1
, expr2
, stmt
);
1986 return new JSC
$stmt_for (ln
, vars
, expr1
, expr2
, expr3
, stmt
);
1992 function JSC
$parser_parse_expr (stream
)
1996 if (typeof (expr
= JSC
$parser_parse_assignment_expr (stream
))
2000 /* Check for the comma expression. */
2001 while (JSC
$parser_peek_token (stream
) == #',')
2003 JSC
$parser_get_token (stream
);
2004 var ln
= JSC
$parser_token_linenum
;
2006 if (typeof (expr2
= JSC
$parser_parse_assignment_expr (stream
))
2008 JSC
$parser_syntax_error ();
2009 expr
= new JSC
$expr_comma (ln
, expr
, expr2
);
2016 function JSC
$parser_parse_assignment_expr (stream
)
2018 var expr
, expr2
, token
;
2020 if (typeof (expr
= JSC
$parser_parse_conditional_expr (stream
))
2024 if (JSC
$parser_expr_is_left_hand_side (expr
))
2026 token
= JSC
$parser_peek_token (stream
);
2027 if (token
== #'=' || token
== JSC
$tMULA
2028 || token
== JSC
$tDIVA
|| token
== JSC
$tMODA
2029 || token
== JSC
$tADDA
|| token
== JSC
$tSUBA
2030 || token
== JSC
$tLSIA
|| token
== JSC
$tRSIA
2031 || token
== JSC
$tRRSA
|| token
== JSC
$tANDA
2032 || token
== JSC
$tXORA
|| token
== JSC
$tORA
)
2034 JSC
$parser_get_token (stream
);
2035 var ln
= JSC
$parser_token_linenum
;
2037 expr2
= JSC
$parser_parse_assignment_expr (stream
);
2038 if (typeof expr2
== "boolean")
2039 JSC
$parser_syntax_error ();
2041 expr
= new JSC
$expr_assignment (ln
, token
, expr
, expr2
);
2045 if (JSC
$optimize_constant_folding
&& expr
.constant_folding
)
2046 return expr
.constant_folding ();
2052 function JSC
$parser_parse_conditional_expr (stream
)
2054 var expr
, expr2
, expr3
, token
;
2056 if (typeof (expr
= JSC
$parser_parse_logical_or_expr (stream
))
2060 token
= JSC
$parser_peek_token (stream
);
2063 JSC
$parser_get_token (stream
);
2064 var ln
= JSC
$parser_token_linenum
;
2066 expr2
= JSC
$parser_parse_assignment_expr (stream
);
2067 if (typeof expr2
== "boolean")
2068 JSC
$parser_syntax_error ();
2070 if (JSC
$parser_get_token (stream
) != #':')
2071 JSC
$parser_syntax_error ();
2072 expr3
= JSC
$parser_parse_assignment_expr (stream
);
2073 if (typeof expr3
== "boolean")
2074 JSC
$parser_syntax_error ();
2076 expr
= new JSC
$expr_quest_colon (ln
, expr
, expr2
, expr3
);
2083 function JSC
$parser_parse_logical_or_expr (stream
)
2087 if (typeof (expr
= JSC
$parser_parse_logical_and_expr (stream
))
2091 while (JSC
$parser_peek_token (stream
) == JSC
$tOR
)
2093 JSC
$parser_get_token (stream
);
2094 var ln
= JSC
$parser_token_linenum
;
2096 expr2
= JSC
$parser_parse_logical_and_expr (stream
);
2097 if (typeof expr2
== "boolean")
2098 JSC
$parser_syntax_error ();
2100 expr
= new JSC
$expr_logical_or (ln
, expr
, expr2
);
2107 function JSC
$parser_parse_logical_and_expr (stream
)
2111 if (typeof (expr
= JSC
$parser_parse_bitwise_or_expr (stream
))
2115 while (JSC
$parser_peek_token (stream
) == JSC
$tAND
)
2117 JSC
$parser_get_token (stream
);
2118 var ln
= JSC
$parser_token_linenum
;
2120 expr2
= JSC
$parser_parse_bitwise_or_expr (stream
);
2121 if (typeof expr2
== "boolean")
2122 JSC
$parser_syntax_error ();
2124 expr
= new JSC
$expr_logical_and (ln
, expr
, expr2
);
2131 function JSC
$parser_parse_bitwise_or_expr (stream
)
2135 if (typeof (expr
= JSC
$parser_parse_bitwise_xor_expr (stream
))
2139 while (JSC
$parser_peek_token (stream
) == #'|')
2141 JSC
$parser_get_token (stream
);
2142 var ln
= JSC
$parser_token_linenum
;
2144 expr2
= JSC
$parser_parse_bitwise_xor_expr (stream
);
2145 if (typeof expr2
== "boolean")
2146 JSC
$parser_syntax_error ();
2148 expr
= new JSC
$expr_bitwise_or (ln
, expr
, expr2
);
2155 function JSC
$parser_parse_bitwise_xor_expr (stream
)
2159 if (typeof (expr
= JSC
$parser_parse_bitwise_and_expr (stream
))
2163 while (JSC
$parser_peek_token (stream
) == #'^')
2165 JSC
$parser_get_token (stream
);
2166 var ln
= JSC
$parser_token_linenum
;
2168 expr2
= JSC
$parser_parse_bitwise_and_expr (stream
);
2169 if (typeof expr2
== "boolean")
2170 JSC
$parser_syntax_error ();
2172 expr
= new JSC
$expr_bitwise_xor (ln
, expr
, expr2
);
2179 function JSC
$parser_parse_bitwise_and_expr (stream
)
2183 if (typeof (expr
= JSC
$parser_parse_equality_expr (stream
))
2187 while (JSC
$parser_peek_token (stream
) == #'&')
2189 JSC
$parser_get_token (stream
);
2190 var ln
= JSC
$parser_token_linenum
;
2192 expr2
= JSC
$parser_parse_equality_expr (stream
);
2193 if (typeof expr2
== "boolean")
2194 JSC
$parser_syntax_error ();
2196 expr
= new JSC
$expr_bitwise_and (ln
, expr
, expr2
);
2203 function JSC
$parser_parse_equality_expr (stream
)
2205 var expr
, expr2
, token
;
2207 if (typeof (expr
= JSC
$parser_parse_relational_expr (stream
))
2211 token
= JSC
$parser_peek_token (stream
);
2212 while (token
== JSC
$tEQUAL
|| token
== JSC
$tNEQUAL
2213 || token
== JSC
$tSEQUAL
|| token
== JSC
$tSNEQUAL
)
2215 JSC
$parser_get_token (stream
);
2216 var ln
= JSC
$parser_token_linenum
;
2218 expr2
= JSC
$parser_parse_relational_expr (stream
);
2219 if (typeof expr2
== "boolean")
2220 JSC
$parser_syntax_error ();
2222 expr
= new JSC
$expr_equality (ln
, token
, expr
, expr2
);
2223 token
= JSC
$parser_peek_token (stream
);
2230 function JSC
$parser_parse_relational_expr (stream
)
2232 var expr
, expr2
, token
;
2234 if (typeof (expr
= JSC
$parser_parse_shift_expr (stream
))
2238 token
= JSC
$parser_peek_token (stream
);
2239 while (token
== #'<' || token
== #'>' || token
== JSC
$tLE
2240 || token
== JSC
$tGE
)
2242 JSC
$parser_get_token (stream
);
2243 var ln
= JSC
$parser_token_linenum
;
2245 expr2
= JSC
$parser_parse_shift_expr (stream
);
2246 if (typeof expr2
== "boolean")
2247 JSC
$parser_syntax_error ();
2249 expr
= new JSC
$expr_relational (ln
, token
, expr
, expr2
);
2250 token
= JSC
$parser_peek_token (stream
);
2257 function JSC
$parser_parse_shift_expr (stream
)
2259 var expr
, expr2
, token
;
2261 if (typeof (expr
= JSC
$parser_parse_additive_expr (stream
))
2265 token
= JSC
$parser_peek_token (stream
);
2266 while (token
== JSC
$tLSHIFT
|| token
== JSC
$tRSHIFT
|| token
== JSC
$tRRSHIFT
)
2268 JSC
$parser_get_token (stream
);
2269 var ln
= JSC
$parser_token_linenum
;
2271 expr2
= JSC
$parser_parse_additive_expr (stream
);
2273 if (typeof expr2
== "boolean")
2274 JSC
$parser_syntax_error ();
2276 expr
= new JSC
$expr_shift (ln
, token
, expr
, expr2
);
2277 token
= JSC
$parser_peek_token (stream
);
2284 function JSC
$parser_parse_additive_expr (stream
)
2286 var expr
, expr2
, token
;
2288 if (typeof (expr
= JSC
$parser_parse_multiplicative_expr (stream
))
2292 token
= JSC
$parser_peek_token (stream
);
2293 while (token
== #'+' || token
== #'-')
2295 JSC
$parser_get_token (stream
);
2296 var ln
= JSC
$parser_token_linenum
;
2298 expr2
= JSC
$parser_parse_multiplicative_expr (stream
);
2299 if (typeof expr2
== "boolean")
2300 JSC
$parser_syntax_error ();
2302 expr
= new JSC
$expr_additive (ln
, token
, expr
, expr2
);
2303 token
= JSC
$parser_peek_token (stream
);
2310 function JSC
$parser_parse_multiplicative_expr (stream
)
2312 var expr
, expr2
, token
;
2314 if (typeof (expr
= JSC
$parser_parse_unary_expr (stream
)) == "boolean")
2317 token
= JSC
$parser_peek_token (stream
);
2318 while (token
== #'*' || token
== #'/' || token
== #'%')
2320 JSC
$parser_get_token (stream
);
2321 var ln
= JSC
$parser_token_linenum
;
2323 expr2
= JSC
$parser_parse_unary_expr (stream
);
2324 if (typeof expr2
== "boolean")
2325 JSC
$parser_syntax_error ();
2327 expr
= new JSC
$expr_multiplicative (ln
, token
, expr
, expr2
);
2328 token
= JSC
$parser_peek_token (stream
);
2335 function JSC
$parser_parse_unary_expr (stream
)
2339 token
= JSC
$parser_peek_token (stream
);
2340 if (token
== JSC
$tDELETE
2341 || token
== JSC
$tVOID
2342 || token
== JSC
$tTYPEOF
2343 || token
== JSC
$tPLUSPLUS
2344 || token
== JSC
$tMINUSMINUS
2350 JSC
$parser_get_token (stream
);
2351 var ln
= JSC
$parser_token_linenum
;
2353 expr
= JSC
$parser_parse_unary_expr (stream
);
2354 if (typeof expr
== "boolean")
2355 JSC
$parser_syntax_error ();
2357 return new JSC
$expr_unary (ln
, token
, expr
);
2360 return JSC
$parser_parse_postfix_expr (stream
);
2364 function JSC
$parser_parse_postfix_expr (stream
)
2368 if (typeof (expr
= JSC
$parser_parse_left_hand_side_expr (stream
))
2372 token
= JSC
$parser_peek_token (stream
);
2373 if (token
== JSC
$tPLUSPLUS
|| token
== JSC
$tMINUSMINUS
)
2375 if (JSC
$parser_peek_token_linenum
> JSC
$parser_token_linenum
)
2377 if (JSC
$warn_missing_semicolon
)
2378 JSC
$warning (JSC
$filename
+ ":"
2379 + JSC
$parser_token_linenum
.toString ()
2380 + ": warning: automatic semicolon insertion cuts the expression before ++ or --");
2384 JSC
$parser_get_token (stream
);
2385 var ln
= JSC
$parser_token_linenum
;
2387 return new JSC
$expr_postfix (ln
, token
, expr
);
2395 function JSC
$parser_parse_left_hand_side_expr (stream
)
2397 var expr
, args
, token
, expr2
;
2399 if (typeof (expr
= JSC
$parser_parse_member_expr (stream
))
2403 /* Parse the possible first pair of arguments. */
2404 if (JSC
$parser_peek_token (stream
) == #'(')
2406 var ln
= JSC
$parser_peek_token_linenum
;
2408 args
= JSC
$parser_parse_arguments (stream
);
2409 if (typeof args
== "boolean")
2410 JSC
$parser_syntax_error ();
2412 expr
= new JSC
$expr_call (ln
, expr
, args
);
2417 /* Parse to possibly following arguments and selectors. */
2418 while ((token
= JSC
$parser_peek_token (stream
)) == #'('
2419 || token
== #'[' || token
== #'.')
2421 var ln
= JSC
$parser_peek_token_linenum
;
2425 args
= JSC
$parser_parse_arguments (stream
);
2426 expr
= new JSC
$expr_call (ln
, expr
, args
);
2428 else if (token
== #'[')
2430 JSC
$parser_get_token (stream
);
2432 expr2
= JSC
$parser_parse_expr (stream
);
2433 if (typeof expr2
== "boolean")
2434 JSC
$parser_syntax_error ();
2436 if (JSC
$parser_get_token (stream
) != #']')
2437 JSC
$parser_syntax_error ();
2439 expr
= new JSC
$expr_object_array (ln
, expr
, expr2
);
2443 JSC
$parser_get_token (stream
);
2444 if (JSC
$parser_get_token (stream
) != JSC
$tIDENTIFIER
)
2445 JSC
$parser_syntax_error ();
2447 expr
= new JSC
$expr_object_property (ln
, expr
,
2448 JSC
$parser_token_value
);
2456 function JSC
$parser_parse_member_expr (stream
)
2458 var expr
, args
, token
, expr2
;
2460 if (typeof (expr
= JSC
$parser_parse_primary_expr (stream
))
2463 token
= JSC
$parser_peek_token (stream
);
2465 if (token
== JSC
$tNEW
)
2467 JSC
$parser_get_token (stream
);
2468 var ln
= JSC
$parser_token_linenum
;
2470 expr
= JSC
$parser_parse_member_expr (stream
);
2471 if (typeof expr
== "boolean")
2472 JSC
$parser_syntax_error ();
2474 if (JSC
$parser_peek_token (stream
) == #'(')
2476 args
= JSC
$parser_parse_arguments (stream
);
2477 if (typeof args
== "boolean")
2478 JSC
$parser_syntax_error ();
2481 return new JSC
$expr_new (ln
, expr
, null);
2483 expr
= new JSC
$expr_new (ln
, expr
, args
);
2489 /* Ok, now we have valid starter. */
2490 token
= JSC
$parser_peek_token (stream
);
2491 while (token
== #'[' || token
== #'.')
2493 JSC
$parser_get_token (stream
);
2494 var ln
= JSC
$parser_token_linenum
;
2498 expr2
= JSC
$parser_parse_expr (stream
);
2499 if (typeof expr2
== "boolean")
2500 JSC
$parser_syntax_error ();
2502 if (JSC
$parser_get_token (stream
) != #']')
2503 JSC
$parser_syntax_error ();
2505 expr
= new JSC
$expr_object_array (ln
, expr
, expr2
);
2509 if (JSC
$parser_get_token (stream
) != JSC
$tIDENTIFIER
)
2510 JSC
$parser_syntax_error ();
2512 expr
= new JSC
$expr_object_property (ln
, expr
,
2513 JSC
$parser_token_value
);
2516 token
= JSC
$parser_peek_token (stream
);
2523 function JSC
$parser_parse_primary_expr (stream
)
2527 token
= JSC
$parser_peek_token (stream
);
2528 var ln
= JSC
$parser_peek_token_linenum
;
2530 if (token
== JSC
$tTHIS
)
2531 val
= new JSC
$expr_this (ln
);
2532 else if (token
== JSC
$tIDENTIFIER
)
2533 val
= new JSC
$expr_identifier (ln
, JSC
$parser_peek_token_value
);
2534 else if (token
== JSC
$tFLOAT
)
2535 val
= new JSC
$expr_float (ln
, JSC
$parser_peek_token_value
);
2536 else if (token
== JSC
$tINTEGER
)
2537 val
= new JSC
$expr_integer (ln
, JSC
$parser_peek_token_value
);
2538 else if (token
== JSC
$tSTRING
)
2539 val
= new JSC
$expr_string (ln
, JSC
$parser_peek_token_value
);
2540 else if (token
== #'/')
2543 * Kludge alert! The regular expression constants (/.../) and
2544 * div operands are impossible to distinguish, based only on the
2545 * lexical analysis. Therefore, we need some syntactical
2546 * knowledge when the regular expression constants are possible
2547 * at all. This is the place where they can appear. In all
2548 * other places, the character `/' is interpreted as a div
2551 JSC
$parser_get_token (stream
);
2553 return new JSC
$expr_regexp (ln
, JSC
$lexer_read_regexp_constant (stream
));
2555 else if (token
== JSC
$tNULL
)
2556 val
= new JSC
$expr_null (ln
);
2557 else if (token
== JSC
$tTRUE
)
2558 val
= new JSC
$expr_true (ln
);
2559 else if (token
== JSC
$tFALSE
)
2560 val
= new JSC
$expr_false (ln
);
2561 else if (token
== #'[')
2563 /* Array initializer. */
2564 /* TODO: SharpVarDefinition_{opt} */
2566 JSC
$parser_get_token (stream
);
2568 var items
= new Array ();
2571 while ((token
= JSC
$parser_peek_token (stream
)) != #']')
2575 JSC
$parser_get_token (stream
);
2576 items
[++pos
] = false;
2580 var expr
= JSC
$parser_parse_assignment_expr (stream
);
2582 JSC
$parser_syntax_error ();
2586 /* Got one expression. It must be followed by ',' or ']'. */
2587 token
= JSC
$parser_peek_token (stream
);
2588 if (token
!= #',' && token
!= #']')
2589 JSC
$parser_syntax_error ();
2592 val
= new JSC
$expr_array_initializer (ln
, items
);
2594 else if (token
== #'{')
2596 /* Object literal. */
2597 /* TODO: SharpVarDefinition_{opt} */
2599 JSC
$parser_get_token (stream
);
2601 var items
= new Array ();
2603 while ((token
= JSC
$parser_peek_token (stream
)) != #'}')
2605 var pair
= new Object ();
2607 token
= JSC
$parser_get_token (stream
);
2609 pair
.linenum
= JSC
$linenum
;
2610 pair
.id_type
= token
;
2611 pair
.id
= JSC
$parser_token_value
;
2613 if (token
!= JSC
$tIDENTIFIER
&& token
!= JSC
$tSTRING
2614 && token
!= JSC
$tINTEGER
)
2615 JSC
$parser_syntax_error ();
2617 if (JSC
$parser_get_token (stream
) != #':')
2618 JSC
$parser_syntax_error ();
2620 pair
.expr
= JSC
$parser_parse_assignment_expr (stream
);
2622 JSC
$parser_syntax_error ();
2627 * Got one property, initializer pair. It must be followed
2630 token
= JSC
$parser_peek_token (stream
);
2633 /* Ok, we have more items. */
2634 JSC
$parser_get_token (stream
);
2636 token
= JSC
$parser_peek_token (stream
);
2637 if (token
!= JSC
$tIDENTIFIER
&& token
!= JSC
$tSTRING
2638 && token
!= JSC
$tINTEGER
)
2639 JSC
$parser_syntax_error ();
2641 else if (token
!= #'}' && token
)
2642 JSC
$parser_syntax_error ();
2645 val
= new JSC
$expr_object_initializer (ln
, items
);
2647 else if (token
== #'(')
2649 JSC
$parser_get_token (stream
);
2651 val
= JSC
$parser_parse_expr (stream
);
2652 if (typeof val
== "boolean"
2653 || JSC
$parser_peek_token (stream
) != #')')
2654 JSC
$parser_syntax_error ();
2659 JSC
$parser_get_token (stream
);
2664 function JSC
$parser_parse_arguments (stream
)
2668 if (JSC
$parser_peek_token (stream
) != #'(')
2671 args
= new Array ();
2673 JSC
$parser_get_token (stream
);
2674 while (JSC
$parser_peek_token (stream
) != #')')
2676 item
= JSC
$parser_parse_assignment_expr (stream
);
2677 if (typeof item
== "boolean")
2678 JSC
$parser_syntax_error ();
2681 var token
= JSC
$parser_peek_token (stream
);
2683 JSC
$parser_get_token (stream
);
2684 else if (token
!= #')')
2685 JSC
$parser_syntax_error ();
2687 JSC
$parser_get_token (stream
);
2699 * Grammar components.
2700 * Copyright (c) 1998 New Generation Software (NGS) Oy
2702 * Author: Markku Rossi <mtr@ngs.fi>
2706 * This library is free software; you can redistribute it and/or
2707 * modify it under the terms of the GNU Library General Public
2708 * License as published by the Free Software Foundation; either
2709 * version 2 of the License, or (at your option) any later version.
2711 * This library is distributed in the hope that it will be useful,
2712 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2713 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2714 * Library General Public License for more details.
2716 * You should have received a copy of the GNU Library General Public
2717 * License along with this library; if not, write to the Free
2718 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
2719 * MA 02111-1307, USA
2723 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/jsc/compiler.js,v $
2727 /* General helpers. */
2729 function JSC
$gram_reset ()
2731 JSC
$label_count
= 1;
2732 JSC
$cont_break
= new JSC
$ContBreak ();
2736 function JSC
$alloc_label (num_labels
)
2738 JSC
$label_count
+= num_labels
;
2740 return JSC
$label_count
- num_labels
;
2744 function JSC
$format_label (num
)
2746 return ".L" + num
.toString ();
2750 function JSC
$count_locals_from_stmt_list (list
)
2754 /* First, count how many variables we need at the toplevel. */
2756 for (i
= 0; i
< list
.length
; i
++)
2757 lcount
+= list
[i
].count_locals (false);
2759 /* Second, count the maximum amount needed by the nested blocks. */
2761 for (i
= 0; i
< list
.length
; i
++)
2763 var rc
= list
[i
].count_locals (true);
2768 return lcount
+ rmax
;
2772 * The handling of the `continue' and `break' labels for looping
2773 * constructs. The variable `JSC$cont_break' holds an instance of
2774 * JSC$ContBreak class. The instance contains a valid chain of
2775 * looping constructs and the currently active with and try testing
2776 * levels. The actual `continue', `break', and `return' statements
2777 * investigate the chain and generate appropriate `with_pop' and
2778 * `try_pop' operands.
2780 * If the instance variable `inswitch' is true, the continue statement
2781 * is inside a switch statement. In this case, the continue statement
2782 * must pop one item from the stack. That item is the value of the
2786 function JSC
$ContBreakFrame (loop_break
, loop_continue
, inswitch
, label
, next
)
2788 this.loop_break
= loop_break
;
2789 this.loop_continue
= loop_continue
;
2790 this.inswitch
= inswitch
;
2794 this.with_nesting
= 0;
2795 this.try_nesting
= 0;
2799 function JSC
$ContBreak ()
2801 this.top
= new JSC
$ContBreakFrame (null, null, false, null);
2804 new JSC
$ContBreak ();
2806 function JSC
$ContBreak
$push (loop_break
, loop_continue
, inswitch
, label
)
2808 this.top
= new JSC
$ContBreakFrame (loop_break
, loop_continue
, inswitch
,
2811 JSC
$ContBreak
.prototype.push
= JSC
$ContBreak
$push
;
2813 function JSC
$ContBreak
$pop ()
2815 if (this.top
== null)
2816 error ("jsc: internal error: continue-break stack underflow");
2818 this.top
= this.top
.next
;
2820 JSC
$ContBreak
.prototype.pop
= JSC
$ContBreak
$pop
;
2823 * Count the currently active `try' nesting that should be removed on
2824 * `return' statement.
2826 function JSC
$ContBreak
$try_return_nesting ()
2831 for (f
= this.top
; f
; f
= f
.next
)
2832 count
+= f
.try_nesting
;
2836 JSC
$ContBreak
.prototype.try_return_nesting
= JSC
$ContBreak
$try_return_nesting
;
2839 * Count currently active `with' nesting that should be removed on
2840 * `continue' or `break' statement.
2842 function JSC
$ContBreak
$count_with_nesting (label
)
2847 for (f
= this.top
; f
; f
= f
.next
)
2849 count
+= f
.with_nesting
;
2852 if (f
.label
== label
)
2856 if (f
.loop_continue
)
2861 JSC
$ContBreak
.prototype.count_with_nesting
= JSC
$ContBreak
$count_with_nesting
;
2864 * Count the currently active `try' nesting that should be removed on
2865 * `continue' or `break' statement.
2867 function JSC
$ContBreak
$count_try_nesting (label
)
2872 for (f
= this.top
; f
; f
= f
.next
)
2874 count
+= f
.try_nesting
;
2877 if (f
.label
== label
)
2881 if (f
.loop_continue
)
2886 JSC
$ContBreak
.prototype.count_try_nesting
= JSC
$ContBreak
$count_try_nesting
;
2888 function JSC
$ContBreak
$count_switch_nesting (label
)
2893 for (f
= this.top
; f
; f
= f
.next
)
2899 if (f
.label
== label
)
2903 if (f
.loop_continue
)
2908 JSC
$ContBreak
.prototype.count_switch_nesting
2909 = JSC
$ContBreak
$count_switch_nesting
;
2911 function JSC
$ContBreak
$get_continue (label
)
2915 for (f
= this.top
; f
; f
= f
.next
)
2918 if (f
.label
== label
)
2919 return f
.loop_continue
;
2922 if (f
.loop_continue
)
2923 return f
.loop_continue
;
2927 JSC
$ContBreak
.prototype.get_continue
= JSC
$ContBreak
$get_continue
;
2929 function JSC
$ContBreak
$get_break (label
)
2933 for (f
= this.top
; f
; f
= f
.next
)
2936 if (f
.label
== label
)
2937 return f
.loop_break
;
2941 return f
.loop_break
;
2945 JSC
$ContBreak
.prototype.get_break
= JSC
$ContBreak
$get_break
;
2947 function JSC
$ContBreak
$is_unique_label (label
)
2951 for (f
= this.top
; f
; f
= f
.next
)
2952 if (f
.label
== label
)
2957 JSC
$ContBreak
.prototype.is_unique_label
= JSC
$ContBreak
$is_unique_label
;
2959 JSC
$cont_break
= null;
2962 /* Function declaration. */
2964 function JSC
$function_declaration (ln
, lbrace_ln
, name
, name_given
, args
,
2965 block
, use_arguments_prop
)
2968 this.lbrace_linenum
= lbrace_ln
;
2970 this.name_given
= name_given
;
2973 this.use_arguments_prop
= use_arguments_prop
;
2974 this.asm
= JSC
$function_declaration_asm
;
2977 function JSC
$function_declaration_asm ()
2981 /* Define arguments. */
2982 JSC
$ns
.push_frame ();
2984 for (i
= 0, a
= 2; i
< this.args
.length
; i
++, a
++)
2985 JSC
$ns
.define_symbol (this.args
[i
], JSC
$SCOPE_ARG
, a
, this.linenum
);
2987 /* Define the function name to be a global symbol. */
2988 new JSC
$ASM_symbol (this.linenum
, this.name
).link ();
2990 /* Check that function gets the required amount of arguments. */
2991 new JSC
$ASM_load_arg (this.lbrace_linenum
, 1).link ();
2992 new JSC
$ASM_add_2_i (this.lbrace_linenum
).link ();
2993 new JSC
$ASM_min_args (this.lbrace_linenum
, this.args
.length
+ 2).link ();
2995 /* Count how many local variables we need. */
2996 var num_locals
= JSC
$count_locals_from_stmt_list (this.block
);
2998 /* Is the `arguments' property of function instance used? */
2999 if (this.use_arguments_prop
)
3004 new JSC
$ASM_locals (this.lbrace_linenum
, num_locals
).link ();
3005 if (this.use_arguments_prop
)
3008 * Create an array for the arguments array and store it to
3009 * the first local variable.
3011 var ln
= this.lbrace_linenum
;
3012 var locn
= JSC
$ns
.alloc_local ();
3013 JSC
$ns
.define_symbol ("arguments", JSC
$SCOPE_LOCAL
, locn
, ln
);
3015 new JSC
$ASM_const_i0 (ln
).link ();
3016 new JSC
$ASM_load_global (ln
, "Array").link ();
3017 new JSC
$ASM_new (ln
).link ();
3018 new JSC
$ASM_swap (ln
).link ();
3019 new JSC
$ASM_apop (ln
, 2).link ();
3020 new JSC
$ASM_store_local (ln
, locn
).link ();
3022 /* Push individual argumens to the array. */
3024 /* Init the loop counter. */
3025 new JSC
$ASM_const_i0 (ln
).link ();
3027 var l_loop
= new JSC
$ASM_label ();
3028 var l_out
= new JSC
$ASM_label ();
3032 /* Check if we'r done. */
3033 new JSC
$ASM_dup (ln
).link ();
3034 new JSC
$ASM_load_arg (ln
, 1).link ();
3035 new JSC
$ASM_cmp_ge (ln
).link ();
3036 new JSC
$ASM_iftrue_b (ln
, l_out
).link ();
3038 /* Load the nth argument to the top of the stack. */
3039 new JSC
$ASM_dup (ln
).link ();
3040 new JSC
$ASM_add_2_i (ln
).link ();
3041 new JSC
$ASM_load_nth_arg (ln
).link ();
3043 /* Push it to the array. */
3044 new JSC
$ASM_const_i1 (ln
).link ();
3045 new JSC
$ASM_load_local (ln
, locn
).link ();
3046 new JSC
$ASM_call_method (ln
, "push").link ();
3047 new JSC
$ASM_pop_n (ln
, 4).link ();
3049 /* Increment loop counter and continue. */
3050 new JSC
$ASM_add_1_i (ln
).link ();
3051 new JSC
$ASM_jmp (ln
, l_loop
).link ();
3056 /* Pop the loop counter. */
3057 new JSC
$ASM_pop (ln
).link ();
3061 /* Assembler for our body. */
3062 for (i
= 0; i
< this.block
.length
; i
++)
3063 this.block
[i
].asm ();
3066 * Every function must return something. We could check if all
3067 * control flows in this function ends to a return, but that would
3068 * bee too hard... Just append a return const_undefined. The optimizer
3069 * will remove it if it is not needed.
3072 if (this.block
.length
> 0)
3073 ln
= this.block
[this.block
.length
- 1].linenum
;
3077 new JSC
$ASM_const_undefined (ln
).link ();
3078 new JSC
$ASM_return (ln
).link ();
3080 /* Pop our namespace. */
3081 JSC
$ns
.pop_frame ();
3085 function JSC
$zero_function ()
3097 function JSC
$stmt_block (ln
, list
)
3099 this.stype
= JSC
$STMT_BLOCK
;
3102 this.asm
= JSC
$stmt_block_asm
;
3103 this.count_locals
= JSC
$stmt_block_count_locals
;
3106 function JSC
$stmt_block_asm ()
3108 JSC
$ns
.push_frame ();
3110 /* Assembler for our stmts. */
3112 for (i
= 0; i
< this.stmts
.length
; i
++)
3113 this.stmts
[i
].asm ();
3115 JSC
$ns
.pop_frame ();
3119 function JSC
$stmt_block_count_locals (recursive
)
3124 return JSC
$count_locals_from_stmt_list (this.stmts
);
3127 /* Function declaration. */
3129 function JSC
$stmt_function_declaration (ln
, container_id
, function_id
,
3132 this.stype
= JSC
$STMT_FUNCTION_DECLARATION
;
3134 this.container_id
= container_id
;
3135 this.function_id
= function_id
;
3136 this.given_id
= given_id
;
3137 this.asm
= JSC
$stmt_function_declaration_asm
;
3138 this.count_locals
= JSC
$zero_function
;
3141 function JSC
$stmt_function_declaration_asm ()
3143 new JSC
$ASM_load_global (this.linenum
, this.function_id
).link ();
3144 new JSC
$ASM_load_global (this.linenum
, this.container_id
).link ();
3145 new JSC
$ASM_store_property (this.linenum
, this.given_id
).link ();
3150 function JSC
$stmt_empty (ln
)
3152 this.stype
= JSC
$STMT_EMPTY
;
3154 this.asm
= JSC
$stmt_empty_asm
;
3155 this.count_locals
= JSC
$zero_function
;
3158 function JSC
$stmt_empty_asm ()
3166 function JSC
$stmt_continue (ln
, label
)
3168 this.stype
= JSC
$STMT_CONTINUE
;
3171 this.asm
= JSC
$stmt_continue_asm
;
3172 this.count_locals
= JSC
$zero_function
;
3175 function JSC
$stmt_continue_asm ()
3177 var l_cont
= JSC
$cont_break
.get_continue (this.label
);
3182 error (JSC
$filename
+ ":" + this.linenum
.toString ()
3183 + ": label `" + this.label
3184 + "' not found for continue statement");
3186 error (JSC
$filename
+ ":" + this.linenum
.toString ()
3187 + ": continue statement not within a loop");
3190 var nesting
= JSC
$cont_break
.count_with_nesting (this.label
);
3192 new JSC
$ASM_with_pop (this.linenum
, nesting
).link ();
3194 nesting
= JSC
$cont_break
.count_try_nesting (this.label
);
3196 new JSC
$ASM_try_pop (this.linenum
, nesting
).link ();
3198 nesting
= JSC
$cont_break
.count_switch_nesting (this.label
);
3201 /* Pop the value of the switch expression. */
3203 new JSC
$ASM_pop (this.linenum
).link ();
3205 new JSC
$ASM_pop_n (this.linenum
, nesting
).link ();
3208 new JSC
$ASM_jmp (this.linenum
, l_cont
).link ();
3214 function JSC
$stmt_break (ln
, label
)
3216 this.stype
= JSC
$STMT_BREAK
;
3219 this.asm
= JSC
$stmt_break_asm
;
3220 this.count_locals
= JSC
$zero_function
;
3223 function JSC
$stmt_break_asm ()
3225 var l_break
= JSC
$cont_break
.get_break (this.label
);
3227 if (l_break
== null)
3230 error (JSC
$filename
+ ":" + this.linenum
.toString ()
3231 + ": label `" + this.label
3232 + "' not found for break statement");
3234 error (JSC
$filename
+ ":" + this.linenum
.toString()
3235 + ": break statement not within a loop or switch");
3238 var nesting
= JSC
$cont_break
.count_with_nesting (this.label
);
3240 new JSC
$ASM_with_pop (this.linenum
, nesting
).link ();
3242 nesting
= JSC
$cont_break
.count_try_nesting (this.label
);
3244 new JSC
$ASM_try_pop (this.linenum
, nesting
).link ();
3247 * For non-labeled breaks, the switch nesting is handled in the
3248 * stmt_switch(). The code after the label, returned by the
3249 * get_break(), will handle the switch nesting in these cases.
3250 * For the labeled breaks, we must pop the switch nesting here.
3254 nesting
= JSC
$cont_break
.count_switch_nesting (this.label
);
3258 new JSC
$ASM_pop (this.linenum
).link ();
3260 new JSC
$ASM_pop_n (this.linenum
, nesting
).link ();
3264 new JSC
$ASM_jmp (this.linenum
, l_break
).link ();
3270 function JSC
$stmt_return (ln
, expr
)
3272 this.stype
= JSC
$STMT_RETURN
;
3275 this.asm
= JSC
$stmt_return_asm
;
3276 this.count_locals
= JSC
$zero_function
;
3279 function JSC
$stmt_return_asm ()
3281 var nesting
= JSC
$cont_break
.try_return_nesting ();
3283 new JSC
$ASM_try_pop (this.linenum
, nesting
).link ();
3285 if (this.expr
!= null)
3288 new JSC
$ASM_const_undefined (this.linenum
).link ();
3290 new JSC
$ASM_return (this.linenum
).link ();
3296 function JSC
$stmt_switch (ln
, last_ln
, expr
, clauses
)
3298 this.stype
= JSC
$STMT_SWITCH
;
3300 this.last_linenum
= last_ln
;
3302 this.clauses
= clauses
;
3303 this.asm
= JSC
$stmt_switch_asm
;
3304 this.count_locals
= JSC
$stmt_switch_count_locals
;
3307 function JSC
$stmt_switch_asm ()
3309 /* Evaluate the switch expression to the top of the stack. */
3312 /* The switch statement define a break label. */
3313 var l_break
= new JSC
$ASM_label ();
3314 JSC
$cont_break
.push (l_break
, null, true, null);
3316 /* For each clause (except the first), insert check and body labels. */
3318 for (i
= 1; i
< this.clauses
.length
; i
++)
3320 this.clauses
[i
].l_check
= new JSC
$ASM_label ();
3321 this.clauses
[i
].l_body
= new JSC
$ASM_label ();
3324 /* Generate code for each clause. */
3325 for (i
= 0; i
< this.clauses
.length
; i
++)
3327 /* Is this the last clause? */
3328 var last
= i
+ 1 >= this.clauses
.length
;
3329 var c
= this.clauses
[i
];
3331 var next_check
, next_body
;
3333 next_check
= next_body
= l_break
;
3336 next_check
= this.clauses
[i
+ 1].l_check
;
3337 next_body
= this.clauses
[i
+ 1].l_body
;
3343 * Must check if this clause matches the expression. If c.expr
3344 * is null, this is the default clause that matches always.
3350 new JSC
$ASM_dup (c
.linenum
).link ();
3352 new JSC
$ASM_cmp_eq (c
.linenum
).link ();
3353 new JSC
$ASM_iffalse_b (c
.linenum
, next_check
).link ();
3358 /* The check label for the default case. */
3362 /* Generate assembler for the body. */
3367 for (j
= 0; j
< c
.length
; j
++)
3370 /* And finally, jump to the next body. (this is the fallthrough case). */
3371 new JSC
$ASM_jmp (c
.last_linenum
, next_body
).link ();
3374 JSC
$cont_break
.pop ();
3376 /* The break label. */
3379 /* Pop the value of the switch expression. */
3380 new JSC
$ASM_pop (this.last_linenum
).link ();
3383 function JSC
$stmt_switch_count_locals (recursive
)
3390 /* For the recursive cases, we need the maximum of our clause stmts. */
3391 for (i
= 0; i
< this.clauses
.length
; i
++)
3393 var c
= this.clauses
[i
];
3394 for (j
= 0; j
< c
.length
; j
++)
3396 var l
= c
[j
].count_locals (true);
3405 * The case clauses are not blocks. Therefore, we need the amount,
3406 * needed by the clauses at the top-level.
3409 for (i
= 0; i
< this.clauses
.length
; i
++)
3411 var c
= this.clauses
[i
];
3412 for (j
= 0; j
< c
.length
; j
++)
3413 locals
+= c
[j
].count_locals (false);
3423 function JSC
$stmt_with (ln
, expr
, stmt
)
3425 this.stype
= JSC
$STMT_WITH
;
3429 this.asm
= JSC
$stmt_with_asm
;
3430 this.count_locals
= JSC
$stmt_with_count_locals
;
3433 function JSC
$stmt_with_asm ()
3437 new JSC
$ASM_with_push (this.linenum
).link ();
3438 JSC
$cont_break
.top
.with_nesting
++;
3442 JSC
$cont_break
.top
.with_nesting
--;
3443 new JSC
$ASM_with_pop (this.linenum
, 1).link ();
3446 function JSC
$stmt_with_count_locals (recursive
)
3450 if (this.stmt
.stype
== JSC
$STMT_VARIABLE
)
3451 return this.stmt
.list
.length
;
3456 return this.stmt
.count_locals (true);
3462 function JSC
$stmt_try (ln
, try_block_last_ln
, try_last_ln
, block
, catch_list
,
3465 this.stype
= JSC
$STMT_TRY
;
3467 this.try_block_last_linenum
= try_block_last_ln
;
3468 this.try_last_linenum
= try_last_ln
;
3470 this.catch_list
= catch_list
;
3472 this.asm
= JSC
$stmt_try_asm
;
3473 this.count_locals
= JSC
$stmt_try_count_locals
;
3476 function JSC
$stmt_try_asm ()
3478 var l_finally
= new JSC
$ASM_label ();
3480 /* Protect and execute the try-block. */
3482 var l_try_error
= new JSC
$ASM_label ();
3483 new JSC
$ASM_try_push (this.linenum
, l_try_error
).link ();
3484 JSC
$cont_break
.top
.try_nesting
++;
3488 JSC
$cont_break
.top
.try_nesting
--;
3489 new JSC
$ASM_try_pop (this.try_block_last_linenum
, 1).link ();
3492 * All ok so far. Push a `false' to indicate no error and jump to
3493 * the finally block (or out if we have no finally block).
3495 new JSC
$ASM_const_false (this.try_block_last_linenum
).link ();
3496 new JSC
$ASM_jmp (this.try_block_last_linenum
, l_finally
).link ();
3499 * Handle try block failures. The thrown value is on the top of the
3503 l_try_error
.link ();
3505 if (this.catch_list
)
3508 * We keep one boolean variable below the thrown value. Its default
3509 * value is false. When one of our catch blocks are entered, it is
3510 * set to true to indicate that we shouldn't throw the error
3513 new JSC
$ASM_const_false (this.catch_list
.linenum
).link ();
3514 new JSC
$ASM_swap (this.catch_list
.linenum
).link ();
3516 /* Protect and execute the catch list. */
3518 var l_catch_list_error
= new JSC
$ASM_label ();
3519 new JSC
$ASM_try_push (this.catch_list
.linenum
,
3520 l_catch_list_error
).link ();
3521 JSC
$cont_break
.top
.try_nesting
++;
3523 /* Insert start and body labels for each catch list item. */
3525 for (i
= 0; i
< this.catch_list
.length
; i
++)
3527 this.catch_list
[i
].l_start
= new JSC
$ASM_label ();
3528 this.catch_list
[i
].l_body
= new JSC
$ASM_label ();
3531 /* A label for the catch list end. */
3532 var l_catch_list_end
= new JSC
$ASM_label ();
3534 /* Process the individual catches. */
3535 for (i
= 0; i
< this.catch_list
.length
; i
++)
3537 var c
= this.catch_list
[i
];
3539 /* This is the starting point of this catch frame. */
3543 * Create a new namespace frame and bind the catch's
3544 * identifier to the thrown exception.
3547 JSC
$ns
.push_frame ();
3548 JSC
$ns
.define_symbol (c
.id
, JSC
$SCOPE_LOCAL
, JSC
$ns
.alloc_local (),
3551 new JSC
$ASM_dup (c
.linenum
).link ();
3552 new JSC
$ASM_store_local (c
.linenum
,
3553 JSC
$ns
.lookup_symbol (c
.id
).value
).link ();
3555 /* Check the possible guard. We must protect its calculation. */
3558 var l_guard_error
= new JSC
$ASM_label ();
3559 new JSC
$ASM_try_push (c
.linenum
, l_guard_error
).link ();
3560 JSC
$cont_break
.top
.try_nesting
++;
3562 /* Calculate the guard. */
3565 JSC
$cont_break
.top
.try_nesting
--;
3566 new JSC
$ASM_try_pop (c
.linenum
, 1).link ();
3569 * Wow! We managed to do it. Now, let's check if we
3570 * accept this catch case.
3574 if (i
+ 1 >= this.catch_list
.length
)
3575 next
= l_catch_list_end
;
3577 next
= this.catch_list
[i
+ 1].l_start
;
3579 if (c
.guard
.lang_type
== JSC
$JS_BOOLEAN
)
3580 new JSC
$ASM_iffalse_b (c
.linenum
, next
).link ();
3582 new JSC
$ASM_iffalse (c
.linenum
, next
).link ();
3584 /* Yes, we do accept it. Just jump to do the stuffs. */
3585 new JSC
$ASM_jmp (c
.linenum
, c
.l_body
).link ();
3588 * The evaluation of the guard failed. Do the cleanup
3589 * and jump to the next case.
3592 l_guard_error
.link ();
3594 /* Pop the exception. */
3595 new JSC
$ASM_pop (c
.linenum
).link ();
3597 /* Check the next case. */
3598 new JSC
$ASM_jmp (c
.linenum
, next
).link ();
3602 * We did enter the catch body. Let's update our boolean
3603 * status variable to reflect this fact.
3607 new JSC
$ASM_swap (c
.linenum
).link ();
3608 new JSC
$ASM_pop (c
.linenum
).link ();
3609 new JSC
$ASM_const_true (c
.linenum
).link ();
3610 new JSC
$ASM_swap (c
.linenum
).link ();
3612 /* Code for the catch body. */
3615 /* We'r done with the namespace frame. */
3616 JSC
$ns
.pop_frame ();
3619 * The next catch tag, or the l_catch_list_end follows us,
3620 * so we don't need a jumps here.
3625 * The catch list was evaluated without errors.
3628 l_catch_list_end
.link ();
3629 JSC
$cont_break
.top
.try_nesting
--;
3630 new JSC
$ASM_try_pop (this.catch_list
.last_linenum
, 1).link ();
3632 /* Did we enter any of our catch lists? */
3634 var l_we_did_enter
= new JSC
$ASM_label ();
3635 new JSC
$ASM_swap (this.catch_list
.last_linenum
).link ();
3636 new JSC
$ASM_iftrue_b (this.catch_list
.last_linenum
,
3637 l_we_did_enter
).link ();
3642 * Push `true' to indicate an exception and jump to the finally
3643 * block. The exception is now on the top of the stack.
3645 new JSC
$ASM_const_true (this.catch_list
.last_linenum
).link ();
3646 new JSC
$ASM_jmp (this.catch_list
.last_linenum
, l_finally
).link ();
3648 /* Yes, we did enter one (or many) of our catch lists. */
3650 l_we_did_enter
.link ();
3652 /* Pop the try-block's exception */
3653 new JSC
$ASM_pop (this.catch_list
.last_linenum
).link ();
3656 * Push a `false' to indicate "no errors" and jump to the
3659 new JSC
$ASM_const_false (this.catch_list
.last_linenum
).link ();
3660 new JSC
$ASM_jmp (this.catch_list
.last_linenum
, l_finally
).link ();
3664 * Handle catch list failures. The thrown value is on the top of the
3668 l_catch_list_error
.link ();
3671 * Pop the try-block's exception and our boolean `did we enter a
3672 * catch block' variable. They are below our new exception.
3674 new JSC
$ASM_apop (this.catch_list
.last_linenum
, 2).link ();
3677 * Push `true' to indicate an exception. We will fallthrough to
3678 * the finally part, so no jump is needed here.
3680 new JSC
$ASM_const_true (this.catch_list
.last_linenum
).link ();
3684 /* No catch list. */
3685 new JSC
$ASM_const_true (this.try_block_last_linenum
).link ();
3688 /* The possible finally block. */
3693 /* Execute it without protection. */
3696 /* We'r almost there. Let's see if we have to raise a new exception. */
3698 var l_out
= new JSC
$ASM_label ();
3699 new JSC
$ASM_iffalse_b (this.try_last_linenum
, l_out
).link ();
3702 new JSC
$ASM_throw (this.try_last_linenum
).link ();
3704 /* The possible exception is handled. Please, continue. */
3708 function JSC
$stmt_try_count_locals (recursive
)
3715 c
= this.block
.count_locals (true);
3719 if (this.catch_list
)
3722 for (i
= 0; i
< this.catch_list
.length
; i
++)
3724 c
= this.catch_list
[i
].stmt
.count_locals (true);
3731 c
= this.fin
.count_locals (true);
3738 if (this.block
.stype
== JSC
$STMT_VARIABLE
)
3739 count
+= this.block
.list
.length
;
3741 if (this.catch_list
)
3743 /* One for the call variable. */
3747 for (i
= 0; i
< this.catch_list
.length
; i
++)
3748 if (this.catch_list
[i
].stmt
.stype
== JSC
$STMT_VARIABLE
)
3749 count
+= this.catch_list
[i
].stmt
.list
.length
;
3753 if (this.fin
.stype
== JSC
$STMT_VARIABLE
)
3754 count
+= this.fin
.list
.length
;
3763 function JSC
$stmt_throw (ln
, expr
)
3765 this.stype
= JSC
$STMT_THROW
;
3768 this.asm
= JSC
$stmt_throw_asm
;
3769 this.count_locals
= JSC
$zero_function
;
3772 function JSC
$stmt_throw_asm ()
3775 new JSC
$ASM_throw (this.linenum
).link ();
3779 /* Labeled statement. */
3780 function JSC
$stmt_labeled_stmt (ln
, id
, stmt
)
3782 this.stype
= JSC
$STMT_LABELED_STMT
;
3786 this.asm
= JSC
$stmt_labeled_stmt_asm
;
3787 this.count_locals
= JSC
$stmt_labeled_stmt_count_locals
;
3790 function JSC
$stmt_labeled_stmt_asm ()
3792 var l_continue
= new JSC
$ASM_label ();
3793 var l_break
= new JSC
$ASM_label ();
3796 * It is an error if we already have a labeled statement with the
3799 if (!JSC
$cont_break
.is_unique_label (this.id
))
3800 error (JSC
$filename
+ ":" + this.linenum
.toString ()
3801 + ": labeled statement is enclosed by another labeled statement "
3802 + "with the same label");
3804 /* Push the break and continue labels. */
3805 JSC
$cont_break
.push (l_break
, l_continue
, false, this.id
);
3807 /* Dump the assembler. */
3812 /* And we'r done with out label scope. */
3813 JSC
$cont_break
.pop ();
3816 function JSC
$stmt_labeled_stmt_count_locals (recursive
)
3818 return this.stmt
.count_locals (recursive
);
3824 function JSC
$stmt_expr (expr
)
3826 this.stype
= JSC
$STMT_EXPR
;
3827 this.linenum
= expr
.linenum
;
3829 this.asm
= JSC
$stmt_expr_asm
;
3830 this.count_locals
= JSC
$zero_function
;
3833 function JSC
$stmt_expr_asm ()
3836 new JSC
$ASM_pop (this.linenum
).link ();
3842 function JSC
$stmt_if (ln
, expr
, stmt1
, stmt2
)
3844 this.stype
= JSC
$STMT_IF
;
3849 this.asm
= JSC
$stmt_if_asm
;
3850 this.count_locals
= JSC
$stmt_if_count_locals
;
3853 function JSC
$stmt_if_asm ()
3857 var l1
= new JSC
$ASM_label ();
3858 var l2
= new JSC
$ASM_label ();
3860 if (JSC
$optimize_type
&& this.expr
.lang_type
3861 && this.expr
.lang_type
== JSC
$JS_BOOLEAN
)
3862 new JSC
$ASM_iffalse_b (this.linenum
, l1
).link ();
3864 new JSC
$ASM_iffalse (this.linenum
, l1
).link ();
3866 /* Code for the then branch. */
3868 new JSC
$ASM_jmp (this.linenum
, l2
).link ();
3870 /* Code for the else branch. */
3872 if (this.stmt2
!= null)
3880 function JSC
$stmt_if_count_locals (recursive
)
3887 if (this.stmt1
.stype
== JSC
$STMT_VARIABLE
)
3888 lcount
+= this.stmt1
.list
.length
;
3890 if (this.stmt2
!= null && this.stmt2
.stype
== JSC
$STMT_VARIABLE
)
3891 lcount
+= this.stmt2
.list
.length
;
3895 lcount
= this.stmt1
.count_locals (true);
3899 var c
= this.stmt2
.count_locals (true);
3911 function JSC
$stmt_do_while (ln
, expr
, stmt
)
3913 this.stype
= JSC
$STMT_DO_WHILE
;
3917 this.asm
= JSC
$stmt_do_while_asm
;
3918 this.count_locals
= JSC
$stmt_do_while_count_locals
;
3921 function JSC
$stmt_do_while_asm ()
3923 var l1
= new JSC
$ASM_label ();
3924 var l2
= new JSC
$ASM_label ();
3925 var l3
= new JSC
$ASM_label ();
3931 JSC
$cont_break
.push (l3
, l2
, false, null);
3933 JSC
$cont_break
.pop ();
3935 /* Condition & continue. */
3938 if (JSC
$optimize_type
&& this.expr
.lang_type
3939 && this.expr
.lang_type
== JSC
$JS_BOOLEAN
)
3940 new JSC
$ASM_iftrue_b (this.linenum
, l1
).link ();
3942 new JSC
$ASM_iftrue (this.linenum
, l1
).link ();
3948 function JSC
$stmt_do_while_count_locals (recursive
)
3952 if (this.stmt
.stype
== JSC
$STMT_VARIABLE
)
3953 return this.stmt
.list
.length
;
3958 return this.stmt
.count_locals (true);
3963 function JSC
$stmt_while (ln
, expr
, stmt
)
3965 this.stype
= JSC
$STMT_WHILE
;
3969 this.asm
= JSC
$stmt_while_asm
;
3970 this.count_locals
= JSC
$stmt_while_count_locals
;
3973 function JSC
$stmt_while_asm ()
3975 var l1
= new JSC
$ASM_label ();
3976 var l2
= new JSC
$ASM_label ();
3983 if (JSC
$optimize_type
&& this.expr
.lang_type
3984 && this.expr
.lang_type
== JSC
$JS_BOOLEAN
)
3985 new JSC
$ASM_iffalse_b (this.linenum
, l2
).link ();
3987 new JSC
$ASM_iffalse (this.linenum
, l2
).link ();
3990 JSC
$cont_break
.push (l2
, l1
, false, null);
3992 JSC
$cont_break
.pop ();
3995 new JSC
$ASM_jmp (this.linenum
, l1
).link ();
4002 function JSC
$stmt_while_count_locals (recursive
)
4006 if (this.stmt
.stype
== JSC
$STMT_VARIABLE
)
4007 return this.stmt
.list
.length
;
4012 return this.stmt
.count_locals (true);
4018 function JSC
$stmt_for (ln
, vars
, e1
, e2
, e3
, stmt
)
4020 this.stype
= JSC
$STMT_FOR
;
4027 this.asm
= JSC
$stmt_for_asm
;
4028 this.count_locals
= JSC
$stmt_for_count_locals
;
4031 function JSC
$stmt_for_asm ()
4033 /* Code for the init. */
4036 /* We have our own variable scope. */
4037 JSC
$ns
.push_frame ();
4040 for (i
= 0; i
< this.vars
.length
; i
++)
4042 var decl
= this.vars
[i
];
4044 JSC
$ns
.define_symbol (decl
.id
, JSC
$SCOPE_LOCAL
,
4045 JSC
$ns
.alloc_local (), this.linenum
);
4047 /* Possible init. */
4052 var r
= JSC
$ns
.lookup_symbol (decl
.id
);
4053 if (r
== null || r
.scope
!= JSC
$SCOPE_LOCAL
)
4054 error (JSC
$filename
+ ":" + this.liennum
.toString ()
4055 + ": internal compiler error in local variable "
4056 + "declaration in for statement");
4058 new JSC
$ASM_store_local (this.linenum
, r
.value
).link ();
4062 else if (this.expr1
!= null)
4065 new JSC
$ASM_pop (this.linenum
).link ();
4068 var l1
= new JSC
$ASM_label ();
4069 var l2
= new JSC
$ASM_label ();
4070 var l3
= new JSC
$ASM_label ();
4076 var type_op
= false;
4077 if (this.expr2
!= null)
4080 if (JSC
$optimize_type
&& this.expr2
.lang_type
4081 && this.expr2
.lang_type
== JSC
$JS_BOOLEAN
)
4086 new JSC
$ASM_const_true (this.linenum
).link ();
4087 type_op
= JSC
$optimize_type
;
4090 new JSC
$ASM_iffalse_b (this.linenum
, l3
).link ();
4092 new JSC
$ASM_iffalse (this.linenum
, l3
).link ();
4094 JSC
$cont_break
.push (l3
, l2
, false, null);
4097 JSC
$cont_break
.pop ();
4099 /* Continue label. */
4103 if (this.expr3
!= null)
4106 new JSC
$ASM_pop (this.linenum
).link ();
4110 new JSC
$ASM_jmp (this.linenum
, l1
).link ();
4116 /* Pop the local variable scope. */
4117 JSC
$ns
.pop_frame ();
4121 function JSC
$stmt_for_count_locals (recursive
)
4128 count
+= this.vars
.length
;
4130 count
+= this.stmt
.count_locals (true);
4134 if (this.stmt
.stype
== JSC
$STMT_VARIABLE
)
4135 count
+= this.stmt
.list
.length
;
4144 function JSC
$stmt_for_in (ln
, vars
, e1
, e2
, stmt
)
4146 this.stype
= JSC
$STMT_FOR_IN
;
4152 this.asm
= JSC
$stmt_for_in_asm
;
4153 this.count_locals
= JSC
$stmt_for_in_count_locals
;
4156 function JSC
$stmt_for_in_asm ()
4162 /* We need our own variable scope here. */
4163 JSC
$ns
.push_frame ();
4165 var decl
= this.vars
[0];
4166 local_id
= JSC
$ns
.alloc_local ();
4167 JSC
$ns
.define_symbol (decl
.id
, JSC
$SCOPE_LOCAL
, local_id
, this.linenum
);
4169 /* Possible init. */
4173 new JSC
$ASM_store_local (this.linenum
, local_id
).link ();
4177 /* Init the world. */
4179 new JSC
$ASM_dup (this.linenum
).link ();
4180 new JSC
$ASM_const_i0 (this.linenum
).link ();
4181 new JSC
$ASM_swap (this.linenum
).link ();
4182 new JSC
$ASM_const_i0 (this.linenum
).link ();
4184 var l_loop
= new JSC
$ASM_label ();
4185 var l_cont
= new JSC
$ASM_label ();
4186 var l_iffalse_b
= new JSC
$ASM_label ();
4187 var l_break
= new JSC
$ASM_label ();
4193 new JSC
$ASM_nth (this.linenum
).link ();
4194 new JSC
$ASM_iffalse_b (this.linenum
, l_iffalse_b
).link ();
4196 /* Store value to variable. */
4198 new JSC
$ASM_store_local (this.linenum
, local_id
).link ();
4200 JSC
$asm_expr_lvalue_store_asm (this.expr1
);
4203 JSC
$cont_break
.push (l_break
, l_cont
, false, null);
4205 JSC
$cont_break
.pop ();
4207 /* Continue label. */
4211 new JSC
$ASM_const_i1 (this.linenum
).link ();
4212 new JSC
$ASM_add (this.linenum
).link ();
4213 new JSC
$ASM_dup (this.linenum
).link ();
4214 new JSC
$ASM_roll (this.linenum
, -3).link ();
4215 new JSC
$ASM_dup (this.linenum
).link ();
4216 new JSC
$ASM_roll (this.linenum
, 4).link ();
4217 new JSC
$ASM_swap (this.linenum
).link ();
4220 new JSC
$ASM_jmp (this.linenum
, l_loop
).link ();
4223 l_iffalse_b
.link ();
4225 new JSC
$ASM_pop (this.linenum
).link ();
4229 new JSC
$ASM_pop_n (this.linenum
, 2).link ();
4232 /* Pop the variable scope. */
4233 JSC
$ns
.pop_frame ();
4236 function JSC
$stmt_for_in_count_locals (recursive
)
4245 count
+= this.stmt
.count_locals (true);
4249 if (this.stmt
.stype
== JSC
$STMT_VARIABLE
)
4250 count
+= this.stmt
.list
.length
;
4260 function JSC
$stmt_variable (ln
, list
)
4262 this.stype
= JSC
$STMT_VARIABLE
;
4264 this.global_level
= false;
4266 this.asm
= JSC
$stmt_variable_asm
;
4267 this.count_locals
= JSC
$stmt_variable_count_locals
;
4270 function JSC
$stmt_variable_asm ()
4274 /* Define all local variables to our namespace. */
4275 for (j
= 0; j
< this.list
.length
; j
++)
4277 var i
= this.list
[j
];
4279 if (!this.global_level
)
4280 JSC
$ns
.define_symbol (i
.id
, JSC
$SCOPE_LOCAL
,
4281 JSC
$ns
.alloc_local (), this.linenum
);
4286 if (this.global_level
)
4287 new JSC
$ASM_store_global (this.linenum
, i
.id
).link ();
4290 r
= JSC
$ns
.lookup_symbol (i
.id
);
4291 if (r
== null || r
.scope
!= JSC
$SCOPE_LOCAL
)
4292 error (JSC
$filename
+ ":" + this.linenum
.toString()
4293 + ": internal compiler error in local variable declaration");
4295 new JSC
$ASM_store_local (this.linenum
, r
.value
).link ();
4301 function JSC
$stmt_variable_count_locals (recursive
)
4305 if (this.global_level
)
4306 /* We define these as global variables. */
4309 return this.list
.length
;
4315 function JSC
$var_declaration (id
, expr
)
4328 function JSC
$expr_this (ln
)
4330 this.etype
= JSC
$EXPR_THIS
;
4332 this.asm
= JSC
$expr_this_asm
;
4335 function JSC
$expr_this_asm ()
4337 new JSC
$ASM_load_arg (this.linenum
, 0).link ();
4342 function JSC
$expr_identifier (ln
, value
)
4344 this.etype
= JSC
$EXPR_IDENTIFIER
;
4347 this.asm
= JSC
$expr_identifier_asm
;
4350 function JSC
$expr_identifier_asm ()
4352 JSC
$asm_expr_lvalue_load_asm (this);
4357 function JSC
$expr_float (ln
, value
)
4359 this.etype
= JSC
$EXPR_FLOAT
;
4360 this.lang_type
= JSC
$JS_FLOAT
;
4363 this.asm
= JSC
$expr_float_asm
;
4366 function JSC
$expr_float_asm ()
4368 new JSC
$ASM_const (this.linenum
, this.value
).link ();
4373 function JSC
$expr_integer (ln
, value
)
4375 this.etype
= JSC
$EXPR_INTEGER
;
4376 this.lang_type
= JSC
$JS_INTEGER
;
4379 this.asm
= JSC
$expr_integer_asm
;
4382 function JSC
$expr_integer_asm ()
4384 if (this.value
== 0)
4385 new JSC
$ASM_const_i0 (this.linenum
).link ();
4386 else if (this.value
== 1)
4387 new JSC
$ASM_const_i1 (this.linenum
).link ();
4388 else if (this.value
== 2)
4389 new JSC
$ASM_const_i2 (this.linenum
).link ();
4390 else if (this.value
== 3)
4391 new JSC
$ASM_const_i3 (this.linenum
).link ();
4393 new JSC
$ASM_const_i (this.linenum
, this.value
).link ();
4398 function JSC
$expr_string (ln
, value
)
4400 this.etype
= JSC
$EXPR_STRING
;
4401 this.lang_type
= JSC
$JS_STRING
;
4404 this.asm
= JSC
$expr_string_asm
;
4407 function JSC
$expr_string_asm ()
4409 new JSC
$ASM_const (this.linenum
, this.value
).link ();
4414 function JSC
$expr_regexp (ln
, value
)
4416 this.etype
= JSC
$EXPR_REGEXP
;
4417 this.lang_type
= JSC
$JS_BUILTIN
;
4420 this.asm
= JSC
$expr_regexp_asm
;
4423 function JSC
$expr_regexp_asm ()
4425 new JSC
$ASM_const (this.linenum
, this.value
).link ();
4428 /* Array initializer. */
4430 function JSC
$expr_array_initializer (ln
, items
)
4432 this.etype
= JSC
$EXPR_ARRAY_INITIALIZER
;
4433 this.lang_type
= JSC
$JS_ARRAY
;
4436 this.asm
= JSC
$expr_array_initializer_asm
;
4439 function JSC
$expr_array_initializer_asm ()
4441 /* Generate assembler for the individual items. */
4444 for (i
= this.items
.length
- 1; i
>= 0; i
--)
4447 this.items
[i
].asm ();
4449 new JSC
$ASM_const_undefined (this.linenum
).link ();
4453 * The number of items as a negative integer. The Array object's
4454 * constructor knows that if the number of arguments is negative, it
4455 * is called from the array initializer. Why? Because the code:
4459 * creates an array of length of 5, but code:
4463 * creates an array with one item: integer number five. These cases
4464 * must be separatable from the code and that's why the argument
4465 * counts for the array initializers are negative.
4467 new JSC
$ASM_const (this.linenum
, -this.items
.length
).link ();
4469 /* Call the constructor. */
4470 new JSC
$ASM_load_global (this.linenum
, "Array").link ();
4471 new JSC
$ASM_new (this.linenum
).link ();
4472 new JSC
$ASM_swap (this.linenum
).link ();
4473 new JSC
$ASM_apop (this.linenum
, this.items
.length
+ 2).link ();
4476 /* Object initializer. */
4478 function JSC
$expr_object_initializer (ln
, items
)
4480 this.etype
= JSC
$EXPR_OBJECT_INITIALIZER
;
4481 this.lang_type
= JSC
$JS_OBJECT
;
4484 this.asm
= JSC
$expr_object_initializer_asm
;
4487 function JSC
$expr_object_initializer_asm ()
4489 /* Create a new object. */
4490 new JSC
$ASM_const_i0 (this.linenum
).link ();
4491 new JSC
$ASM_load_global (this.linenum
, "Object").link ();
4492 new JSC
$ASM_new (this.linenum
).link ();
4493 new JSC
$ASM_swap (this.linenum
).link ();
4494 new JSC
$ASM_apop (this.linenum
, 2).link ();
4496 /* Insert the items. */
4497 for (var i
= 0; i
< this.items
.length
; i
++)
4499 var item
= this.items
[i
];
4501 new JSC
$ASM_dup (item
.linenum
).link ();
4503 new JSC
$ASM_swap (item
.linenum
).link ();
4505 switch (item
.id_type
)
4507 case JSC
$tIDENTIFIER
:
4508 new JSC
$ASM_store_property (item
.linenum
, item
.id
).link ();
4512 new JSC
$ASM_const (item
.linenum
, item
.id
).link ();
4513 new JSC
$ASM_store_array (item
.linenum
).link ();
4520 new JSC
$ASM_const_i0 (item
.linenum
).link ();
4524 new JSC
$ASM_const_i1 (item
.linenum
).link ();
4528 new JSC
$ASM_const_i2 (item
.linenum
).link ();
4532 new JSC
$ASM_const_i3 (item
.linenum
).link ();
4536 new JSC
$ASM_const_i (item
.linenum
, item
.id
).link ();
4539 new JSC
$ASM_store_array (item
.linenum
).link ();
4548 function JSC
$expr_null (ln
)
4550 this.etype
= JSC
$EXPR_NULL
;
4551 this.lang_type
= JSC
$JS_NULL
;
4553 this.asm
= JSC
$expr_null_asm
;
4556 function JSC
$expr_null_asm ()
4558 new JSC
$ASM_const_null (this.linenum
).link ();
4563 function JSC
$expr_true (ln
)
4565 this.etype
= JSC
$EXPR_TRUE
;
4566 this.lang_type
= JSC
$JS_BOOLEAN
;
4568 this.asm
= JSC
$expr_true_asm
;
4571 function JSC
$expr_true_asm ()
4573 new JSC
$ASM_const_true (this.linenum
).link ();
4578 function JSC
$expr_false (ln
)
4580 this.etype
= JSC
$EXPR_FALSE
;
4581 this.lang_type
= JSC
$JS_BOOLEAN
;
4583 this.asm
= JSC
$expr_false_asm
;
4586 function JSC
$expr_false_asm ()
4588 new JSC
$ASM_const_false (this.linenum
).link ();
4592 /* Multiplicative expr. */
4594 function JSC
$expr_multiplicative (ln
, type
, e1
, e2
)
4596 this.etype
= JSC
$EXPR_MULTIPLICATIVE
;
4601 this.asm
= JSC
$expr_multiplicative_asm
;
4604 function JSC
$expr_multiplicative_asm ()
4608 if (this.type
== #'*')
4609 new JSC
$ASM_mul (this.linenum
).link ();
4610 else if (this.type
== #'/')
4611 new JSC
$ASM_div (this.linenum
).link ();
4613 new JSC
$ASM_mod (this.linenum
).link ();
4617 /* Additive expr. */
4619 function JSC
$expr_additive (ln
, type
, e1
, e2
)
4621 this.etype
= JSC
$EXPR_ADDITIVE
;
4626 this.asm
= JSC
$expr_additive_asm
;
4627 this.constant_folding
= JSC
$expr_additive_constant_folding
;
4630 function JSC
$expr_additive_asm ()
4634 if (this.type
== #'+')
4635 new JSC
$ASM_add (this.linenum
).link ();
4637 new JSC
$ASM_sub (this.linenum
).link ();
4640 function JSC
$expr_additive_constant_folding ()
4642 if (this.e1
.constant_folding
)
4643 this.e1
= this.e1
.constant_folding ();
4644 if (this.e2
.constant_folding
)
4645 this.e2
= this.e2
.constant_folding ();
4647 /* This could be smarter. */
4648 if (this.e1
.lang_type
&& this.e2
.lang_type
4649 && this.e1
.lang_type
== this.e2
.lang_type
)
4651 switch (this.e1
.lang_type
)
4653 case JSC
$JS_INTEGER
:
4654 return new JSC
$expr_integer (this.linenum
,
4656 ? this.e1
.value
+ this.e2
.value
4657 : this.e1
.value
- this.e2
.value
);
4661 return new JSC
$expr_float (this.linenum
,
4663 ? this.e1
.value
+ this.e2
.value
4664 : this.e1
.value
- this.e2
.value
);
4668 if (this.type
== #'+')
4669 /* Only the addition is available for the strings. */
4670 return new JSC
$expr_string (this.linenum
,
4671 this.e1
.value
+ this.e2
.value
);
4685 function JSC
$expr_shift (ln
, type
, e1
, e2
)
4687 this.etype
= JSC
$EXPR_SHIFT
;
4692 this.asm
= JSC
$expr_shift_asm
;
4695 function JSC
$expr_shift_asm ()
4700 if (this.type
== JSC
$tLSHIFT
)
4701 new JSC
$ASM_shift_left (this.linenum
).link ();
4702 else if (this.type
== JSC
$tRSHIFT
)
4703 new JSC
$ASM_shift_right (this.linenum
).link ();
4705 new JSC
$ASM_shift_rright (this.linenum
).link ();
4709 /* Relational expr. */
4711 function JSC
$expr_relational (ln
, type
, e1
, e2
)
4713 this.etype
= JSC
$EXPR_RELATIONAL
;
4714 this.lang_type
= JSC
$JS_BOOLEAN
;
4719 this.asm
= JSC
$expr_relational_asm
;
4722 function JSC
$expr_relational_asm ()
4727 if (this.type
== #'<')
4728 new JSC
$ASM_cmp_lt (this.linenum
).link ();
4729 else if (this.type
== #'>')
4730 new JSC
$ASM_cmp_gt (this.linenum
).link ();
4731 else if (this.type
== JSC
$tLE
)
4732 new JSC
$ASM_cmp_le (this.linenum
).link ();
4734 new JSC
$ASM_cmp_ge (this.linenum
).link ();
4738 /* Equality expr. */
4740 function JSC
$expr_equality (ln
, type
, e1
, e2
)
4742 this.etype
= JSC
$EXPR_EQUALITY
;
4743 this.lang_type
= JSC
$JS_BOOLEAN
;
4748 this.asm
= JSC
$expr_equality_asm
;
4751 function JSC
$expr_equality_asm ()
4759 new JSC
$ASM_cmp_eq (this.linenum
).link ();
4763 new JSC
$ASM_cmp_ne (this.linenum
).link ();
4767 new JSC
$ASM_cmp_seq (this.linenum
).link ();
4771 new JSC
$ASM_cmp_sne (this.linenum
).link ();
4775 error ("jsc: expr_equality: internal compiler error");
4781 /* Bitwise and expr. */
4783 function JSC
$expr_bitwise_and (ln
, e1
, e2
)
4785 this.etype
= JSC
$EXPR_BITWISE
;
4789 this.asm
= JSC
$expr_bitwise_and_asm
;
4792 function JSC
$expr_bitwise_and_asm ()
4797 new JSC
$ASM_and (this.linenum
).link ();
4801 /* Bitwise or expr. */
4803 function JSC
$expr_bitwise_or (ln
, e1
, e2
)
4805 this.etype
= JSC
$EXPR_BITWISE
;
4809 this.asm
= JSC
$expr_bitwise_or_asm
;
4812 function JSC
$expr_bitwise_or_asm ()
4817 new JSC
$ASM_or (this.linenum
).link ();
4821 /* Bitwise xor expr. */
4823 function JSC
$expr_bitwise_xor (ln
, e1
, e2
)
4825 this.etype
= JSC
$EXPR_BITWISE
;
4829 this.asm
= JSC
$expr_bitwise_xor_asm
;
4832 function JSC
$expr_bitwise_xor_asm ()
4837 new JSC
$ASM_xor (this.linenum
).link ();
4841 /* Logical and expr. */
4843 function JSC
$expr_logical_and (ln
, e1
, e2
)
4845 this.etype
= JSC
$EXPR_LOGICAL
;
4847 if (e1
.lang_type
&& e2
.lang_type
4848 && e1
.lang_type
== JSC
$JS_BOOLEAN
&& e2
.lang_type
== JSC
$JS_BOOLEAN
)
4849 this.lang_type
= JSC
$JS_BOOLEAN
;
4854 this.asm
= JSC
$expr_logical_and_asm
;
4857 function JSC
$expr_logical_and_asm ()
4861 var l
= new JSC
$ASM_label ();
4862 new JSC
$ASM_dup (this.linenum
).link ();
4864 if (JSC
$optimize_type
&& this.e1
.lang_type
4865 && this.e1
.lang_type
== JSC
$JS_BOOLEAN
)
4866 new JSC
$ASM_iffalse_b (this.linenum
, l
).link ();
4868 new JSC
$ASM_iffalse (this.linenum
, l
).link ();
4870 new JSC
$ASM_pop (this.linenum
).link ();
4879 /* Logical or expr. */
4881 function JSC
$expr_logical_or (ln
, e1
, e2
)
4883 this.etype
= JSC
$EXPR_LOGICAL
;
4885 if (e1
.lang_type
&& e2
.lang_type
4886 && e1
.lang_type
== JSC
$JS_BOOLEAN
&& e2
.lang_type
== JSC
$JS_BOOLEAN
)
4887 this.lang_type
= JSC
$JS_BOOLEAN
;
4892 this.asm
= JSC
$expr_logical_or_asm
;
4895 function JSC
$expr_logical_or_asm ()
4899 var l
= new JSC
$ASM_label ();
4900 new JSC
$ASM_dup (this.linenum
).link ();
4902 if (JSC
$optimize_type
&& this.e1
.lang_type
4903 && this.e1
.lang_type
== JSC
$JS_BOOLEAN
)
4904 new JSC
$ASM_iftrue_b (this.linenum
, l
).link ();
4906 new JSC
$ASM_iftrue (this.linenum
, l
).link ();
4908 new JSC
$ASM_pop (this.linenum
).link ();
4919 function JSC
$expr_new (ln
, expr
, args
)
4921 this.etype
= JSC
$EXPR_NEW
;
4925 this.asm
= JSC
$expr_new_asm
;
4928 function JSC
$expr_new_asm ()
4934 /* Code for the arguments. */
4935 for (i
= this.args
.length
- 1; i
>= 0; i
--)
4936 this.args
[i
].asm ();
4938 if (this.args
.length
== 0)
4939 new JSC
$ASM_const_i0 (this.linenum
).link ();
4940 else if (this.args
.length
== 1)
4941 new JSC
$ASM_const_i1 (this.linenum
).link ();
4942 else if (this.args
.length
== 2)
4943 new JSC
$ASM_const_i2 (this.linenum
).link ();
4944 else if (this.args
.length
== 3)
4945 new JSC
$ASM_const_i3 (this.linenum
).link ();
4947 new JSC
$ASM_const (this.linenum
, this.args
.length
).link ();
4951 /* A `new Foo' call. This is identical to `new Foo ()'. */
4952 new JSC
$ASM_const_i0 (this.linenum
).link ();
4959 new JSC
$ASM_new (this.linenum
).link ();
4961 /* Replace the constructor's return value with the object. */
4962 new JSC
$ASM_swap (this.linenum
).link ();
4964 /* Remove the arguments and return the new object. */
4965 new JSC
$ASM_apop (this.linenum
,
4966 (this.args
? this.args
.length
: 0) + 2).link ();
4970 /* Object property expr. */
4972 function JSC
$expr_object_property (ln
, expr
, id
)
4974 this.etype
= JSC
$EXPR_OBJECT_PROPERTY
;
4978 this.asm
= JSC
$expr_object_property_asm
;
4981 function JSC
$expr_object_property_asm ()
4983 JSC
$asm_expr_lvalue_load_asm (this);
4987 /* Object array expr. */
4989 function JSC
$expr_object_array (ln
, expr1
, expr2
)
4991 this.etype
= JSC
$EXPR_OBJECT_ARRAY
;
4995 this.asm
= JSC
$expr_object_array_asm
;
4998 function JSC
$expr_object_array_asm ()
5000 JSC
$asm_expr_lvalue_load_asm (this);
5006 function JSC
$expr_call (ln
, expr
, args
)
5008 this.etype
= JSC
$EXPR_CALL
;
5012 this.asm
= JSC
$expr_call_asm
;
5015 function JSC
$expr_call_asm ()
5019 /* Code for the arguments. */
5020 for (i
= this.args
.length
- 1; i
>= 0; i
--)
5021 this.args
[i
].asm ();
5023 if (this.args
.length
== 0)
5024 new JSC
$ASM_const_i0 (this.linenum
).link ();
5025 else if (this.args
.length
== 1)
5026 new JSC
$ASM_const_i1 (this.linenum
).link ();
5027 else if (this.args
.length
== 2)
5028 new JSC
$ASM_const_i2 (this.linenum
).link ();
5029 else if (this.args
.length
== 3)
5030 new JSC
$ASM_const_i3 (this.linenum
).link ();
5032 new JSC
$ASM_const (this.linenum
, this.args
.length
).link ();
5034 /* Check the function type. */
5035 if (this.expr
.etype
== JSC
$EXPR_IDENTIFIER
)
5037 /* The simple subroutine or global object method invocation. */
5039 var saved_with_nesting
= JSC
$cont_break
.top
.with_nesting
;
5040 JSC
$cont_break
.top
.with_nesting
= 0;
5042 JSC
$asm_expr_lvalue_load_asm (this.expr
);
5044 JSC
$cont_break
.top
.with_nesting
= saved_with_nesting
;
5046 if (JSC
$cont_break
.top
.with_nesting
> 0)
5047 new JSC
$ASM_jsr_w (this.linenum
, this.expr
.value
).link ();
5049 new JSC
$ASM_jsr (this.linenum
).link ();
5051 new JSC
$ASM_apop (this.linenum
, this.args
.length
+ 2).link ();
5053 else if (this.expr
.etype
== JSC
$EXPR_OBJECT_PROPERTY
)
5055 /* Method invocation. */
5056 this.expr
.expr
.asm ();
5057 new JSC
$ASM_call_method (this.linenum
, this.expr
.id
).link ();
5058 new JSC
$ASM_apop (this.linenum
, this.args
.length
+ 2).link ();
5062 /* Something like a function pointer invocation. */
5063 JSC
$asm_expr_lvalue_load_asm (this.expr
);
5064 new JSC
$ASM_jsr (this.linenum
).link ();
5065 new JSC
$ASM_apop (this.linenum
, this.args
.length
+ 2).link ();
5072 function JSC
$expr_assignment (ln
, type
, expr1
, expr2
)
5074 this.etype
= JSC
$EXPR_ASSIGNMENT
;
5079 this.asm
= JSC
$expr_assignment_asm
;
5082 function JSC
$expr_assignment_asm ()
5084 if (this.type
!= #'=')
5085 JSC
$asm_expr_lvalue_load_asm (this.expr1
);
5087 /* Count the rvalue. */
5090 if (this.type
== #'=')
5093 else if (this.type
== JSC
$tMULA
)
5094 new JSC
$ASM_mul (this.linenum
).link ();
5095 else if (this.type
== JSC
$tDIVA
)
5096 new JSC
$ASM_div (this.linenum
).link ();
5097 else if (this.type
== JSC
$tMODA
)
5098 new JSC
$ASM_mod (this.linenum
).link ();
5099 else if (this.type
== JSC
$tADDA
)
5100 new JSC
$ASM_add (this.linenum
).link ();
5101 else if (this.type
== JSC
$tSUBA
)
5102 new JSC
$ASM_sub (this.linenum
).link ();
5103 else if (this.type
== JSC
$tLSIA
)
5104 new JSC
$ASM_shift_left (this.linenum
).link ();
5105 else if (this.type
== JSC
$tRSIA
)
5106 new JSC
$ASM_shift_right (this.linenum
).link ();
5107 else if (this.type
== JSC
$tRRSA
)
5108 new JSC
$ASM_shift_rright (this.linenum
).link ();
5109 else if (this.type
== JSC
$tANDA
)
5110 new JSC
$ASM_and (this.linenum
).link ();
5111 else if (this.type
== JSC
$tXORA
)
5112 new JSC
$ASM_xor (this.linenum
).link ();
5113 else if (this.type
== JSC
$tORA
)
5114 new JSC
$ASM_or (this.linenum
).link ();
5116 error (JSC
$filename
+ ":" + this.linenum
.toString ()
5117 + ": internal compiler error in assignment expression");
5119 /* Duplicate the value. */
5120 new JSC
$ASM_dup (this.linenum
).link ();
5122 /* Store it to the lvalue. */
5123 JSC
$asm_expr_lvalue_store_asm (this.expr1
);
5126 function JSC
$asm_expr_lvalue_load_asm (expr
)
5130 if (expr
.etype
== JSC
$EXPR_IDENTIFIER
)
5132 /* Must check global / local / argument. */
5133 i
= JSC
$ns
.lookup_symbol (expr
.value
);
5136 if (JSC
$cont_break
.top
.with_nesting
> 0)
5137 new JSC
$ASM_load_global_w (expr
.linenum
, expr
.value
).link ();
5139 new JSC
$ASM_load_global (expr
.linenum
, expr
.value
).link ();
5141 else if (i
.scope
== JSC
$SCOPE_ARG
)
5143 if (JSC
$cont_break
.top
.with_nesting
> 0 && JSC
$warn_with_clobber
)
5144 JSC
$warning (JSC
$filename
+ ":" + expr
.linenum
.toString ()
5145 + ": warning: the with-lookup of symbol `" + i
.symbol
5146 + "' is clobbered by the argument definition");
5148 new JSC
$ASM_load_arg (expr
.linenum
, i
.value
).link ();
5152 if (JSC
$cont_break
.top
.with_nesting
> 0 && JSC
$warn_with_clobber
)
5153 JSC
$warning (JSC
$filename
+ ":" + expr
.linenum
.toString ()
5154 + ": warning: the with-lookup of symbol `" + i
.symbol
5155 + "' is clobbered by the local variable definition");
5157 new JSC
$ASM_load_local (expr
.linenum
, i
.value
).link ();
5160 else if (expr
.etype
== JSC
$EXPR_OBJECT_PROPERTY
)
5163 new JSC
$ASM_load_property (expr
.linenum
, expr
.id
).link ();
5165 else if (expr
.etype
== JSC
$EXPR_OBJECT_ARRAY
)
5169 new JSC
$ASM_load_array (expr
.linenum
).link ();
5172 error (JSC
$filename
+ ":" + expr
.linenum
.toString () + ": syntax error");
5175 function JSC
$asm_expr_lvalue_store_asm (expr
)
5179 if (expr
.etype
== JSC
$EXPR_IDENTIFIER
)
5181 i
= JSC
$ns
.lookup_symbol (expr
.value
);
5183 new JSC
$ASM_store_global (expr
.linenum
, expr
.value
).link ();
5184 else if (i
.scope
== JSC
$SCOPE_ARG
)
5185 new JSC
$ASM_store_arg (expr
.linenum
, i
.value
).link ();
5187 new JSC
$ASM_store_local (expr
.linenum
, i
.value
).link ();
5189 else if (expr
.etype
== JSC
$EXPR_OBJECT_PROPERTY
)
5192 new JSC
$ASM_store_property (expr
.linenum
, expr
.id
).link ();
5194 else if (expr
.etype
== JSC
$EXPR_OBJECT_ARRAY
)
5198 new JSC
$ASM_store_array (expr
.linenum
).link ();
5201 error (JSC
$filename
+ ":" + expr
.linenum
.toString () + ": syntax error");
5207 function JSC
$expr_quest_colon (ln
, e1
, e2
, e3
)
5209 this.etype
= JSC
$EXPR_QUEST_COLON
;
5214 this.asm
= JSC
$expr_quest_colon_asm
;
5217 function JSC
$expr_quest_colon_asm()
5219 /* Code for the condition. */
5222 var l1
= new JSC
$ASM_label ();
5223 var l2
= new JSC
$ASM_label ();
5225 if (JSC
$optimize_type
&& this.e1
.lang_type
5226 && this.e1
.lang_type
== JSC
$JS_BOOLEAN
)
5227 new JSC
$ASM_iffalse_b (this.linenum
, l1
).link ();
5229 new JSC
$ASM_iffalse (this.linenum
, l1
).link ();
5231 /* Code for the true branch. */
5233 new JSC
$ASM_jmp (this.linenum
, l2
).link ();
5235 /* Code for the false branch. */
5246 function JSC
$expr_unary (ln
, type
, expr
)
5248 this.etype
= JSC
$EXPR_UNARY
;
5252 this.asm
= JSC
$expr_unary_asm
;
5255 function JSC
$expr_unary_asm ()
5257 if (this.type
== #'!')
5260 new JSC
$ASM_not (this.linenum
).link ();
5262 else if (this.type
== #'+')
5267 else if (this.type
== #'~')
5270 new JSC
$ASM_const (this.linenum
, -1).link ();
5271 new JSC
$ASM_xor (this.linenum
).link ();
5273 else if (this.type
== #'-')
5276 new JSC
$ASM_neg (this.linenum
).link ();
5278 else if (this.type
== JSC
$tDELETE
)
5280 if (this.expr
.etype
== JSC
$EXPR_OBJECT_PROPERTY
)
5282 this.expr
.expr
.asm ();
5283 new JSC
$ASM_delete_property (this.linenum
, this.expr
.id
).link ();
5285 else if (this.expr
.etype
== JSC
$EXPR_OBJECT_ARRAY
)
5287 this.expr
.expr1
.asm ();
5288 this.expr
.expr2
.asm ();
5289 new JSC
$ASM_delete_array (this.linenum
).link ();
5291 else if (this.expr
.etype
== JSC
$EXPR_IDENTIFIER
)
5293 if (JSC
$cont_break
.top
.with_nesting
== 0)
5294 error (JSC
$filename
+ ":" + this.linenum
.toString ()
5295 + ": `delete property' called outside of a with-block");
5297 new JSC
$ASM_const_null (this.linenum
).link ();
5298 new JSC
$ASM_delete_property (this.linenum
, this.expr
.value
).link ();
5301 error (JSC
$filename
+ ":" + this.linenum
.toString ()
5302 + ": illegal target for the delete operand");
5304 else if (this.type
== JSC
$tVOID
)
5307 new JSC
$ASM_pop (this.linenum
).link ();
5308 new JSC
$ASM_const_undefined (this.linenum
).link ();
5310 else if (this.type
== JSC
$tTYPEOF
)
5313 new JSC
$ASM_typeof (this.linenum
).link ();
5315 else if (this.type
== JSC
$tPLUSPLUS
5316 || this.type
== JSC
$tMINUSMINUS
)
5318 /* Fetch the old value. */
5319 JSC
$asm_expr_lvalue_load_asm (this.expr
);
5321 /* Do the operation. */
5322 new JSC
$ASM_const_i1 (this.linenum
).link ();
5323 if (this.type
== JSC
$tPLUSPLUS
)
5324 new JSC
$ASM_add (this.linenum
).link ();
5326 new JSC
$ASM_sub (this.linenum
).link ();
5328 /* Duplicate the value and store one copy pack to lvalue. */
5329 new JSC
$ASM_dup (this.linenum
).link ();
5330 JSC
$asm_expr_lvalue_store_asm (this.expr
);
5334 error ("jsc: internal error: unary expr's type is "
5335 + this.type
.toString ());
5342 function JSC
$expr_postfix (ln
, type
, expr
)
5344 this.etype
= JSC
$EXPR_POSTFIX
;
5348 this.asm
= JSC
$expr_postfix_asm
;
5351 function JSC
$expr_postfix_asm ()
5353 /* Fetch the old value. */
5354 JSC
$asm_expr_lvalue_load_asm (this.expr
);
5356 /* Duplicate the value since it is the expression's value. */
5357 new JSC
$ASM_dup (this.linenum
).link ();
5359 /* Do the operation. */
5360 new JSC
$ASM_const_i1 (this.linenum
).link ();
5361 if (this.type
== JSC
$tPLUSPLUS
)
5362 new JSC
$ASM_add (this.linenum
).link ();
5364 new JSC
$ASM_sub (this.linenum
).link ();
5366 /* And finally, store it back. */
5367 JSC
$asm_expr_lvalue_store_asm (this.expr
);
5373 function JSC
$expr_comma (ln
, expr1
, expr2
)
5375 this.etype
= JSC
$EXPR_COMMA
;
5379 this.asm
= JSC
$expr_comma_asm
;
5382 function JSC
$expr_comma_asm ()
5385 new JSC
$ASM_pop (this.linenum
).link ();
5396 * Namespace handling.
5397 * Copyright (c) 1998 New Generation Software (NGS) Oy
5399 * Author: Markku Rossi <mtr@ngs.fi>
5403 * This library is free software; you can redistribute it and/or
5404 * modify it under the terms of the GNU Library General Public
5405 * License as published by the Free Software Foundation; either
5406 * version 2 of the License, or (at your option) any later version.
5408 * This library is distributed in the hope that it will be useful,
5409 * but WITHOUT ANY WARRANTY; without even the implied warranty of
5410 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5411 * Library General Public License for more details.
5413 * You should have received a copy of the GNU Library General Public
5414 * License along with this library; if not, write to the Free
5415 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
5416 * MA 02111-1307, USA
5420 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/jsc/compiler.js,v $
5429 JSC
$SCOPE_LOCAL
= 2;
5431 function JSC
$NameSpace ()
5433 this.frame
= new JSC
$NameSpaceFrame ();
5434 this.push_frame
= JSC
$NameSpace_push_frame
;
5435 this.pop_frame
= JSC
$NameSpace_pop_frame
;
5436 this.alloc_local
= JSC
$NameSpace_alloc_local
;
5437 this.define_symbol
= JSC
$NameSpace_define_symbol
;
5438 this.lookup_symbol
= JSC
$NameSpace_lookup_symbol
;
5442 function JSC
$NameSpace_push_frame ()
5444 var f
= new JSC
$NameSpaceFrame ();
5446 f
.num_locals
= this.frame
.num_locals
;
5448 f
.next
= this.frame
;
5453 function JSC
$NameSpace_pop_frame ()
5457 for (i
= this.frame
.defs
; i
!= null; i
= i
.next
)
5458 if (i
.usecount
== 0)
5460 if (i
.scope
== JSC
$SCOPE_ARG
)
5462 if (JSC
$warn_unused_argument
)
5463 JSC
$warning (JSC
$filename
+ ":" + i
.linenum
.toString ()
5464 + ": warning: unused argument `" + i
.symbol
+ "'");
5468 if (JSC
$warn_unused_variable
)
5469 JSC
$warning (JSC
$filename
+ ":" + i
.linenum
.toString ()
5470 + ": warning: unused variable `" + i
.symbol
+ "'");
5474 this.frame
= this.frame
.next
;
5478 function JSC
$NameSpace_alloc_local ()
5480 return this.frame
.num_locals
++;
5484 function JSC
$NameSpace_define_symbol (symbol
, scope
, value
, linenum
)
5488 for (i
= this.frame
.defs
; i
!= null; i
= i
.next
)
5489 if (i
.symbol
== symbol
)
5491 if (i
.scope
== scope
)
5492 error (JSC
$filename
+ ":" + i
.linenum
.toString()
5493 + ": redeclaration of `" + i
.symbol
+ "'");
5494 if (i
.scope
== JSC
$SCOPE_ARG
&& JSC
$warn_shadow
)
5495 JSC
$warning (JSC
$filename
+ ":" + linenum
.toString ()
5496 + ": warning: declaration of `" + symbol
5497 + "' shadows a parameter");
5501 i
.linenum
= linenum
;
5506 /* Create a new definition. */
5507 i
= new JSC
$SymbolDefinition (symbol
, scope
, value
, linenum
);
5508 i
.next
= this.frame
.defs
;
5509 this.frame
.defs
= i
;
5513 function JSC
$NameSpace_lookup_symbol (symbol
)
5517 for (f
= this.frame
; f
!= null; f
= f
.next
)
5518 for (i
= f
.defs
; i
!= null; i
= i
.next
)
5519 if (i
.symbol
== symbol
)
5532 function JSC
$NameSpaceFrame ()
5536 this.num_locals
= 0;
5540 function JSC
$SymbolDefinition (symbol
, scope
, value
, linenum
)
5543 this.symbol
= symbol
;
5546 this.linenum
= linenum
;
5557 * Input stream definitions.
5558 * Copyright (c) 1998 New Generation Software (NGS) Oy
5560 * Author: Markku Rossi <mtr@ngs.fi>
5564 * This library is free software; you can redistribute it and/or
5565 * modify it under the terms of the GNU Library General Public
5566 * License as published by the Free Software Foundation; either
5567 * version 2 of the License, or (at your option) any later version.
5569 * This library is distributed in the hope that it will be useful,
5570 * but WITHOUT ANY WARRANTY; without even the implied warranty of
5571 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5572 * Library General Public License for more details.
5574 * You should have received a copy of the GNU Library General Public
5575 * License along with this library; if not, write to the Free
5576 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
5577 * MA 02111-1307, USA
5581 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/jsc/compiler.js,v $
5589 function JSC
$StreamFile (name
)
5592 this.stream
= new File (name
);
5595 this.open
= JSC
$StreamFile_open
;
5596 this.close
= JSC
$StreamFile_close
;
5597 this.rewind
= JSC
$StreamFile_rewind
;
5598 this.readByte
= JSC
$StreamFile_read_byte
;
5599 this.ungetByte
= JSC
$StreamFile_unget_byte
;
5600 this.readln
= JSC
$StreamFile_readln
;
5604 function JSC
$StreamFile_open ()
5606 if (!this.stream
.open ("r"))
5608 this.error
= System
.strerror (System
.errno
);
5616 function JSC
$StreamFile_close ()
5618 return this.stream
.close ();
5622 function JSC
$StreamFile_rewind ()
5624 return this.stream
.setPosition (0);
5628 function JSC
$StreamFile_read_byte ()
5630 return this.stream
.readByte ();
5634 function JSC
$StreamFile_unget_byte (byte)
5636 this.stream
.ungetByte (byte);
5640 function JSC
$StreamFile_readln ()
5642 return this.stream
.readln ();
5650 function JSC
$StreamString (str
)
5652 this.name
= "StringStream";
5655 this.unget_byte
= -1;
5658 this.open
= JSC
$StreamString_open
;
5659 this.close
= JSC
$StreamString_close
;
5660 this.rewind
= JSC
$StreamString_rewind
;
5661 this.readByte
= JSC
$StreamString_read_byte
;
5662 this.ungetByte
= JSC
$StreamString_unget_byte
;
5663 this.readln
= JSC
$StreamString_readln
;
5667 function JSC
$StreamString_open ()
5673 function JSC
$StreamString_close ()
5679 function JSC
$StreamString_rewind ()
5682 this.unget_byte
= -1;
5688 function JSC
$StreamString_read_byte ()
5692 if (this.unget_byte
>= 0)
5694 ch
= this.unget_byte
;
5695 this.unget_byte
= -1;
5699 if (this.pos
>= this.string
.length
)
5702 return this.string
.charCodeAt (this.pos
++);
5706 function JSC
$StreamString_unget_byte (byte)
5708 this.unget_byte
= byte;
5712 function JSC
$StreamString_readln ()
5714 var line
= new String ("");
5717 while ((ch
= this.readByte ()) != -1 && ch
!= #'\n')
5718 line
.append (String
.pack ("C", ch
));
5730 * JavaScript Assembler.
5731 * Copyright (c) 1998 New Generation Software (NGS) Oy
5733 * Author: Markku Rossi <mtr@ngs.fi>
5737 * This library is free software; you can redistribute it and/or
5738 * modify it under the terms of the GNU Library General Public
5739 * License as published by the Free Software Foundation; either
5740 * version 2 of the License, or (at your option) any later version.
5742 * This library is distributed in the hope that it will be useful,
5743 * but WITHOUT ANY WARRANTY; without even the implied warranty of
5744 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5745 * Library General Public License for more details.
5747 * You should have received a copy of the GNU Library General Public
5748 * License along with this library; if not, write to the Free
5749 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
5750 * MA 02111-1307, USA
5754 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/jsc/compiler.js,v $
5758 /* Byte-code file definitions. */
5760 JSC
$BC_MAGIC
= 0xc0014a53;
5762 JSC
$BC_SECT_CODE
= 0;
5763 JSC
$BC_SECT_CONSTANTS
= 1;
5764 JSC
$BC_SECT_SYMTAB
= 2;
5765 JSC
$BC_SECT_DEBUG
= 3;
5768 JSC
$CONST_STRING
= 4;
5769 JSC
$CONST_FLOAT
= 5;
5770 JSC
$CONST_SYMBOL
= 10;
5771 JSC
$CONST_REGEXP
= 11;
5774 JSC
$CONST_REGEXP_FLAG_G
= 0x01;
5775 JSC
$CONST_REGEXP_FLAG_I
= 0x02;
5777 JSC
$DEBUG_FILENAME
= 1;
5778 JSC
$DEBUG_LINENUMBER
= 2;
5780 /* Opcode definitions. */
5792 JSC
$OP_CONST_NULL
= 10;
5793 JSC
$OP_CONST_TRUE
= 11;
5794 JSC
$OP_CONST_FALSE
= 12;
5795 JSC
$OP_CONST_UNDEFINED
= 13;
5796 JSC
$OP_CONST_I0
= 14;
5797 JSC
$OP_CONST_I1
= 15;
5798 JSC
$OP_CONST_I2
= 16;
5799 JSC
$OP_CONST_I3
= 17;
5800 JSC
$OP_CONST_I
= 18;
5801 JSC
$OP_LOAD_GLOBAL
= 19;
5802 JSC
$OP_STORE_GLOBAL
= 20;
5803 JSC
$OP_LOAD_ARG
= 21;
5804 JSC
$OP_STORE_ARG
= 22;
5805 JSC
$OP_LOAD_LOCAL
= 23;
5806 JSC
$OP_STORE_LOCAL
= 24;
5807 JSC
$OP_LOAD_PROPERTY
= 25;
5808 JSC
$OP_STORE_PROPERTY
= 26;
5809 JSC
$OP_LOAD_ARRAY
= 27;
5810 JSC
$OP_STORE_ARRAY
= 28;
5818 JSC
$OP_CMP_SEQ
= 36;
5819 JSC
$OP_CMP_SNE
= 37;
5830 JSC
$OP_SHIFT_LEFT
= 48;
5831 JSC
$OP_SHIFT_RIGHT
= 49;
5832 JSC
$OP_SHIFT_RRIGHT
= 50;
5833 JSC
$OP_IFFALSE
= 51;
5835 JSC
$OP_CALL_METHOD
= 53;
5841 JSC
$OP_DELETE_PROPERTY
= 59;
5842 JSC
$OP_DELETE_ARRAY
= 60;
5844 JSC
$OP_MIN_ARGS
= 62;
5845 JSC
$OP_LOAD_NTH_ARG
= 63;
5846 JSC
$OP_WITH_PUSH
= 64;
5847 JSC
$OP_WITH_POP
= 65;
5848 JSC
$OP_TRY_PUSH
= 66;
5849 JSC
$OP_TRY_POP
= 67;
5852 /* Type aware operands. */
5853 JSC
$OP_IFFALSE_B
= 69;
5854 JSC
$OP_IFTRUE_B
= 70;
5855 JSC
$OP_ADD_1_I
= 71;
5856 JSC
$OP_ADD_2_I
= 72;
5857 JSC
$OP_LOAD_GLOBAL_W
= 73;
5860 /* Internal values. */
5861 JSC
$ASM_SYMBOL
= 1000;
5862 JSC
$ASM_LABEL
= 1001;
5868 /* Generate byte-code for operands with Int8 value. */
5869 function JSC
$ASM_bytecode_int8 ()
5871 return String
.pack ("C", this.value
);
5874 /* Generate byte-code for operands with Int16 value. */
5875 function JSC
$ASM_bytecode_int16 ()
5877 return String
.pack ("n", this.value
);
5880 /* Generate byte-code for operands with Int32 value. */
5881 function JSC
$ASM_bytecode_int32 ()
5883 return String
.pack ("N", this.value
);
5886 /* Generate byte-code for operands with Symbol value. */
5887 function JSC
$ASM_bytecode_symbol ()
5889 var cid
= JSC
$asm_genconstant (String
.pack ("C", JSC
$CONST_SYMBOL
)
5890 + this.value
+ String
.pack ("C", 0));
5891 return String
.pack ("N", cid
);
5894 /* Generate byte-code for local jump operands. */
5895 function JSC
$ASM_bytecode_local_jump ()
5897 var delta
= this.value
.offset
- (this.offset
+ this.size
);
5898 return String
.pack ("N", delta
);
5903 * Assembler operands.
5908 function JSC
$ASM_symbol (ln
, value
)
5910 this.type
= JSC
$ASM_SYMBOL
;
5914 this.print
= JSC
$ASM_symbol_print
;
5915 this.link
= JSC
$asm_link
;
5918 function JSC
$ASM_symbol_print (stream
)
5920 stream
.write ("\n" + this.value
+ ":\n");
5925 function JSC
$ASM_label ()
5927 this.type
= JSC
$ASM_LABEL
;
5930 this.value
= JSC
$asm_label_count
++;
5931 this.referenced
= false;
5933 this.print
= JSC
$ASM_label_print
;
5934 this.link
= JSC
$asm_link
;
5935 this.format
= JSC
$ASM_label_format
;
5938 function JSC
$ASM_label_print (stream
)
5940 stream
.write (this.format () + ":\n");
5943 function JSC
$ASM_label_format ()
5945 return ".L" + this.value
.toString ();
5950 function JSC
$ASM_halt (ln
)
5952 this.type
= JSC
$OP_HALT
;
5955 this.print
= JSC
$ASM_halt_print
;
5956 this.link
= JSC
$asm_link
;
5959 function JSC
$ASM_halt_print (stream
)
5961 stream
.write ("\thalt\n");
5966 function JSC
$ASM_done (ln
)
5968 this.type
= JSC
$OP_DONE
;
5971 this.print
= JSC
$ASM_done_print
;
5972 this.link
= JSC
$asm_link
;
5975 function JSC
$ASM_done_print (stream
)
5977 stream
.write ("\tdone\n");
5982 function JSC
$ASM_nop (ln
)
5984 this.type
= JSC
$OP_NOP
;
5987 this.print
= JSC
$ASM_nop_print
;
5988 this.link
= JSC
$asm_link
;
5991 function JSC
$ASM_nop_print (stream
)
5993 stream
.write ("\tnop\n");
5998 function JSC
$ASM_dup (ln
)
6000 this.type
= JSC
$OP_DUP
;
6002 this.stack_delta
= 1;
6004 this.print
= JSC
$ASM_dup_print
;
6005 this.link
= JSC
$asm_link
;
6008 function JSC
$ASM_dup_print (stream
)
6010 stream
.write ("\tdup\n");
6015 function JSC
$ASM_pop (ln
)
6017 this.type
= JSC
$OP_POP
;
6019 this.stack_delta
= -1;
6021 this.print
= JSC
$ASM_pop_print
;
6022 this.link
= JSC
$asm_link
;
6025 function JSC
$ASM_pop_print (stream
)
6027 stream
.write ("\tpop\n");
6032 function JSC
$ASM_pop_n (ln
, value
)
6034 this.type
= JSC
$OP_POP_N
;
6037 this.stack_delta
= -value
;
6039 this.print
= JSC
$ASM_pop_n_print
;
6040 this.link
= JSC
$asm_link
;
6041 this.bytecode
= JSC
$ASM_bytecode_int8
;
6044 function JSC
$ASM_pop_n_print (stream
)
6046 stream
.write ("\tpop_n\t\t" + this.value
.toString () + "\n");
6051 function JSC
$ASM_apop (ln
, value
)
6053 this.type
= JSC
$OP_APOP
;
6056 this.stack_delta
= -value
;
6058 this.print
= JSC
$ASM_apop_print
;
6059 this.link
= JSC
$asm_link
;
6060 this.bytecode
= JSC
$ASM_bytecode_int8
;
6063 function JSC
$ASM_apop_print (stream
)
6065 stream
.write ("\tapop\t\t" + this.value
.toString () + "\n");
6070 function JSC
$ASM_swap (ln
)
6072 this.type
= JSC
$OP_SWAP
;
6075 this.print
= JSC
$ASM_swap_print
;
6076 this.link
= JSC
$asm_link
;
6079 function JSC
$ASM_swap_print (stream
)
6081 stream
.write ("\tswap\n");
6085 function JSC
$ASM_roll (ln
, value
)
6087 this.type
= JSC
$OP_ROLL
;
6091 this.print
= JSC
$ASM_roll_print
;
6092 this.link
= JSC
$asm_link
;
6093 this.bytecode
= JSC
$ASM_bytecode_int8
;
6096 function JSC
$ASM_roll_print (stream
)
6098 stream
.write ("\troll\t\t" + this.value
.toString () + "\n");
6103 function JSC
$ASM_const (ln
, value
)
6105 this.type
= JSC
$OP_CONST
;
6108 this.stack_delta
= 1;
6110 this.print
= JSC
$ASM_const_print
;
6111 this.link
= JSC
$asm_link
;
6112 this.bytecode
= JSC
$ASM_const_bytecode
;
6115 function JSC
$ASM_const_print (stream
)
6117 if (typeof this.value
== "number")
6118 stream
.write ("\tconst\t\t" + this.value
.toString () + "\n");
6119 else if (typeof this.value
== "string"
6120 || typeof this.value
== "#builtin")
6124 var stringp
= (typeof this.value
== "string");
6134 src
= this.value
.source
;
6137 stream
.write ("\tconst\t\t" + ender
);
6138 for (i
= 0; i
< src
.length
; i
++)
6140 c
= src
.charCodeAt (i
);
6141 if (c
== ender
[0] || c
== #'\\')
6142 stream
.write ("\\" + src
.charAt (i
));
6143 else if (c
== #'\n')
6144 stream
.write ("\\n");
6145 else if (c
== #'\r')
6146 stream
.write ("\\r");
6147 else if (c
== #'\t')
6148 stream
.write ("\\t");
6149 else if (c
== #'\f')
6150 stream
.write ("\\f");
6152 stream
.write (src
.charAt (i
));
6154 stream
.write (ender
);
6158 if (this.value
.global
)
6160 if (this.value
.ignoreCase
)
6164 stream
.write ("\n");
6168 function JSC
$ASM_const_bytecode ()
6172 if (typeof this.value
== "number")
6174 if (isInt (this.value
))
6175 cid
= JSC
$asm_genconstant (String
.pack ("CN", JSC
$CONST_INT
,
6177 else if (isFloat (this.value
))
6178 cid
= JSC
$asm_genconstant (String
.pack ("Cd", JSC
$CONST_FLOAT
,
6181 cid
= JSC
$asm_genconstant (String
.pack ("C", JSC
$CONST_NAN
));
6183 else if (typeof this.value
== "string")
6184 cid
= JSC
$asm_genconstant (String
.pack ("CN", JSC
$CONST_STRING
,
6187 else if (typeof this.value
== "#builtin")
6189 /* Regular expression. */
6192 if (this.value
.global
)
6193 flags
|= JSC
$CONST_REGEXP_FLAG_G
;
6194 if (this.value
.ignoreCase
)
6195 flags
|= JSC
$CONST_REGEXP_FLAG_I
;
6197 cid
= JSC
$asm_genconstant (String
.pack ("CCN", JSC
$CONST_REGEXP
, flags
,
6198 this.value
.source
.length
)
6199 + this.value
.source
);
6202 error ("ASM_const_bytecode(): unknown type: " + typeof this.value
);
6204 return String
.pack ("N", cid
);
6209 function JSC
$ASM_const_null (ln
)
6211 this.type
= JSC
$OP_CONST_NULL
;
6213 this.stack_delta
= 1;
6215 this.print
= JSC
$ASM_const_null_print
;
6216 this.link
= JSC
$asm_link
;
6219 function JSC
$ASM_const_null_print (stream
)
6221 stream
.write ("\tconst_null\n");
6226 function JSC
$ASM_const_true (ln
)
6228 this.type
= JSC
$OP_CONST_TRUE
;
6230 this.stack_delta
= 1;
6232 this.print
= JSC
$ASM_const_true_print
;
6233 this.link
= JSC
$asm_link
;
6236 function JSC
$ASM_const_true_print (stream
)
6238 stream
.write ("\tconst_true\n");
6243 function JSC
$ASM_const_false (ln
)
6245 this.type
= JSC
$OP_CONST_FALSE
;
6247 this.stack_delta
= 1;
6249 this.print
= JSC
$ASM_const_false_print
;
6250 this.link
= JSC
$asm_link
;
6253 function JSC
$ASM_const_false_print (stream
)
6255 stream
.write ("\tconst_false\n");
6258 /* const_undefined */
6260 function JSC
$ASM_const_undefined (ln
)
6262 this.type
= JSC
$OP_CONST_UNDEFINED
;
6264 this.stack_delta
= 1;
6266 this.print
= JSC
$ASM_const_undefined_print
;
6267 this.link
= JSC
$asm_link
;
6270 function JSC
$ASM_const_undefined_print (stream
)
6272 stream
.write ("\tconst_undefined\n");
6277 function JSC
$ASM_const_i0 (ln
)
6279 this.type
= JSC
$OP_CONST_I0
;
6281 this.stack_delta
= 1;
6283 this.print
= JSC
$ASM_const_i0_print
;
6284 this.link
= JSC
$asm_link
;
6287 function JSC
$ASM_const_i0_print (stream
)
6289 stream
.write ("\tconst_i0\n");
6294 function JSC
$ASM_const_i1 (ln
)
6296 this.type
= JSC
$OP_CONST_I1
;
6298 this.stack_delta
= 1;
6300 this.print
= JSC
$ASM_const_i1_print
;
6301 this.link
= JSC
$asm_link
;
6304 function JSC
$ASM_const_i1_print (stream
)
6306 stream
.write ("\tconst_i1\n");
6311 function JSC
$ASM_const_i2 (ln
)
6313 this.type
= JSC
$OP_CONST_I2
;
6315 this.stack_delta
= 1;
6317 this.print
= JSC
$ASM_const_i2_print
;
6318 this.link
= JSC
$asm_link
;
6321 function JSC
$ASM_const_i2_print (stream
)
6323 stream
.write ("\tconst_i2\n");
6328 function JSC
$ASM_const_i3 (ln
)
6330 this.type
= JSC
$OP_CONST_I3
;
6332 this.stack_delta
= 1;
6334 this.print
= JSC
$ASM_const_i3_print
;
6335 this.link
= JSC
$asm_link
;
6338 function JSC
$ASM_const_i3_print (stream
)
6340 stream
.write ("\tconst_i3\n");
6345 function JSC
$ASM_const_i (ln
, value
)
6347 this.type
= JSC
$OP_CONST_I
;
6350 this.stack_delta
= 1;
6352 this.print
= JSC
$ASM_const_i_print
;
6353 this.bytecode
= JSC
$ASM_bytecode_int32
;
6354 this.link
= JSC
$asm_link
;
6357 function JSC
$ASM_const_i_print (stream
)
6359 stream
.write ("\tconst_i\t\t" + this.value
.toString () + "\n");
6364 function JSC
$ASM_load_global (ln
, value
)
6366 this.type
= JSC
$OP_LOAD_GLOBAL
;
6369 this.stack_delta
= 1;
6371 this.print
= JSC
$ASM_load_global_print
;
6372 this.bytecode
= JSC
$ASM_bytecode_symbol
;
6373 this.link
= JSC
$asm_link
;
6376 function JSC
$ASM_load_global_print (stream
)
6378 stream
.write ("\tload_global\t" + this.value
+ "\n");
6383 function JSC
$ASM_store_global (ln
, value
)
6385 this.type
= JSC
$OP_STORE_GLOBAL
;
6388 this.stack_delta
= -1;
6390 this.print
= JSC
$ASM_store_global_print
;
6391 this.bytecode
= JSC
$ASM_bytecode_symbol
;
6392 this.link
= JSC
$asm_link
;
6395 function JSC
$ASM_store_global_print (stream
)
6397 stream
.write ("\tstore_global\t" + this.value
+ "\n");
6402 function JSC
$ASM_load_arg (ln
, value
)
6404 this.type
= JSC
$OP_LOAD_ARG
;
6407 this.stack_delta
= 1;
6409 this.print
= JSC
$ASM_load_arg_print
;
6410 this.bytecode
= JSC
$ASM_bytecode_int8
;
6411 this.link
= JSC
$asm_link
;
6414 function JSC
$ASM_load_arg_print (stream
)
6416 stream
.write ("\tload_arg\t" + this.value
.toString () + "\n");
6421 function JSC
$ASM_store_arg (ln
, value
)
6423 this.type
= JSC
$OP_STORE_ARG
;
6426 this.stack_delta
= -1;
6428 this.print
= JSC
$ASM_store_arg_print
;
6429 this.bytecode
= JSC
$ASM_bytecode_int8
;
6430 this.link
= JSC
$asm_link
;
6433 function JSC
$ASM_store_arg_print (stream
)
6435 stream
.write ("\tstore_arg\t" + this.value
.toString () + "\n");
6440 function JSC
$ASM_load_local (ln
, value
)
6442 this.type
= JSC
$OP_LOAD_LOCAL
;
6445 this.stack_delta
= 1;
6447 this.print
= JSC
$ASM_load_local_print
;
6448 this.bytecode
= JSC
$ASM_bytecode_int16
;
6449 this.link
= JSC
$asm_link
;
6452 function JSC
$ASM_load_local_print (stream
)
6454 stream
.write ("\tload_local\t" + this.value
.toString () + "\n");
6459 function JSC
$ASM_store_local (ln
, value
)
6461 this.type
= JSC
$OP_STORE_LOCAL
;
6464 this.stack_delta
= -1;
6466 this.print
= JSC
$ASM_store_local_print
;
6467 this.bytecode
= JSC
$ASM_bytecode_int16
;
6468 this.link
= JSC
$asm_link
;
6471 function JSC
$ASM_store_local_print (stream
)
6473 stream
.write ("\tstore_local\t" + this.value
.toString () + "\n");
6478 function JSC
$ASM_load_property (ln
, value
)
6480 this.type
= JSC
$OP_LOAD_PROPERTY
;
6484 this.print
= JSC
$ASM_load_property_print
;
6485 this.bytecode
= JSC
$ASM_bytecode_symbol
;
6486 this.link
= JSC
$asm_link
;
6489 function JSC
$ASM_load_property_print (stream
)
6491 stream
.write ("\tload_property\t" + this.value
+ "\n");
6494 /* store_property */
6496 function JSC
$ASM_store_property (ln
, value
)
6498 this.type
= JSC
$OP_STORE_PROPERTY
;
6501 this.stack_delta
= -2;
6503 this.print
= JSC
$ASM_store_property_print
;
6504 this.bytecode
= JSC
$ASM_bytecode_symbol
;
6505 this.link
= JSC
$asm_link
;
6508 function JSC
$ASM_store_property_print (stream
)
6510 stream
.write ("\tstore_property\t" + this.value
+ "\n");
6515 function JSC
$ASM_load_array (ln
)
6517 this.type
= JSC
$OP_LOAD_ARRAY
;
6519 this.stack_delta
= -1;
6521 this.print
= JSC
$ASM_load_array_print
;
6522 this.link
= JSC
$asm_link
;
6525 function JSC
$ASM_load_array_print (stream
)
6527 stream
.write ("\tload_array\n");
6532 function JSC
$ASM_store_array (ln
)
6534 this.type
= JSC
$OP_STORE_ARRAY
;
6536 this.stack_delta
= -3;
6538 this.print
= JSC
$ASM_store_array_print
;
6539 this.link
= JSC
$asm_link
;
6542 function JSC
$ASM_store_array_print (stream
)
6544 stream
.write ("\tstore_array\n");
6549 function JSC
$ASM_nth (ln
)
6551 this.type
= JSC
$OP_NTH
;
6554 this.print
= JSC
$ASM_nth_print
;
6555 this.link
= JSC
$asm_link
;
6558 function JSC
$ASM_nth_print (stream
)
6560 stream
.write ("\tnth\n");
6565 function JSC
$ASM_cmp_eq (ln
)
6567 this.type
= JSC
$OP_CMP_EQ
;
6569 this.stack_delta
= -1;
6571 this.print
= JSC
$ASM_cmp_eq_print
;
6572 this.link
= JSC
$asm_link
;
6575 function JSC
$ASM_cmp_eq_print (stream
)
6577 stream
.write ("\tcmp_eq\n");
6582 function JSC
$ASM_cmp_ne (ln
)
6584 this.type
= JSC
$OP_CMP_NE
;
6586 this.stack_delta
= -1;
6588 this.print
= JSC
$ASM_cmp_ne_print
;
6589 this.link
= JSC
$asm_link
;
6592 function JSC
$ASM_cmp_ne_print (stream
)
6594 stream
.write ("\tcmp_ne\n");
6599 function JSC
$ASM_cmp_lt (ln
)
6601 this.type
= JSC
$OP_CMP_LT
;
6603 this.stack_delta
= -1;
6605 this.print
= JSC
$ASM_cmp_lt_print
;
6606 this.link
= JSC
$asm_link
;
6609 function JSC
$ASM_cmp_lt_print (stream
)
6611 stream
.write ("\tcmp_lt\n");
6616 function JSC
$ASM_cmp_gt (ln
)
6618 this.type
= JSC
$OP_CMP_GT
;
6620 this.stack_delta
= -1;
6622 this.print
= JSC
$ASM_cmp_gt_print
;
6623 this.link
= JSC
$asm_link
;
6626 function JSC
$ASM_cmp_gt_print (stream
)
6628 stream
.write ("\tcmp_gt\n");
6633 function JSC
$ASM_cmp_le (ln
)
6635 this.type
= JSC
$OP_CMP_LE
;
6637 this.stack_delta
= -1;
6639 this.print
= JSC
$ASM_cmp_le_print
;
6640 this.link
= JSC
$asm_link
;
6643 function JSC
$ASM_cmp_le_print (stream
)
6645 stream
.write ("\tcmp_le\n");
6650 function JSC
$ASM_cmp_ge (ln
)
6652 this.type
= JSC
$OP_CMP_GE
;
6654 this.stack_delta
= -1;
6656 this.print
= JSC
$ASM_cmp_ge_print
;
6657 this.link
= JSC
$asm_link
;
6660 function JSC
$ASM_cmp_ge_print (stream
)
6662 stream
.write ("\tcmp_ge\n");
6667 function JSC
$ASM_cmp_seq (ln
)
6669 this.type
= JSC
$OP_CMP_SEQ
;
6671 this.stack_delta
= -1;
6673 this.print
= JSC
$ASM_cmp_seq_print
;
6674 this.link
= JSC
$asm_link
;
6677 function JSC
$ASM_cmp_seq_print (stream
)
6679 stream
.write ("\tcmp_seq\n");
6684 function JSC
$ASM_cmp_sne (ln
)
6686 this.type
= JSC
$OP_CMP_SNE
;
6688 this.stack_delta
= -1;
6690 this.print
= JSC
$ASM_cmp_sne_print
;
6691 this.link
= JSC
$asm_link
;
6694 function JSC
$ASM_cmp_sne_print (stream
)
6696 stream
.write ("\tcmp_sne\n");
6701 function JSC
$ASM_sub (ln
)
6703 this.type
= JSC
$OP_SUB
;
6705 this.stack_delta
= -1;
6707 this.print
= JSC
$ASM_sub_print
;
6708 this.link
= JSC
$asm_link
;
6711 function JSC
$ASM_sub_print (stream
)
6713 stream
.write ("\tsub\n");
6718 function JSC
$ASM_add (ln
)
6720 this.type
= JSC
$OP_ADD
;
6722 this.stack_delta
= -1;
6724 this.print
= JSC
$ASM_add_print
;
6725 this.link
= JSC
$asm_link
;
6728 function JSC
$ASM_add_print (stream
)
6730 stream
.write ("\tadd\n");
6735 function JSC
$ASM_mul (ln
)
6737 this.type
= JSC
$OP_MUL
;
6739 this.stack_delta
= -1;
6741 this.print
= JSC
$ASM_mul_print
;
6742 this.link
= JSC
$asm_link
;
6745 function JSC
$ASM_mul_print (stream
)
6747 stream
.write ("\tmul\n");
6752 function JSC
$ASM_div (ln
)
6754 this.type
= JSC
$OP_DIV
;
6756 this.stack_delta
= -1;
6758 this.print
= JSC
$ASM_div_print
;
6759 this.link
= JSC
$asm_link
;
6762 function JSC
$ASM_div_print (stream
)
6764 stream
.write ("\tdiv\n");
6769 function JSC
$ASM_mod (ln
)
6771 this.type
= JSC
$OP_MOD
;
6773 this.stack_delta
= -1;
6775 this.print
= JSC
$ASM_mod_print
;
6776 this.link
= JSC
$asm_link
;
6779 function JSC
$ASM_mod_print (stream
)
6781 stream
.write ("\tmod\n");
6786 function JSC
$ASM_neg (ln
)
6788 this.type
= JSC
$OP_NEG
;
6791 this.print
= JSC
$ASM_neg_print
;
6792 this.link
= JSC
$asm_link
;
6795 function JSC
$ASM_neg_print (stream
)
6797 stream
.write ("\tneg\n");
6802 function JSC
$ASM_and (ln
)
6804 this.type
= JSC
$OP_AND
;
6806 this.stack_delta
= -1;
6808 this.print
= JSC
$ASM_and_print
;
6809 this.link
= JSC
$asm_link
;
6812 function JSC
$ASM_and_print (stream
)
6814 stream
.write ("\tand\n");
6819 function JSC
$ASM_not (ln
)
6821 this.type
= JSC
$OP_NOT
;
6824 this.print
= JSC
$ASM_not_print
;
6825 this.link
= JSC
$asm_link
;
6828 function JSC
$ASM_not_print (stream
)
6830 stream
.write ("\tnot\n");
6835 function JSC
$ASM_or (ln
)
6837 this.type
= JSC
$OP_OR
;
6839 this.stack_delta
= -1;
6841 this.print
= JSC
$ASM_or_print
;
6842 this.link
= JSC
$asm_link
;
6845 function JSC
$ASM_or_print (stream
)
6847 stream
.write ("\tor\n");
6852 function JSC
$ASM_xor (ln
)
6854 this.type
= JSC
$OP_XOR
;
6856 this.stack_delta
= -1;
6858 this.print
= JSC
$ASM_xor_print
;
6859 this.link
= JSC
$asm_link
;
6862 function JSC
$ASM_xor_print (stream
)
6864 stream
.write ("\txor\n");
6869 function JSC
$ASM_shift_left (ln
)
6871 this.type
= JSC
$OP_SHIFT_LEFT
;
6873 this.stack_delta
= -1;
6875 this.print
= JSC
$ASM_shift_left_print
;
6876 this.link
= JSC
$asm_link
;
6879 function JSC
$ASM_shift_left_print (stream
)
6881 stream
.write ("\tshift_left\n");
6886 function JSC
$ASM_shift_right (ln
)
6888 this.type
= JSC
$OP_SHIFT_RIGHT
;
6890 this.stack_delta
= -1;
6892 this.print
= JSC
$ASM_shift_right_print
;
6893 this.link
= JSC
$asm_link
;
6896 function JSC
$ASM_shift_right_print (stream
)
6898 stream
.write ("\tshift_right\n");
6903 function JSC
$ASM_shift_rright (ln
)
6905 this.type
= JSC
$OP_SHIFT_RRIGHT
;
6907 this.stack_delta
= -1;
6909 this.print
= JSC
$ASM_shift_rright_print
;
6910 this.link
= JSC
$asm_link
;
6913 function JSC
$ASM_shift_rright_print (stream
)
6915 stream
.write ("\tshift_rright\n");
6920 function JSC
$ASM_iffalse (ln
, value
)
6922 this.type
= JSC
$OP_IFFALSE
;
6925 this.stack_delta
= -1;
6927 this.print
= JSC
$ASM_iffalse_print
;
6928 this.bytecode
= JSC
$ASM_bytecode_local_jump
;
6929 this.link
= JSC
$asm_link
;
6932 function JSC
$ASM_iffalse_print (stream
)
6934 stream
.write ("\tiffalse\t\t" + this.value
.format () + "\n");
6939 function JSC
$ASM_iftrue (ln
, value
)
6941 this.type
= JSC
$OP_IFTRUE
;
6944 this.stack_delta
= -1;
6946 this.print
= JSC
$ASM_iftrue_print
;
6947 this.bytecode
= JSC
$ASM_bytecode_local_jump
;
6948 this.link
= JSC
$asm_link
;
6951 function JSC
$ASM_iftrue_print (stream
)
6953 stream
.write ("\tiftrue\t\t" + this.value
.format () + "\n");
6958 function JSC
$ASM_call_method (ln
, value
)
6960 this.type
= JSC
$OP_CALL_METHOD
;
6963 this.stack_delta
= 1;
6965 this.print
= JSC
$ASM_call_method_print
;
6966 this.bytecode
= JSC
$ASM_bytecode_symbol
;
6967 this.link
= JSC
$asm_link
;
6970 function JSC
$ASM_call_method_print (stream
)
6972 stream
.write ("\tcall_method\t" + this.value
+ "\n");
6977 function JSC
$ASM_jmp (ln
, value
)
6979 this.type
= JSC
$OP_JMP
;
6983 this.print
= JSC
$ASM_jmp_print
;
6984 this.bytecode
= JSC
$ASM_bytecode_local_jump
;
6985 this.link
= JSC
$asm_link
;
6988 function JSC
$ASM_jmp_print (stream
)
6990 stream
.write ("\tjmp\t\t" + this.value
.format () + "\n");
6995 function JSC
$ASM_jsr (ln
)
6997 this.type
= JSC
$OP_JSR
;
6999 this.stack_delta
= 1;
7001 this.print
= JSC
$ASM_jsr_print
;
7002 this.link
= JSC
$asm_link
;
7005 function JSC
$ASM_jsr_print (stream
)
7007 stream
.write ("\tjsr\n");
7012 function JSC
$ASM_return (ln
)
7014 this.type
= JSC
$OP_RETURN
;
7017 this.print
= JSC
$ASM_return_print
;
7018 this.link
= JSC
$asm_link
;
7021 function JSC
$ASM_return_print (stream
)
7023 stream
.write ("\treturn\n");
7028 function JSC
$ASM_typeof (ln
)
7030 this.type
= JSC
$OP_TYPEOF
;
7033 this.print
= JSC
$ASM_typeof_print
;
7034 this.link
= JSC
$asm_link
;
7037 function JSC
$ASM_typeof_print (stream
)
7039 stream
.write ("\ttypeof\n");
7044 function JSC
$ASM_new (ln
)
7046 this.type
= JSC
$OP_NEW
;
7048 this.stack_delta
= 1;
7050 this.print
= JSC
$ASM_new_print
;
7051 this.link
= JSC
$asm_link
;
7054 function JSC
$ASM_new_print (stream
)
7056 stream
.write ("\tnew\n");
7059 /* delete_property */
7061 function JSC
$ASM_delete_property (ln
, value
)
7063 this.type
= JSC
$OP_DELETE_PROPERTY
;
7067 this.print
= JSC
$ASM_delete_property_print
;
7068 this.bytecode
= JSC
$ASM_bytecode_symbol
;
7069 this.link
= JSC
$asm_link
;
7072 function JSC
$ASM_delete_property_print (stream
)
7074 stream
.write ("\tdelete_property\t" + this.value
+ "\n");
7079 function JSC
$ASM_delete_array (ln
)
7081 this.type
= JSC
$OP_DELETE_ARRAY
;
7083 this.stack_delta
= -1;
7085 this.print
= JSC
$ASM_delete_array_print
;
7086 this.link
= JSC
$asm_link
;
7089 function JSC
$ASM_delete_array_print (stream
)
7091 stream
.write ("\tdelete_array\n");
7096 function JSC
$ASM_locals (ln
, value
)
7098 this.type
= JSC
$OP_LOCALS
;
7101 this.stack_delta
= value
;
7103 this.print
= JSC
$ASM_locals_print
;
7104 this.bytecode
= JSC
$ASM_bytecode_int16
;
7105 this.link
= JSC
$asm_link
;
7108 function JSC
$ASM_locals_print (stream
)
7110 stream
.write ("\tlocals\t\t" + this.value
.toString () + "\n");
7115 function JSC
$ASM_min_args (ln
, value
)
7117 this.type
= JSC
$OP_MIN_ARGS
;
7120 this.stack_delta
= -1;
7122 this.print
= JSC
$ASM_min_args_print
;
7123 this.bytecode
= JSC
$ASM_bytecode_int8
;
7124 this.link
= JSC
$asm_link
;
7127 function JSC
$ASM_min_args_print (stream
)
7129 stream
.write ("\tmin_args\t" + this.value
.toString () + "\n");
7134 function JSC
$ASM_load_nth_arg (ln
)
7136 this.type
= JSC
$OP_LOAD_NTH_ARG
;
7139 this.print
= JSC
$ASM_load_nth_arg_print
;
7140 this.link
= JSC
$asm_link
;
7143 function JSC
$ASM_load_nth_arg_print (stream
)
7145 stream
.write ("\tload_nth_arg\n");
7150 function JSC
$ASM_with_push (ln
)
7152 this.type
= JSC
$OP_WITH_PUSH
;
7154 this.stack_delta
= -1;
7156 this.print
= JSC
$ASM_with_push_print
;
7157 this.link
= JSC
$asm_link
;
7160 function JSC
$ASM_with_push_print (stream
)
7162 stream
.write ("\twith_push\n");
7167 function JSC
$ASM_with_pop (ln
, value
)
7169 this.type
= JSC
$OP_WITH_POP
;
7173 this.print
= JSC
$ASM_with_pop_print
;
7174 this.bytecode
= JSC
$ASM_bytecode_int8
;
7175 this.link
= JSC
$asm_link
;
7178 function JSC
$ASM_with_pop_print (stream
)
7180 stream
.write ("\twith_pop\t" + this.value
.toString () + "\n");
7185 function JSC
$ASM_try_push (ln
, value
)
7187 this.type
= JSC
$OP_TRY_PUSH
;
7191 this.print
= JSC
$ASM_try_push_print
;
7192 this.bytecode
= JSC
$ASM_bytecode_local_jump
;
7193 this.link
= JSC
$asm_link
;
7196 function JSC
$ASM_try_push_print (stream
)
7198 stream
.write ("\ttry_push\t" + this.value
.format () + "\n");
7203 function JSC
$ASM_try_pop (ln
, value
)
7205 this.type
= JSC
$OP_TRY_POP
;
7209 this.print
= JSC
$ASM_try_pop_print
;
7210 this.bytecode
= JSC
$ASM_bytecode_int8
;
7211 this.link
= JSC
$asm_link
;
7214 function JSC
$ASM_try_pop_print (stream
)
7216 stream
.write ("\ttry_pop\t\t" + this.value
.toString () + "\n");
7221 function JSC
$ASM_throw (ln
)
7223 this.type
= JSC
$OP_THROW
;
7225 this.stack_delta
= -1;
7227 this.print
= JSC
$ASM_throw_print
;
7228 this.link
= JSC
$asm_link
;
7231 function JSC
$ASM_throw_print (stream
)
7233 stream
.write ("\tthrow\n");
7238 function JSC
$ASM_iffalse_b (ln
, value
)
7240 this.type
= JSC
$OP_IFFALSE_B
;
7243 this.stack_delta
= -1;
7245 this.print
= JSC
$ASM_iffalse_b_print
;
7246 this.bytecode
= JSC
$ASM_bytecode_local_jump
;
7247 this.link
= JSC
$asm_link
;
7250 function JSC
$ASM_iffalse_b_print (stream
)
7252 stream
.write ("\tiffalse_b\t" + this.value
.format () + "\n");
7257 function JSC
$ASM_iftrue_b (ln
, value
)
7259 this.type
= JSC
$OP_IFTRUE_B
;
7262 this.stack_delta
= -1;
7264 this.print
= JSC
$ASM_iftrue_b_print
;
7265 this.bytecode
= JSC
$ASM_bytecode_local_jump
;
7266 this.link
= JSC
$asm_link
;
7269 function JSC
$ASM_iftrue_b_print (stream
)
7271 stream
.write ("\tiftrue_b\t" + this.value
.format () + "\n");
7276 function JSC
$ASM_add_1_i (ln
)
7278 this.type
= JSC
$OP_ADD_1_I
;
7281 this.print
= JSC
$ASM_add_1_i_print
;
7282 this.link
= JSC
$asm_link
;
7285 function JSC
$ASM_add_1_i_print (stream
)
7287 stream
.write ("\tadd_1_i\n");
7292 function JSC
$ASM_add_2_i (ln
)
7294 this.type
= JSC
$OP_ADD_2_I
;
7297 this.print
= JSC
$ASM_add_2_i_print
;
7298 this.link
= JSC
$asm_link
;
7301 function JSC
$ASM_add_2_i_print (stream
)
7303 stream
.write ("\tadd_2_i\n");
7308 function JSC
$ASM_load_global_w (ln
, value
)
7310 this.type
= JSC
$OP_LOAD_GLOBAL_W
;
7313 this.stack_delta
= 1;
7315 this.print
= JSC
$ASM_load_global_w_print
;
7316 this.bytecode
= JSC
$ASM_bytecode_symbol
;
7317 this.link
= JSC
$asm_link
;
7320 function JSC
$ASM_load_global_w_print (stream
)
7322 stream
.write ("\tload_global_w\t" + this.value
+ "\n");
7327 function JSC
$ASM_jsr_w (ln
, value
)
7329 this.type
= JSC
$OP_JSR_W
;
7332 this.stack_delta
= 1;
7334 this.print
= JSC
$ASM_jsr_w_print
;
7335 this.bytecode
= JSC
$ASM_bytecode_symbol
;
7336 this.link
= JSC
$asm_link
;
7339 function JSC
$ASM_jsr_w_print (stream
)
7341 stream
.write ("\tjsr_w\t\t" + this.value
+ "\n");
7348 function JSC
$asm_link ()
7352 if (JSC
$asm_tail
!= null)
7354 JSC
$asm_tail_prev
= JSC
$asm_tail
;
7355 JSC
$asm_tail
.next
= this;
7358 JSC
$asm_head
= this;
7360 JSC
$asm_tail
= this;
7365 * The phases of the assembler.
7368 /* This is called from the compiler initialization code. */
7369 function JSC
$asm_reset ()
7371 JSC
$asm_label_count
= 1;
7372 JSC
$asm_head
= JSC
$asm_tail
= JSC
$asm_tail_prev
= null;
7373 JSC
$asm_constcount
= 0;
7374 JSC
$asm_constants
= null;
7375 JSC
$asm_known_constants
= null;
7379 function JSC
$asm_generate ()
7384 JSC
$message ("jsc: generating assembler");
7386 JSC
$ns
= new JSC
$NameSpace ();
7389 for (i
= 0; i
< JSC
$functions
.length
; i
++)
7390 JSC
$functions
[i
].asm ();
7392 /* Global statements. */
7393 if (JSC
$global_stmts
.length
> 0)
7395 /* Define the `.global' symbol. */
7396 new JSC
$ASM_symbol (JSC
$global_stmts
[0].linenum
, ".global").link ();
7398 /* Handle local variables. */
7399 var num_locals
= JSC
$count_locals_from_stmt_list (JSC
$global_stmts
);
7401 new JSC
$ASM_locals (JSC
$global_stmts
[0].linenum
, num_locals
).link ();
7403 /* Generate assembler. */
7404 for (i
= 0; i
< JSC
$global_stmts
.length
; i
++)
7405 JSC
$global_stmts
[i
].asm ();
7408 * Fix things so that also the global statement returns something
7409 * (this is required when we use eval() in JavaScript).
7411 if (JSC
$asm_tail_prev
== null)
7413 /* This is probably illegal, but we don't panic. */
7414 new JSC
$ASM_const_undefined (0).link ();
7419 * If the latest op is `pop', remove it. Otherwise, append
7420 * a `const_undefined'.
7422 if (JSC
$asm_tail
.type
== JSC
$OP_POP
)
7424 JSC
$asm_tail
= JSC
$asm_tail_prev
;
7425 JSC
$asm_tail
.next
= null;
7426 JSC
$asm_tail_prev
= null;
7429 new JSC
$ASM_const_undefined (JSC
$asm_tail
.linenum
).link ();
7437 function JSC
$asm_print (src_stream
, stream
)
7441 var annotate
= src_stream
? true : false;
7445 stream
.write ("; -*- asm -*-\n");
7447 /* Set the prev properties. */
7449 for (i
= JSC
$asm_head
; i
!= null; prev
= i
, i
= i
.next
)
7453 * Fix the label line numbers to be the same that the next
7454 * assembler operand has.
7457 for (i
= JSC
$asm_tail
; i
!= null; i
= i
.prev
)
7459 if (i
.type
== JSC
$ASM_LABEL
)
7460 i
.linenum
= last_ln
;
7461 else if (typeof i
.linenum
!= "undefined")
7462 last_ln
= i
.linenum
;
7467 for (i
= JSC
$asm_head
; i
!= null; i
= i
.next
)
7469 if (typeof i
.linenum
== "undefined")
7472 stream
.write ("; undefined linenum\n");
7475 while (annotate
&& i
.linenum
> last_ln
)
7477 var line
= src_stream
.readln ();
7478 stream
.write ("; " + line
+ "\n");
7487 function JSC
$asm_is_load_op (op
)
7489 return (op
.type
== JSC
$OP_LOAD_GLOBAL
7490 || op
.type
== JSC
$OP_LOAD_ARG
7491 || op
.type
== JSC
$OP_LOAD_LOCAL
);
7495 function JSC
$asm_is_store_op (op
)
7497 return (op
.type
== JSC
$OP_STORE_GLOBAL
7498 || op
.type
== JSC
$OP_STORE_ARG
7499 || op
.type
== JSC
$OP_STORE_LOCAL
);
7503 function JSC
$asm_is_local_jump (op
)
7505 return (op
.type
== JSC
$OP_JMP
7506 || op
.type
== JSC
$OP_IFFALSE
7507 || op
.type
== JSC
$OP_IFTRUE
7508 || op
.type
== JSC
$OP_IFFALSE_B
7509 || op
.type
== JSC
$OP_IFTRUE_B
7510 || op
.type
== JSC
$OP_TRY_PUSH
);
7514 function JSC
$asm_is_const_op (op
)
7516 return (JSC
$OP_CONST
<= op
.type
&& op
.type
<= JSC
$OP_CONST_I3
);
7520 function JSC
$asm_lookup_next_op (item
)
7522 while (item
!= null &&
7523 (item
.type
== JSC
$ASM_LABEL
|| item
.type
== JSC
$ASM_SYMBOL
))
7530 function JSC
$asm_optimize (flags
)
7534 /* Simple peephole optimization. */
7535 if ((flags
& JSC
$FLAG_OPTIMIZE_PEEPHOLE
) != 0)
7538 JSC
$message ("jsc: optimize: peephole");
7540 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7543 * Optimization for dup ... pop cases where pop removes the
7544 * item duplicated by dup.
7546 if (item
.next
!= null && item
.next
.type
== JSC
$OP_DUP
)
7552 for (i1
= item
.next
.next
;
7553 i1
!= null && i1
.next
!= null;
7559 * The lookup ends on branches, and on dup, throw,
7560 * and try_pop operands. We optimize on a basic
7561 * block and we match the closest dup-pop pairs.
7563 if (JSC
$asm_is_local_jump (i1
)
7564 || i1
.type
== JSC
$OP_JSR
7565 || i1
.type
== JSC
$OP_NEW
7566 || i1
.type
== JSC
$OP_CALL_METHOD
7567 || i1
.type
== JSC
$OP_RETURN
7568 || i1
.type
== JSC
$ASM_SYMBOL
7569 || i1
.type
== JSC
$ASM_LABEL
7570 || i1
.type
== JSC
$OP_DUP
7571 || i1
.type
== JSC
$OP_TRY_POP
7572 || i1
.type
== JSC
$OP_THROW
)
7577 balance
+= i1
.stack_delta
;
7579 /* Going to negative. Stop here. */
7583 if (i2
.type
== JSC
$OP_POP
&& balance
== 1)
7585 /* Found a matching pop. */
7594 /* The dup can be removed. */
7595 item
.next
= item
.next
.next
;
7599 /* Two instruction optimization (starting from item.next). */
7600 if (item
.next
!= null && item
.next
.next
!= null)
7605 if (i1
.type
== JSC
$OP_APOP
7606 && i2
.type
== JSC
$OP_POP
)
7610 * i2: pop -> pop_n n + 1
7612 var i
= new JSC
$ASM_pop_n (i1
.linenum
, i1
.value
+ 1);
7617 if (item
.next
!= null && item
.next
.next
!= null)
7622 if (i1
.type
== JSC
$OP_CONST_TRUE
7623 && (i2
.type
== JSC
$OP_IFFALSE
7624 || i2
.type
== JSC
$OP_IFFALSE_B
))
7628 * i2: iffalse{,_b} .LX => ---
7630 item
.next
= i2
.next
;
7633 if (item
.next
!= null && item
.next
.next
!= null)
7638 if (i1
.type
== JSC
$OP_CONST_FALSE
7639 && (i2
.type
== JSC
$OP_IFTRUE
7640 || i2
.type
== JSC
$OP_IFTRUE_B
))
7644 * i2: iftrue{,_b} .LX => ---
7646 item
.next
= i2
.next
;
7649 if (item
.next
!= null && item
.next
.next
!= null)
7654 if ((i1
.type
== JSC
$OP_CONST_FALSE
7655 && (i2
.type
== JSC
$OP_IFFALSE
7656 || i2
.type
== JSC
$OP_IFFALSE_B
))
7657 || (i1
.type
== JSC
$OP_CONST_TRUE
7658 && (i2
.type
== JSC
$OP_IFTRUE
7659 || i2
.type
== JSC
$OP_IFTRUE_B
)))
7663 * i2: iffalse{,_b} .LX => jmp .LX
7666 * i2: iftrue{,_b} .LX => jmp .LX
7668 var i
= new JSC
$ASM_jmp (i1
.linenum
, i2
.value
);
7676 /* Jumps to jumps. */
7677 if ((flags
& JSC
$FLAG_OPTIMIZE_JUMPS
) != 0)
7680 JSC
$message ("jsc: optimize: jumps to jumps");
7681 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7682 if (JSC
$asm_is_local_jump (item
))
7686 /* Operand's value is a label */
7687 i2
= JSC
$asm_lookup_next_op (item
.value
);
7689 if (i2
!= null && i2
.type
== JSC
$OP_JMP
)
7690 /* Ok, we can jump there directly. */
7691 item
.value
= i2
.value
;
7695 if ((flags
& JSC
$FLAG_OPTIMIZE_HEAVY
) != 0)
7696 JSC
$optimize_heavy ();
7699 * Optimizations for the size of the generated byte-code. It isn't
7700 * probably worth of doing these optimization for interactive
7701 * scripts since these won't affect the speed of the execution.
7702 * However, these optimizations make the byte-code files smaller so
7703 * these are nice for batch-compiled files.
7705 if ((flags
& JSC
$FLAG_OPTIMIZE_BC_SIZE
) != 0)
7713 /* Remove un-referenced labels. */
7716 JSC
$message ("jsc: optimize: removing un-referenced labels");
7718 /* First, make all labels unreferenced. */
7719 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7720 if (item
.type
== JSC
$ASM_LABEL
)
7721 item
.referenced
= false;
7723 /* Second, mark all referenced labels. */
7724 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7725 if (JSC
$asm_is_local_jump (item
))
7726 item
.value
.referenced
= true;
7728 /* Third, remove all un-referenced labels. */
7729 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7730 while (item
.next
!= null && item
.next
.type
== JSC
$ASM_LABEL
7731 && !item
.next
.referenced
7732 && item
.next
.next
!= null)
7735 item
.next
= item
.next
.next
;
7738 /* Dead code elimination. */
7740 JSC
$message ("jsc: optimize: dead code elimination");
7741 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7742 if (item
.type
== JSC
$OP_RETURN
|| item
.type
== JSC
$OP_JMP
)
7743 while (item
.next
!= null && item
.next
.type
!= JSC
$ASM_SYMBOL
7744 && item
.next
.type
!= JSC
$ASM_LABEL
)
7747 item
.next
= item
.next
.next
;
7751 /* Simple peephole optimization. */
7753 JSC
$message ("jsc: optimize: peephole");
7754 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7756 /* Two instruction optimization (starting from item.next). */
7757 if (item
.next
!= null && item
.next
.next
!= null)
7762 if (i1
.type
== JSC
$OP_JMP
7763 && i2
.type
== JSC
$ASM_LABEL
7780 function JSC
$optimize_heavy ()
7783 JSC
$message ("jsc: optimize: liveness analyzing");
7785 /* First, set the prev pointers and zero usage flags. */
7786 var item
, prev
= null;
7788 for (item
= JSC
$asm_head
; item
!= null; prev
= item
, item
= item
.next
)
7792 item
.live_locals
= 0;
7793 item
.live_used
= false;
7796 /* For each function. */
7798 for (ftail
= JSC
$asm_tail
; ftail
!= null; ftail
= fhead
.prev
)
7802 /* While there is change in the liveness. */
7808 fhead
.type
!= JSC
$ASM_SYMBOL
;
7813 if (fhead
.next
!= null)
7815 floc
= fhead
.next
.live_locals
;
7816 farg
= fhead
.next
.live_args
;
7821 if (fhead
.type
== JSC
$OP_LOAD_LOCAL
&& fhead
.value
< 32)
7822 floc
|= (1 << fhead
.value
);
7824 if (fhead
.type
== JSC
$OP_STORE_LOCAL
&& fhead
.value
< 32)
7825 floc
&= ~(1 << fhead
.value
);
7827 if (fhead
.type
== JSC
$OP_LOAD_ARG
&& fhead
.value
< 32)
7828 farg
|= (1 << fhead
.value
);
7830 if (fhead
.type
== JSC
$OP_STORE_ARG
&& fhead
.value
< 32)
7831 farg
&= ~(1 << fhead
.value
);
7833 if (JSC
$asm_is_local_jump (fhead
))
7835 floc
|= fhead
.value
.live_locals
;
7836 fhead
.value
.live_used
= true;
7839 if (fhead
.live_used
&& (fhead
.live_locals
!= floc
7840 || fhead
.live_args
!= farg
))
7843 fhead
.live_used
= false;
7844 fhead
.live_locals
= floc
;
7845 fhead
.live_args
= farg
;
7851 * When we have the liveness analyzing performed, we can do some
7852 * fancy optimizations.
7856 JSC
$message ("jsc: optimize: peephole");
7858 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7860 /* Three instruction optimization. */
7861 if (item
.next
!= null && item
.next
.next
!= null
7862 && item
.next
.next
.next
!= null)
7868 if (i1
.type
== JSC
$OP_STORE_LOCAL
7869 && i2
.type
== JSC
$OP_LOAD_LOCAL
7870 && i1
.value
== i2
.value
7871 && (i3
.live_locals
& (1 << i1
.value
)) == 0)
7876 * i3: nnn (n not live) => nnn
7886 function JSC
$asm_finalize ()
7891 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7893 item
.offset
= offset
;
7894 offset
+= item
.size
;
7899 function JSC
$ConstantReg ()
7903 function JSC
$asm_genconstant (val
)
7905 if (JSC
$asm_known_constants
== null)
7906 JSC
$asm_known_constants
= new JSC
$ConstantReg ();
7908 /* Lookup <val> from a list of known constants. */
7909 var id
= JSC
$asm_known_constants
[val
];
7910 if (typeof id
== "number")
7913 /* This is a new constant. */
7914 JSC
$asm_constants
.append (val
);
7915 JSC
$asm_known_constants
[val
] = JSC
$asm_constcount
;
7917 return JSC
$asm_constcount
++;
7920 function JSC
$asm_bytecode ()
7923 var symtab
= new String ("");
7924 var nsymtab_entries
= 0;
7925 var code
= new String ("");
7926 var debug
= new String ("");
7927 var debug_last_linenum
= 0;
7930 JSC
$message ("jsc: generating byte-code");
7932 if (JSC
$generate_debug_info
)
7933 /* Source file name. */
7934 debug
.append (String
.pack ("CN", JSC
$DEBUG_FILENAME
, JSC
$filename
.length
)
7937 JSC
$asm_constants
= new String ("");
7939 for (item
= JSC
$asm_head
; item
!= null; item
= item
.next
)
7941 if (item
.type
== JSC
$ASM_SYMBOL
)
7943 symtab
.append (item
.value
+ String
.pack ("CN", 0, item
.offset
));
7946 else if (item
.type
== JSC
$ASM_LABEL
)
7950 /* Real assembler operands. */
7952 if (JSC
$generate_debug_info
)
7953 if (item
.linenum
!= debug_last_linenum
)
7955 debug
.append (String
.pack ("CNN", JSC
$DEBUG_LINENUMBER
,
7956 item
.offset
+ item
.size
,
7958 debug_last_linenum
= item
.linenum
;
7962 /* We handle these. */
7963 code
.append (String
.pack ("C", item
.type
));
7967 * All operands which take an argument, have a method to create
7968 * the byte code entry for their argument.
7970 code
.append (String
.pack ("C", item
.type
) + item
.bytecode ());
7975 symtab
= String
.pack ("N", nsymtab_entries
) + symtab
;
7979 var msg
= ("jsc: code=" + code
.length
.toString ()
7980 + ", constants=" + JSC
$asm_constants
.length
.toString ()
7981 + ", symtab=" + symtab
.length
.toString ());
7983 if (JSC
$generate_debug_info
)
7984 msg
+= ", debug=" + debug
.length
.toString ();
7986 msg
+= (", headers="
7987 + (32 + (JSC
$generate_debug_info
? 8 : 0)).toString ()
7989 + (code
.length
+ JSC
$asm_constants
.length
+ symtab
.length
7991 + (JSC
$generate_debug_info
? 8 : 0)).toString ());
7995 return (String
.pack ("NN", JSC
$BC_MAGIC
,
7996 3 + (JSC
$generate_debug_info
? 1 : 0))
7997 + String
.pack ("NN", JSC
$BC_SECT_CODE
, code
.length
) + code
7999 + String
.pack ("NN", JSC
$BC_SECT_CONSTANTS
,
8000 JSC
$asm_constants
.length
)
8003 + String
.pack ("NN", JSC
$BC_SECT_SYMTAB
, symtab
.length
) + symtab
8005 + (JSC
$generate_debug_info
8006 ? String
.pack ("NN", JSC
$BC_SECT_DEBUG
, debug
.length
) + debug
8017 * Public entry points to the JavaScript compiler.
8018 * Copyright (c) 1998 New Generation Software (NGS) Oy
8020 * Author: Markku Rossi <mtr@ngs.fi>
8024 * This library is free software; you can redistribute it and/or
8025 * modify it under the terms of the GNU Library General Public
8026 * License as published by the Free Software Foundation; either
8027 * version 2 of the License, or (at your option) any later version.
8029 * This library is distributed in the hope that it will be useful,
8030 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8031 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8032 * Library General Public License for more details.
8034 * You should have received a copy of the GNU Library General Public
8035 * License along with this library; if not, write to the Free
8036 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
8037 * MA 02111-1307, USA
8041 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/jsc/compiler.js,v $
8049 JSC
$FLAG_VERBOSE
= 0x00000001;
8050 JSC
$FLAG_ANNOTATE_ASSEMBLER
= 0x00000002;
8051 JSC
$FLAG_GENERATE_DEBUG_INFO
= 0x00000004;
8052 JSC
$FLAG_GENERATE_EXECUTABLE_BC_FILES
= 0x00000008;
8054 JSC
$FLAG_OPTIMIZE_PEEPHOLE
= 0x00000020;
8055 JSC
$FLAG_OPTIMIZE_JUMPS
= 0x00000040;
8056 JSC
$FLAG_OPTIMIZE_BC_SIZE
= 0x00000080;
8057 JSC
$FLAG_OPTIMIZE_HEAVY
= 0x00000100;
8059 JSC
$FLAG_OPTIMIZE_MASK
= 0x0000fff0;
8061 JSC
$FLAG_WARN_UNUSED_ARGUMENT
= 0x00010000;
8062 JSC
$FLAG_WARN_UNUSED_VARIABLE
= 0x00020000;
8063 JSC
$FLAG_WARN_SHADOW
= 0x00040000;
8064 JSC
$FLAG_WARN_WITH_CLOBBER
= 0x00080000;
8065 JSC
$FLAG_WARN_MISSING_SEMICOLON
= 0x00100000;
8066 JSC
$FLAG_WARN_STRICT_ECMA
= 0x00200000;
8067 JSC
$FLAG_WARN_DEPRECATED
= 0x00400000;
8069 JSC
$FLAG_WARN_MASK
= 0xffff0000;
8072 * Global interfaces to the compiler.
8075 function JSC
$compile_file (fname
, flags
, asm_file
, bc_file
)
8077 var stream
= new JSC
$StreamFile (fname
);
8078 return JSC
$compile_stream (stream
, flags
, asm_file
, bc_file
);
8082 function JSC
$compile_string (str
, flags
, asm_file
, bc_file
)
8084 var stream
= new JSC
$StreamString (str
);
8085 return JSC
$compile_stream (stream
, flags
, asm_file
, bc_file
);
8089 function JSC
$compiler_reset ()
8091 /* Reset compiler to a known initial state. */
8092 JSC
$parser_reset ();
8098 function JSC
$compile_stream (stream
, flags
, asm_file
, bc_file
)
8102 JSC
$compiler_reset ();
8108 JSC
$verbose
= ((flags
& JSC
$FLAG_VERBOSE
) != 0);
8109 JSC
$generate_debug_info
8110 = ((flags
& JSC
$FLAG_GENERATE_DEBUG_INFO
) != 0);
8112 JSC
$warn_unused_argument
8113 = ((flags
& JSC
$FLAG_WARN_UNUSED_ARGUMENT
) != 0);
8114 JSC
$warn_unused_variable
8115 = ((flags
& JSC
$FLAG_WARN_UNUSED_VARIABLE
) != 0);
8117 = ((flags
& JSC
$FLAG_WARN_SHADOW
) != 0);
8118 JSC
$warn_with_clobber
8119 = ((flags
& JSC
$FLAG_WARN_WITH_CLOBBER
) != 0);
8120 JSC
$warn_missing_semicolon
8121 = ((flags
& JSC
$FLAG_WARN_MISSING_SEMICOLON
) != 0);
8122 JSC
$warn_strict_ecma
8123 = ((flags
& JSC
$FLAG_WARN_STRICT_ECMA
) != 0);
8125 = ((flags
& JSC
$FLAG_WARN_DEPRECATED
) != 0);
8127 /* Compilation and assembler generation time optimizations. */
8128 JSC
$optimize_constant_folding
= true;
8129 JSC
$optimize_type
= true;
8131 JSC
$parser_parse (stream
);
8134 JSC
$asm_generate ();
8137 * We don't need the syntax tree anymore. Free it and save
8140 JSC
$parser_reset ();
8142 /* Optimize if requested. */
8143 if ((flags
& JSC
$FLAG_OPTIMIZE_MASK
) != 0)
8144 JSC
$asm_optimize (flags
);
8146 if (typeof asm_file
== "string")
8148 var asm_stream
= new File (asm_file
);
8149 var src_stream
= false;
8151 if (asm_stream
.open ("w"))
8153 if ((flags
& JSC
$FLAG_ANNOTATE_ASSEMBLER
) != 0)
8154 if (stream
.rewind ())
8155 src_stream
= stream
;
8157 JSC
$asm_print (src_stream
, asm_stream
);
8158 asm_stream
.close ();
8161 JSC
$message ("jsc: couldn't create asm output file \""
8163 + System
.strerror (System
.errno
));
8166 JSC
$asm_finalize ();
8168 result
= JSC
$asm_bytecode ();
8170 /* Remove all intermediate results from the memory. */
8171 JSC
$compiler_reset ();
8173 if (typeof bc_file
== "string")
8175 var ostream
= new File (bc_file
);
8176 if (ostream
.open ("w"))
8178 ostream
.write (result
);
8181 if ((flags
& JSC
$FLAG_GENERATE_EXECUTABLE_BC_FILES
) != 0)
8183 /* Add execute permissions to the output file. */
8184 var st
= File
.stat (bc_file
);
8187 if (!File
.chmod (bc_file
, st
[2] | 0111))
8188 JSC
$message ("jsc: couldn't add execute "
8189 + "permissions to bc file \""
8191 + System
.strerror (System
.errno
));
8194 JSC
$message ("jsc: couldn't stat bc file \"" + bc_file
8196 + System
.strerror (System
.errno
));
8200 JSC
$message ("jsc: couldn't create bc file \"" + bc_file
8201 + "\": " + System
.strerror (System
.errno
));
8210 error ("jsc: couldn't open input stream \"" + stream
.name
+ "\": "