📄 gram.js
字号:
/* Labeled statement. */
function JSC$stmt_labeled_stmt (ln, id, stmt)
{
this.stype = JSC$STMT_LABELED_STMT;
this.linenum = ln;
this.id = id;
this.stmt = stmt;
this.asm = JSC$stmt_labeled_stmt_asm;
this.count_locals = JSC$stmt_labeled_stmt_count_locals;
}
function JSC$stmt_labeled_stmt_asm ()
{
var l_continue = new JSC$ASM_label ();
var l_break = new JSC$ASM_label ();
/*
* It is an error if we already have a labeled statement with the
* same id.
*/
if (!JSC$cont_break.is_unique_label (this.id))
error (JSC$filename + ":" + this.linenum.toString ()
+ ": labeled statement is enclosed by another labeled statement "
+ "with the same label");
/* Push the break and continue labels. */
JSC$cont_break.push (l_break, l_continue, false, this.id);
/* Dump the assembler. */
l_continue.link ();
this.stmt.asm ();
l_break.link ();
/* And we'r done with out label scope. */
JSC$cont_break.pop ();
}
function JSC$stmt_labeled_stmt_count_locals (recursive)
{
return this.stmt.count_locals (recursive);
}
/* Expression. */
function JSC$stmt_expr (expr)
{
this.stype = JSC$STMT_EXPR;
this.linenum = expr.linenum;
this.expr = expr;
this.asm = JSC$stmt_expr_asm;
this.count_locals = JSC$zero_function;
}
function JSC$stmt_expr_asm ()
{
this.expr.asm ();
new JSC$ASM_pop (this.linenum).link ();
}
/* If. */
function JSC$stmt_if (ln, expr, stmt1, stmt2)
{
this.stype = JSC$STMT_IF;
this.linenum = ln;
this.expr = expr;
this.stmt1 = stmt1;
this.stmt2 = stmt2;
this.asm = JSC$stmt_if_asm;
this.count_locals = JSC$stmt_if_count_locals;
}
function JSC$stmt_if_asm ()
{
this.expr.asm ();
var l1 = new JSC$ASM_label ();
var l2 = new JSC$ASM_label ();
if (JSC$optimize_type && this.expr.lang_type
&& this.expr.lang_type == JSC$JS_BOOLEAN)
new JSC$ASM_iffalse_b (this.linenum, l1).link ();
else
new JSC$ASM_iffalse (this.linenum, l1).link ();
/* Code for the then branch. */
this.stmt1.asm ();
new JSC$ASM_jmp (this.linenum, l2).link ();
/* Code for the else branch. */
l1.link ();
if (this.stmt2 != null)
this.stmt2.asm ();
/* Done label. */
l2.link ();
}
function JSC$stmt_if_count_locals (recursive)
{
var lcount;
if (!recursive)
{
lcount = 0;
if (this.stmt1.stype == JSC$STMT_VARIABLE)
lcount += this.stmt1.list.length;
if (this.stmt2 != null && this.stmt2.stype == JSC$STMT_VARIABLE)
lcount += this.stmt2.list.length;
}
else
{
lcount = this.stmt1.count_locals (true);
if (this.stmt2)
{
var c = this.stmt2.count_locals (true);
if (c > lcount)
lcount = c;
}
}
return lcount;
}
/* Do...While. */
function JSC$stmt_do_while (ln, expr, stmt)
{
this.stype = JSC$STMT_DO_WHILE;
this.linenum = ln;
this.expr = expr;
this.stmt = stmt;
this.asm = JSC$stmt_do_while_asm;
this.count_locals = JSC$stmt_do_while_count_locals;
}
function JSC$stmt_do_while_asm ()
{
var l1 = new JSC$ASM_label ();
var l2 = new JSC$ASM_label ();
var l3 = new JSC$ASM_label ();
/* Loop label. */
l1.link ();
/* Body. */
JSC$cont_break.push (l3, l2, false, null);
this.stmt.asm ();
JSC$cont_break.pop ();
/* Condition & continue. */
l2.link ();
this.expr.asm ();
if (JSC$optimize_type && this.expr.lang_type
&& this.expr.lang_type == JSC$JS_BOOLEAN)
new JSC$ASM_iftrue_b (this.linenum, l1).link ();
else
new JSC$ASM_iftrue (this.linenum, l1).link ();
/* Break label. */
l3.link ();
}
function JSC$stmt_do_while_count_locals (recursive)
{
if (!recursive)
{
if (this.stmt.stype == JSC$STMT_VARIABLE)
return this.stmt.list.length;
return 0;
}
else
return this.stmt.count_locals (true);
}
/* While. */
function JSC$stmt_while (ln, expr, stmt)
{
this.stype = JSC$STMT_WHILE;
this.linenum = ln;
this.expr = expr;
this.stmt = stmt;
this.asm = JSC$stmt_while_asm;
this.count_locals = JSC$stmt_while_count_locals;
}
function JSC$stmt_while_asm ()
{
var l1 = new JSC$ASM_label ();
var l2 = new JSC$ASM_label ();
/* Loop label. */
l1.link ();
/* Condition. */
this.expr.asm ();
if (JSC$optimize_type && this.expr.lang_type
&& this.expr.lang_type == JSC$JS_BOOLEAN)
new JSC$ASM_iffalse_b (this.linenum, l2).link ();
else
new JSC$ASM_iffalse (this.linenum, l2).link ();
/* Body. */
JSC$cont_break.push (l2, l1, false, null);
this.stmt.asm ();
JSC$cont_break.pop ();
/* Goto loop. */
new JSC$ASM_jmp (this.linenum, l1).link ();
/* Break label. */
l2.link ();
}
function JSC$stmt_while_count_locals (recursive)
{
if (!recursive)
{
if (this.stmt.stype == JSC$STMT_VARIABLE)
return this.stmt.list.length;
return 0;
}
else
return this.stmt.count_locals (true);
}
/* For. */
function JSC$stmt_for (ln, vars, e1, e2, e3, stmt)
{
this.stype = JSC$STMT_FOR;
this.linenum = ln;
this.vars = vars;
this.expr1 = e1;
this.expr2 = e2;
this.expr3 = e3;
this.stmt = stmt;
this.asm = JSC$stmt_for_asm;
this.count_locals = JSC$stmt_for_count_locals;
}
function JSC$stmt_for_asm ()
{
/* Code for the init. */
if (this.vars)
{
/* We have our own variable scope. */
JSC$ns.push_frame ();
var i;
for (i = 0; i < this.vars.length; i++)
{
var decl = this.vars[i];
JSC$ns.define_symbol (decl.id, JSC$SCOPE_LOCAL,
JSC$ns.alloc_local (), this.linenum);
/* Possible init. */
if (decl.expr)
{
decl.expr.asm ();
var r = JSC$ns.lookup_symbol (decl.id);
if (r == null || r.scope != JSC$SCOPE_LOCAL)
error (JSC$filename + ":" + this.liennum.toString ()
+ ": internal compiler error in local variable "
+ "declaration in for statement");
new JSC$ASM_store_local (this.linenum, r.value).link ();
}
}
}
else if (this.expr1 != null)
{
this.expr1.asm ();
new JSC$ASM_pop (this.linenum).link ();
}
var l1 = new JSC$ASM_label ();
var l2 = new JSC$ASM_label ();
var l3 = new JSC$ASM_label ();
/* Loop label. */
l1.link ();
/* Condition. */
var type_op = false;
if (this.expr2 != null)
{
this.expr2.asm ();
if (JSC$optimize_type && this.expr2.lang_type
&& this.expr2.lang_type == JSC$JS_BOOLEAN)
type_op = true;
}
else
{
new JSC$ASM_const_true (this.linenum).link ();
type_op = JSC$optimize_type;
}
if (type_op)
new JSC$ASM_iffalse_b (this.linenum, l3).link ();
else
new JSC$ASM_iffalse (this.linenum, l3).link ();
JSC$cont_break.push (l3, l2, false, null);
/* Body. */
this.stmt.asm ();
JSC$cont_break.pop ();
/* Continue label. */
l2.link ();
/* Increment. */
if (this.expr3 != null)
{
this.expr3.asm ();
new JSC$ASM_pop (this.linenum).link ();
}
/* Goto loop. */
new JSC$ASM_jmp (this.linenum, l1).link ();
/* Break label. */
l3.link ();
if (this.vars)
/* Pop the local variable scope. */
JSC$ns.pop_frame ();
}
function JSC$stmt_for_count_locals (recursive)
{
var count = 0;
if (recursive)
{
if (this.vars)
count += this.vars.length;
count += this.stmt.count_locals (true);
}
else
{
if (this.stmt.stype == JSC$STMT_VARIABLE)
count += this.stmt.list.length;
}
return count;
}
/* For...in. */
function JSC$stmt_for_in (ln, vars, e1, e2, stmt)
{
this.stype = JSC$STMT_FOR_IN;
this.linenum = ln;
this.vars = vars;
this.expr1 = e1;
this.expr2 = e2;
this.stmt = stmt;
this.asm = JSC$stmt_for_in_asm;
this.count_locals = JSC$stmt_for_in_count_locals;
}
function JSC$stmt_for_in_asm ()
{
var local_id;
if (this.vars)
{
/* We need our own variable scope here. */
JSC$ns.push_frame ();
var decl = this.vars[0];
local_id = JSC$ns.alloc_local ();
JSC$ns.define_symbol (decl.id, JSC$SCOPE_LOCAL, local_id, this.linenum);
/* Possible init. */
if (decl.expr)
{
decl.expr.asm ();
new JSC$ASM_store_local (this.linenum, local_id).link ();
}
}
/* Init the world. */
this.expr2.asm ();
new JSC$ASM_dup (this.linenum).link ();
new JSC$ASM_const_i0 (this.linenum).link ();
new JSC$ASM_swap (this.linenum).link ();
new JSC$ASM_const_i0 (this.linenum).link ();
var l_loop = new JSC$ASM_label ();
var l_cont = new JSC$ASM_label ();
var l_iffalse_b = new JSC$ASM_label ();
var l_break = new JSC$ASM_label ();
/* Loop label. */
l_loop.link ();
/* Fetch nth. */
new JSC$ASM_nth (this.linenum).link ();
new JSC$ASM_iffalse_b (this.linenum, l_iffalse_b).link ();
/* Store value to variable. */
if (this.vars)
new JSC$ASM_store_local (this.linenum, local_id).link ();
else
JSC$asm_expr_lvalue_store_asm (this.expr1);
/* Body. */
JSC$cont_break.push (l_break, l_cont, false, null);
this.stmt.asm ();
JSC$cont_break.pop ();
/* Continue label. */
l_cont.link ();
/* Increment. */
new JSC$ASM_const_i1 (this.linenum).link ();
new JSC$ASM_add (this.linenum).link ();
new JSC$ASM_dup (this.linenum).link ();
new JSC$ASM_roll (this.linenum, -3).link ();
new JSC$ASM_dup (this.linenum).link ();
new JSC$ASM_roll (this.linenum, 4).link ();
new JSC$ASM_swap (this.linenum).link ();
/* Goto loop. */
new JSC$ASM_jmp (this.linenum, l_loop).link ();
/* Out label. */
l_iffalse_b.link ();
new JSC$ASM_pop (this.linenum).link ();
/* Break label. */
l_break.link ();
new JSC$ASM_pop_n (this.linenum, 2).link ();
if (this.vars)
/* Pop the variable scope. */
JSC$ns.pop_frame ();
}
function JSC$stmt_for_in_count_locals (recursive)
{
var count = 0;
if (recursive)
{
if (this.vars)
count++;
count += this.stmt.count_locals (true);
}
else
{
if (this.stmt.stype == JSC$STMT_VARIABLE)
count += this.stmt.list.length;
}
return count;
}
/* Variable. */
function JSC$stmt_variable (ln, list)
{
this.stype = JSC$STMT_VARIABLE;
this.linenum = ln;
this.global_level = false;
this.list = list;
this.asm = JSC$stmt_variable_asm;
this.count_locals = JSC$stmt_variable_count_locals;
}
function JSC$stmt_variable_asm ()
{
var j, r;
/* Define all local variables to our namespace. */
for (j = 0; j < this.list.length; j++)
{
var i = this.list[j];
if (!this.global_level)
JSC$ns.define_symbol (i.id, JSC$SCOPE_LOCAL,
JSC$ns.alloc_local (), this.linenum);
if (i.expr)
{
i.expr.asm ();
if (this.global_level)
new JSC$ASM_store_global (this.linenum, i.id).link ();
else
{
r = JSC$ns.lookup_symbol (i.id);
if (r == null || r.scope != JSC$SCOPE_LOCAL)
error (JSC$filename + ":" + this.linenum.toString()
+ ": internal compiler error in local variable declaration");
new JSC$ASM_store_local (this.linenum, r.value).link ();
}
}
}
}
function JSC$stmt_variable_count_locals (recursive)
{
if (!recursive)
{
if (this.global_level)
/* We define these as global variables. */
return 0;
return this.list.length;
}
return 0;
}
function JSC$var_declaration (id, expr)
{
this.id = id;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -