⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gram.js

📁 一个类似windows
💻 JS
📖 第 1 页 / 共 5 页
字号:
  var nesting = JSC$cont_break.count_with_nesting (this.label);
  if (nesting > 0)
    new JSC$ASM_with_pop (this.linenum, nesting).link ();

  nesting = JSC$cont_break.count_try_nesting (this.label);
  if (nesting > 0)
    new JSC$ASM_try_pop (this.linenum, nesting).link ();

  /*
   * For non-labeled breaks, the switch nesting is handled in the
   * stmt_switch().  The code after the label, returned by the
   * get_break(), will handle the switch nesting in these cases.
   * For the labeled breaks, we must pop the switch nesting here.
   */
  if (this.label)
    {
      nesting = JSC$cont_break.count_switch_nesting (this.label);
      if (nesting > 0)
	{
	  if (nesting == 1)
	    new JSC$ASM_pop (this.linenum).link ();
	  else
	    new JSC$ASM_pop_n (this.linenum, nesting).link ();
	}
    }

  new JSC$ASM_jmp (this.linenum, l_break).link ();
}


/* Return. */

function JSC$stmt_return (ln, expr)
{
  this.stype = JSC$STMT_RETURN;
  this.linenum = ln;
  this.expr = expr;
  this.asm = JSC$stmt_return_asm;
  this.count_locals = JSC$zero_function;
}

function JSC$stmt_return_asm ()
{
  var nesting = JSC$cont_break.try_return_nesting ();
  if (nesting > 0)
    new JSC$ASM_try_pop (this.linenum, nesting).link ();

  if (this.expr != null)
    this.expr.asm ();
  else
    new JSC$ASM_const_undefined (this.linenum).link ();

  new JSC$ASM_return (this.linenum).link ();
}


/* Switch. */

function JSC$stmt_switch (ln, last_ln, expr, clauses)
{
  this.stype = JSC$STMT_SWITCH;
  this.linenum = ln;
  this.last_linenum = last_ln;
  this.expr = expr;
  this.clauses = clauses;
  this.asm = JSC$stmt_switch_asm;
  this.count_locals = JSC$stmt_switch_count_locals;
}

function JSC$stmt_switch_asm ()
{
  /* Evaluate the switch expression to the top of the stack. */
  this.expr.asm ();

  /* The switch statement define a break label. */
  var l_break = new JSC$ASM_label ();
  JSC$cont_break.push (l_break, null, true, null);

  /* For each clause (except the first), insert check and body labels. */
  var i;
  for (i = 1; i < this.clauses.length; i++)
    {
      this.clauses[i].l_check = new JSC$ASM_label ();
      this.clauses[i].l_body = new JSC$ASM_label ();
    }

  /* Generate code for each clause. */
  for (i = 0; i < this.clauses.length; i++)
    {
      /* Is this the last clause? */
      var last = i + 1 >= this.clauses.length;
      var c = this.clauses[i];

      var next_check, next_body;
      if (last)
	next_check = next_body = l_break;
      else
	{
	  next_check = this.clauses[i + 1].l_check;
	  next_body = this.clauses[i + 1].l_body;
	}

      if (c.expr)
	{
	  /*
	   * Must check if this clause matches the expression.  If c.expr
	   * is null, this is the default clause that matches always.
	   */

	  if (i > 0)
	    c.l_check.link ();

	  new JSC$ASM_dup (c.linenum).link ();
	  c.expr.asm ();
	  new JSC$ASM_cmp_eq (c.linenum).link ();
	  new JSC$ASM_iffalse_b (c.linenum, next_check).link ();
	}
      else
	{
	  if (i > 0)
	    /* The check label for the default case. */
	    c.l_check.link ();
	}

      /* Generate assembler for the body. */
      if (i > 0)
	c.l_body.link ();

      var j;
      for (j = 0; j < c.length; j++)
	c[j].asm ();

      /* And finally, jump to the next body. (this is the fallthrough case). */
      new JSC$ASM_jmp (c.last_linenum, next_body).link ();
    }

  JSC$cont_break.pop ();

  /* The break label. */
  l_break.link ();

  /* Pop the value of the switch expression. */
  new JSC$ASM_pop (this.last_linenum).link ();
}

function JSC$stmt_switch_count_locals (recursive)
{
  var locals = 0;
  var i, j;

  if (recursive)
    {
      /* For the recursive cases, we need the maximum of our clause stmts. */
      for (i = 0; i < this.clauses.length; i++)
	{
	  var c = this.clauses[i];
	  for (j = 0; j < c.length; j++)
	    {
	      var l = c[j].count_locals (true);
	      if (l > locals)
		locals = l;
	    }
	}
    }
  else
    {
      /*
       * The case clauses are not blocks.  Therefore, we need the amount,
       * needed by the clauses at the top-level.
       */

      for (i = 0; i < this.clauses.length; i++)
	{
	  var c = this.clauses[i];
	  for (j = 0; j < c.length; j++)
	    locals += c[j].count_locals (false);
	}
    }

  return locals;
}


