// import := "import" STRING [ "{" <ident> { "," <ident> } "}" ] // import "System" private Stmt ImportStmt() { Match("import"); ImportStmt import = new ImportStmt(); import.Name = ((StrToken)Expect(typeof(StrToken))).Text; EatToken(); return(import); }
private void GenStmt(Stmt stmt, Env table, ILGenerator il) { if (stmt is Sequence) { Sequence seq = (Sequence)stmt; GenStmt(seq.First, table, il); GenStmt(seq.Second, table, il); } else if (stmt is ImportStmt) { // 只能导入.Net模块 ImportStmt import = (ImportStmt)stmt; Reflect.Assembly asm = null; if (import.Name == "System") { // 首先在核心模块中查找 // 获取int类型所在的程序集(mscorlib.dll) asm = Reflect.Assembly.GetAssembly(typeof(int)); } else { string root = Framework.GetFrameworkDirectory(); string assembly = IO.Path.Combine(root, import.Name + ".dll"); asm = Reflect.Assembly.LoadFile(assembly); // TODO 错误处理 } table.AddModule(new Module(import.Name, asm)); } else if (stmt is DeclareVar) { DeclareVar declare = (DeclareVar)stmt; Type type = declare.Type; if (type == null) { type = TypeOfExpr(declare.Expr, table); } if (table.IsDeclared(declare.Name)) { throw new Exception(String.Format("A local variable named '{0}' is already defined in this scope", declare.Name)); } // TODO 保存本地变量的位置索引 table[declare.Name] = new LocalVariable(il.DeclareLocal(type)); // set the initial value BinaryExpr be = new BinaryExpr(); Variable var = new Variable(); var.Name = declare.Name; be.Left = var; be.Op = "="; if (declare.Expr is Undefined) { // FIXME 根据所声明变量的类型赋初值 IntLiteral expr = new IntLiteral(); expr.Value = 0; be.Right = expr; } else { be.Right = declare.Expr; } GenExpr(be, table, il); } else if (stmt is Return) { Return ret = (Return)stmt; GenExpr(ret.Expr, table, il); } else if (stmt is Function) { // 定义全局函数 DefineGlobalMethod((Function)stmt, table); } else if (stmt is Print) { Print print = (Print)stmt; GenExpr(print.Expr, table, il); Reflect.MethodInfo mi = typeof(Console).GetMethod("WriteLine", new Type[] { TypeOfExpr(print.Expr, table) }); il.Emit(OpCodes.Call, mi); } else if (stmt is IfStmt) { IfStmt ifStmt = (IfStmt)stmt; // 代码块的结束位置 Label End = il.DefineLabel(); // 生成条件表达式 GenExpr(ifStmt.Cond, table, il); il.Emit(OpCodes.Brfalse, End); // then代码块 //il.BeginScope(); GenStmt(ifStmt.Then, table, il); //il.EndScope(); il.MarkLabel(End); } else if (stmt is IfElseStmt) { IfElseStmt ifElseStmt = (IfElseStmt)stmt; // 分支标签 Label ThenEnd = il.DefineLabel(); Label End = il.DefineLabel(); // 条件表达式 GenExpr(ifElseStmt.Cond, table, il); il.Emit(OpCodes.Brfalse, ThenEnd); // then分支 GenStmt(ifElseStmt.Then, table, il); il.Emit(OpCodes.Br, End); il.MarkLabel(ThenEnd); // else分支 GenStmt(ifElseStmt.Else, table, il); il.MarkLabel(End); } else if (stmt is WhileLoop) { WhileLoop whileLoop = (WhileLoop)stmt; Label LoopStart = il.DefineLabel(); Label LoopEnd = il.DefineLabel(); il.MarkLabel(LoopStart); GenExpr(whileLoop.Cond, table, il); il.Emit(OpCodes.Brfalse, LoopEnd); GenStmt(whileLoop.Body, table, il); il.Emit(OpCodes.Br, LoopStart); il.MarkLabel(LoopEnd); } //else if (stmt is ForLoop) //{ // ForLoop forLoop = (ForLoop)stmt; // Assign assign = new Assign(); // assign.Ident = forLoop.Name; // assign.Expr = forLoop.From; // GenStmt(assign, table, il); // // jump to the test // Label test = il.DefineLabel(); // il.Emit(OpCodes.Br, test); // // statements in the body of the for loop // Label body = il.DefineLabel(); // il.MarkLabel(body); // GenStmt(forLoop.Body, table, il); // // to (increment the value of x) // il.Emit(OpCodes.Ldloc, table[forLoop.Name]); // il.Emit(OpCodes.Ldc_I4, 1); // il.Emit(OpCodes.Add); // Store(forLoop.Name, table, il); // // **test** does x equal 100? (do the test) // il.MarkLabel(test); // il.Emit(OpCodes.Ldloc, table[forLoop.Name]); // GenExpr(forLoop.To, table, il); // il.Emit(OpCodes.Blt, body); //} //else if (stmt is Expr) //{ // GenExpr((Expr)stmt, table, il); //} else if (stmt is Simple) { Simple simple = (Simple)stmt; GenExpr(simple.Expr, table, il); // TODO 无括号的函数调用 } else if (stmt is EmptyStmt) { // empty statement // do nothing } else { throw new Exception("don't know how to gen a " + stmt.GetType().Name); } }