} // EmitFunction // Generate code for the given StmtFrag. Don't bother enclosing the code // in braces (the caller is assumed to have done that). private void EmitStatements(StmtFrag statements) { for ( StatementLine code = ((CSharpStmtFrag)statements).code; code != null; code = code.next ) if (code.text == "$$indent$$") pp.Indent(); else if (code.text == "$$outdent$$") pp.Outdent(); else pp.Line(code.text); } // EmitStatements
} // ExpressionStmt // Return an if/then or if/then/else statement. If there was no else // clause, elseClause will be null. public StmtFrag IfThenElse( SrcLoc loc, ExprFrag condition, StmtFrag ifClause, StmtFrag elseClause ) { CSharpStmtFrag frag = new CSharpStmtFrag(loc); CSharpExprFrag csCondition = (CSharpExprFrag)condition; frag.Append("if (Support.BoolTest(" + csCondition.GenerateRHS() + "))"); frag.AppendIndentedBody(ifClause); if (elseClause != null) { frag.Append("else"); frag.AppendIndentedBody(elseClause); } return frag; } // IfThenElse
} // EmitProgramSuffix // Generate code for the main function, given the function's body. public void EmitMainFunction(StmtFrag body) { pp.Line(); pp.Line("// Main program code"); pp.Line("public static void GlobalCode()"); pp.Indent(); pp.Line("{"); EmitStatements(body); pp.Line("} // GlobalCode"); pp.Outdent(); } // EmitMainFunction
} // EmitMainFunction // Generate code for the given function (other than the main function), // given the function's FunctionInfo object and its body. public void EmitFunction(FunctionInfo info, StmtFrag body) { // HACK snewman 8/15/01: review the way locals are handled here, to // make sure we're declaring them in precise accordance with the spec. // HACK snewman 8/15/01: add support for nested functions if (info.firstChild != null) throw new ParseError( "EmitFunction: nested functions not yet implemented", body.loc ); string functionLabel, functionName; if (info.nameInParent == null) { functionLabel = "Anonymous function"; functionName = "anon_"; } else { functionLabel = "Function \"" + info.nameInParent + "\""; functionName = info.nameInParent + "_"; } functionName = MakeUniqueMethodName(functionName); pp.Line(); pp.Line("// {0}", functionLabel); pp.Line("public static object {0}(object this_, params object[] args)", functionName); pp.Indent(); pp.Line("{"); pp.Text("JActivationObject activation = new JActivationObject(args"); foreach (string paramName in info.paramNames) pp.Text(", \"{0}\"", paramName); pp.EndLine(");"); foreach (string varName in info.locals) pp.Line("activation.Put(\"{0}\", JUndefinedObject.instance);", varName); EmitStatements(body); pp.Line("return JUndefinedObject.instance;"); pp.Line("{0} // {1}", "}", functionName); pp.Outdent(); } // EmitFunction
} // Append (string + parameters) // Append the given fragment, indented and enclosed in braces. internal void AppendIndentedBody(StmtFrag body) { Indent(); Append("{"); Append(body); Append("}"); Outdent(); }
public void AddCase(ExprFrag caseValue, StmtFrag caseStmt) { Entry newEntry = new Entry(); newEntry.caseValue = caseValue; newEntry.caseStmt = caseStmt; entries.Add(newEntry); }
} // Switch // Return a try...catch, try...finally, or try...catch...finally // statement. If there was no "catch" clause, then catchVar, catchWithInfo, // and catchBody will be null. If there was no "finally" clause, then // finallyBody will be null. These parameters can't all be null (i.e. // at least one of the "catch" and "finally" clauses must have been // present). public StmtFrag TryCatchFinally( SrcLoc loc, StmtFrag tryBody, string catchVar, WithInfo catchWithInfo, StmtFrag catchBody, StmtFrag finallyBody ) { CSharpStmtFrag frag = new CSharpStmtFrag(loc); frag.Append("try"); frag.AppendIndentedBody(tryBody); if (catchBody != null) { CSharpWithInfo csWithInfo = (CSharpWithInfo)catchWithInfo; frag.Append("catch (Exception catchTemp_{0})", csWithInfo.index+1); frag.Indent(); frag.Append("{"); frag.Append( "JObject withTemp_{0} = Support.CreateCatchScope(catchTemp_{0}, \"{1}\");", csWithInfo.index+1, catchVar ); frag.Append(catchBody); frag.Append("}"); frag.Outdent(); } if (finallyBody != null) { frag.Append("finally"); frag.AppendIndentedBody(finallyBody); } return frag; } // TryCatchFinally
// Append the given fragment to this fragment, so that they execute // sequentially. (NOTE: once this has been done, the "frag" parameter // is linked into this fragment, and should no longer be manipulated // independently.) public void Append(StmtFrag frag) { CSharpStmtFrag csFrag = (CSharpStmtFrag)frag; Trace.Assert(!used_); Trace.Assert(!csFrag.used_); if (csFrag.code_ == null) return; if (code_ == null) { code_ = csFrag.code_; last_ = csFrag.last_; } else { last_.next = csFrag.code_; last_ = csFrag.last_; } csFrag.used_ = true; } // Append (StmtFrag)
} // Throw // Return a with statement. public StmtFrag With(WithInfo withInfo, ExprFrag value, StmtFrag body) { CSharpWithInfo csWithInfo = (CSharpWithInfo)withInfo; CSharpStmtFrag frag = new CSharpStmtFrag(csWithInfo.loc); frag.Append( "object withTemp_{0} = ({1});", csWithInfo.index+1, ((CSharpExprFrag)value).GenerateRHS() ); frag.Append(body); return frag; } // With
} // Break // Return a statement which associated the specified LoopInfo with // an enclosing statement. This should be called for switch statements, // and for any labeled statement which is not a loop statement. public StmtFrag LabeledStmt(LoopInfo loopInfo, StmtFrag stmt) { CSharpLoopInfo csLoopInfo = (CSharpLoopInfo)loopInfo; CSharpStmtFrag frag = new CSharpStmtFrag(csLoopInfo.loc); frag.Append(stmt); frag.Append("breakTarget_{0}: {1}", csLoopInfo.index + 1, "{}"); return frag; } // LabeledStmt
} // For // Return a for/in statement. public StmtFrag ForIn( LoopInfo loopInfo, StmtFrag init, ExprFrag lhs, ExprFrag rhs, StmtFrag body ) { CSharpLoopInfo csLoopInfo = (CSharpLoopInfo)loopInfo; // HACK snewman 8/15/01: implement for/in statements. throw new ParseError( "For/In statements not yet implemented", csLoopInfo.loc ); } // ForIn
} // WhileDo // Return a for statement. init is the loop initializer, cond is the // loop control expression, and step is the loop increment expression. // Any or all of init, cond, and step can be null. public StmtFrag For( LoopInfo loopInfo, StmtFrag init, ExprFrag cond, ExprFrag step, StmtFrag body ) { CSharpLoopInfo csLoopInfo = (CSharpLoopInfo)loopInfo; CSharpStmtFrag frag = new CSharpStmtFrag(csLoopInfo.loc); frag.Append(init); CSharpExprFrag csCondition = (CSharpExprFrag)cond; frag.Append("while (Support.BoolTest(" + csCondition.GenerateRHS() + "))"); ((CSharpStmtFrag)body).Append("continueTarget_{0}:", csLoopInfo.index + 1); ((CSharpStmtFrag)body).Append(ExpressionStmt(step)); frag.AppendIndentedBody(body); frag.Append("breakTarget_{0}: {1}", csLoopInfo.index + 1, "{}"); return frag; } // For
} // IfThenElse // Return a do...while statement. public StmtFrag DoWhile( LoopInfo loopInfo, StmtFrag body, ExprFrag condition ) { CSharpLoopInfo csLoopInfo = (CSharpLoopInfo)loopInfo; CSharpStmtFrag frag = new CSharpStmtFrag(csLoopInfo.loc); CSharpExprFrag csCondition = (CSharpExprFrag)condition; frag.Append("do"); ((CSharpStmtFrag)body).Append("continueTarget_{0}:", csLoopInfo.index + 1); frag.AppendIndentedBody(body); frag.Append("while (Support.BoolTest(" + csCondition.GenerateRHS() + "))"); frag.Append("breakTarget_{0}: {1}", csLoopInfo.index + 1, "{}"); return frag; } // DoWhile