/* With. */

function JSC$stmt_with (ln, expr, stmt)
{
  this.stype = JSC$STMT_WITH;
  this.linenum = ln;
  this.expr = expr;
  this.stmt = stmt;
  this.asm = JSC$stmt_with_asm;
  this.count_locals = JSC$stmt_with_count_locals;
}

function JSC$stmt_with_asm ()
{
  this.expr.asm ();

  new JSC$ASM_with_push (this.linenum).link ();
  JSC$cont_break.top.with_nesting++;

  this.stmt.asm ();

  JSC$cont_break.top.with_nesting--;
  new JSC$ASM_with_pop (this.linenum, 1).link ();
}

function JSC$stmt_with_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);
}


/* Try. */

function JSC$stmt_try (ln, try_block_last_ln, try_last_ln, block, catch_list,
		       fin)
{
  this.stype = JSC$STMT_TRY;
  this.linenum = ln;
  this.try_block_last_linenum = try_block_last_ln;
  this.try_last_linenum = try_last_ln;
  this.block = block;
  this.catch_list = catch_list;
  this.fin = fin;
  this.asm = JSC$stmt_try_asm;
  this.count_locals = JSC$stmt_try_count_locals;
}

function JSC$stmt_try_asm ()
{
  var l_finally = new JSC$ASM_label ();

  /* Protect and execute the try-block. */

  var l_try_error = new JSC$ASM_label ();
  new JSC$ASM_try_push (this.linenum, l_try_error).link ();
  JSC$cont_break.top.try_nesting++;

  this.block.asm ();

  JSC$cont_break.top.try_nesting--;
  new JSC$ASM_try_pop (this.try_block_last_linenum, 1).link ();

  /*
   * All ok so far.  Push a `false' to indicate no error and jump to
   * the finally block (or out if we have no finally block).
   */
  new JSC$ASM_const_false (this.try_block_last_linenum).link ();
  new JSC$ASM_jmp (this.try_block_last_linenum, l_finally).link ();

  /*
   * Handle try block failures.  The thrown value is on the top of the
   * stack.
   */

  l_try_error.link ();

  if (this.catch_list)
    {
      /*
       * We keep one boolean variable below the thrown value.  Its default
       * value is false.  When one of our catch blocks are entered, it is
       * set to true to indicate that we shouldn't throw the error
       * anymore.
       */
      new JSC$ASM_const_false (this.catch_list.linenum).link ();
      new JSC$ASM_swap (this.catch_list.linenum).link ();

      /* Protect and execute the catch list. */

      var l_catch_list_error = new JSC$ASM_label ();
      new JSC$ASM_try_push (this.catch_list.linenum,
			    l_catch_list_error).link ();
      JSC$cont_break.top.try_nesting++;

      /* Insert start and body labels for each catch list item. */
      var i;
      for (i = 0; i < this.catch_list.length; i++)
	{
	  this.catch_list[i].l_start = new JSC$ASM_label ();
	  this.catch_list[i].l_body = new JSC$ASM_label ();
	}

      /* A label for the catch list end. */
      var l_catch_list_end = new JSC$ASM_label ();

      /* Process the individual catches. */
      for (i = 0; i < this.catch_list.length; i++)
	{
	  var c = this.catch_list[i];

	  /* This is the starting point of this catch frame. */
	  c.l_start.link ();

	  /*
	   * Create a new namespace frame and bind the catch's
	   * identifier to the thrown exception.
	   */

	  JSC$ns.push_frame ();
	  JSC$ns.define_symbol (c.id, JSC$SCOPE_LOCAL, JSC$ns.alloc_local (),
				c.linenum);

	  new JSC$ASM_dup (c.linenum).link ();
	  new JSC$ASM_store_local (c.linenum,
				   JSC$ns.lookup_symbol (c.id).value).link ();

	  /* Check the possible guard.  We must protect its calculation. */
	  if (c.guard)
	    {
	      var l_guard_error = new JSC$ASM_label ();
	      new JSC$ASM_try_push (c.linenum, l_guard_error).link ();
	      JSC$cont_break.top.try_nesting++;

	      /* Calculate the guard. */
	      c.guard.asm ();

	      JSC$cont_break.top.try_nesting--;
	      new JSC$ASM_try_pop (c.linenum, 1).link ();

	      /*
	       * Wow!  We managed to do it.  Now, let's check if we
	       * accept this catch case.
	       */

	      var next;
	      if (i + 1 >= this.catch_list.length)
		next = l_catch_list_end;
	      else
		next = this.catch_list[i + 1].l_start;

	      if (c.guard.lang_type == JSC$JS_BOOLEAN)
		new JSC$ASM_iffalse_b (c.linenum, next).link ();
	      else
		new JSC$ASM_iffalse (c.linenum, next).link ();

	      /* Yes, we do accept it.  Just jump to do the stuffs. */
	      new JSC$ASM_jmp (c.linenum, c.l_body).link ();

	      /*
	       * The evaluation of the guard failed.  Do the cleanup
	       * and jump to the next case.
	       */

	      l_guard_error.link ();

	      /* Pop the exception. */
	      new JSC$ASM_pop (c.linenum).link ();

	      /* Check the next case. */
	      new JSC$ASM_jmp (c.linenum, next).link ();
	    }

	  /*
	   * We did enter the catch body.  Let's update our boolean
	   * status variable to reflect this fact.
	   */
	  c.l_body.link ();

	  new JSC$ASM_swap (c.linenum).link ();
	  new JSC$ASM_pop (c.linenum).link ();
	  new JSC$ASM_const_true (c.linenum).link ();
	  new JSC$ASM_swap (c.linenum).link ();

	  /* Code for the catch body. */
	  c.stmt.asm ();

	  /* We'r done with the namespace frame. */
	  JSC$ns.pop_frame ();

	  /*
	   * The next catch tag, or the l_catch_list_end follows us,
	   * so we don't need a jumps here.
	   */
	}

      /*
       * The catch list was evaluated without errors.
       */

      l_catch_list_end.link ();
      JSC$cont_break.top.try_nesting--;
      new JSC$ASM_try_pop (this.catch_list.last_linenum, 1).link ();

      /* Did we enter any of our catch lists? */

      var l_we_did_enter = new JSC$ASM_label ();
      new JSC$ASM_swap (this.catch_list.last_linenum).link ();
      new JSC$ASM_iftrue_b (this.catch_list.last_linenum,
			    l_we_did_enter).link ();

      /* No we didn't. */

      /*
       * Push `true' to indicate an exception and jump to the finally
       * block.  The exception is now on the top of the stack.
       */
      new JSC$ASM_const_true (this.catch_list.last_linenum).link ();
      new JSC$ASM_jmp (this.catch_list.last_linenum, l_finally).link ();

      /* Yes, we did enter one (or many) of our catch lists. */

      l_we_did_enter.link ();

      /* Pop the try-block's exception */
      new JSC$ASM_pop (this.catch_list.last_linenum).link ();

      /*
       * Push a `false' to indicate "no errors" and jump to the
       * finally block.
       */
      new JSC$ASM_const_false (this.catch_list.last_linenum).link ();
      new JSC$ASM_jmp (this.catch_list.last_linenum, l_finally).link ();


      /*
       * Handle catch list failures.  The thrown value is on the top of the
       * stack.
       */

      l_catch_list_error.link ();

      /*
       * Pop the try-block's exception and our boolean `did we enter a
       * catch block' variable.  They are below our new exception.
       */
      new JSC$ASM_apop (this.catch_list.last_linenum, 2).link ();

      /*
       * Push `true' to indicate an exception.  We will fallthrough to
       * the finally part, so no jump is needed here.
       */
      new JSC$ASM_const_true (this.catch_list.last_linenum).link ();
    }
  else
    {
      /* No catch list. */
      new JSC$ASM_const_true (this.try_block_last_linenum).link ();
    }

  /* The possible finally block. */

  l_finally.link ();

  if (this.fin)
    /* Execute it without protection. */
    this.fin.asm ();

  /* We'r almost there.  Let's see if we have to raise a new exception. */

  var l_out = new JSC$ASM_label ();
  new JSC$ASM_iffalse_b (this.try_last_linenum, l_out).link ();

  /* Do raise it. */
  new JSC$ASM_throw (this.try_last_linenum).link ();

  /* The possible exception is handled.  Please, continue. */
  l_out.link ();
}

