예제 #1
0
파일: CodeGen.cs 프로젝트: ypyf/Clound
        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);
            }
        }