function JSC$stmt_try_count_locals (recursive)
{
  var count = 0;
  var c;

  if (recursive)
    {
      c = this.block.count_locals (true);
      if (c > count)
	count = c;

      if (this.catch_list)
	{
	  var i;
	  for (i = 0; i < this.catch_list.length; i++)
	    {
	      c = this.catch_list[i].stmt.count_locals (true);
	      if (c > count)
		count = c;
	    }
	}
      if (this.fin)
	{
	  c = this.fin.count_locals (true);
	  if (c > count)
	    count = c;
	}
    }
  else
    {
      if (this.block.stype == JSC$STMT_VARIABLE)
	count += this.block.list.length;

      if (this.catch_list)
	{
	  /* One for the call variable. */
	  count++;

	  var i;
	  for (i = 0; i < this.catch_list.length; i++)
	    if (this.catch_list[i].stmt.stype == JSC$STMT_VARIABLE)
	      count += this.catch_list[i].stmt.list.length;
	}

      if (this.fin)
	if (this.fin.stype == JSC$STMT_VARIABLE)
	  count += this.fin.list.length;
    }

  return count;
}


/* Throw. */

function JSC$stmt_throw (ln, expr)
{
  this.stype = JSC$STMT_THROW;
  this.linenum = ln;
  this.expr = expr;
  this.asm = JSC$stmt_throw_asm;
  this.count_locals = JSC$zero_function;
}

function JSC$stmt_throw_asm ()
{
  this.expr.asm ();
  new JSC$ASM_throw (this.linenum).link ();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -