private Postfix Postfix() { if (IsToken("(")) { Match("("); CallExpr ce = new CallExpr(); ce.Args = ArgList(); ce.Postfix = Postfix(); Match(")"); return(ce); } else if (IsToken(".")) { Match("."); MemberAccessExpr mae = new MemberAccessExpr(); mae.Ident = ((IdentToken)Expect(typeof(IdentToken))).Text; EatToken(); mae.Postfix = Postfix(); return(mae); } else { return(null); } }
private Type TypeOfExpr(Expr expr, Env table) { if (expr is StrLiteral) { return(typeof(string)); } else if (expr is IntLiteral) { return(typeof(int)); } else if (expr is Variable) { Variable var = (Variable)expr; if (table.HasInstance(var.Name)) { return(table[var.Name].SymbolType); } else { throw new Exception("undeclared variable '" + var.Name + "'"); } } else if (expr is BoolLiteral) { return(typeof(bool)); } else if (expr is CallExpr) { // TODO 检查函数类型 return(typeof(object)); } else if (expr is MemberAccessExpr) { MemberAccessExpr mae = (MemberAccessExpr)expr; return(TypeOfExpr(mae.Postfix, table)); } else if (expr is PrimaryExpr) { PrimaryExpr pe = (PrimaryExpr)expr; return(TypeOfExpr(pe.Postfix, table)); } //else if (expr is Undefined) //{ // return typeof(object); //} else { throw new Exception("don't know how to calculate the type of " + expr.GetType().Name); } }
private void GenExpr(Expr expr, Env table, ILGenerator il) { if (expr is StrLiteral) { il.Emit(OpCodes.Ldstr, ((StrLiteral)expr).Value); } else if (expr is IntLiteral) { il.Emit(OpCodes.Ldc_I4, ((IntLiteral)expr).Value); } else if (expr is BoolLiteral) { il.Emit(OpCodes.Ldc_I4, ((BoolLiteral)expr).Value); } else if (expr is Variable) { string name = ((Variable)expr).Name; Load(name, table, il); } else if (expr is PrimaryExpr) { PrimaryExpr pe = (PrimaryExpr)expr; //GenExpr(pe.Lhs, table, il); if (pe.Lhs is Variable) // LHS此时可能是命名空间、类型名、实例变量(包括函数名)等 { string name = ((Variable)pe.Lhs).Name; if (pe.Postfix is CallExpr) { // TODO 目前不考虑链式调用 CallExpr ce = (CallExpr)pe.Postfix; // 函数调用 if (globalFunctions.ContainsKey(name)) { // 载入参数 foreach (var arg in ce.Args) { GenExpr(arg, table, il); } // 调用函数 Reflect.MethodInfo mi = globalFunctions[name]; il.Emit(OpCodes.Call, mi); } else if (table.HasInstance(name)) { throw new Exception(String.Format("'{0}'是变量,不是函数", name)); } else { throw new Exception(String.Format("当前上下文中不存在名称'{0}'", name)); } } else if (pe.Postfix is MemberAccessExpr) { // 目前只实现了导入模块,还没有实现Class MemberAccessExpr mae = (MemberAccessExpr)pe.Postfix; if (mae.Postfix is MemberAccessExpr) { string ns = ns = name + "." + mae.Ident;; // 合并命名空间(CLR的类型名在运行时是命名空间的一部分) PrimaryExpr exp = new PrimaryExpr(); Variable var = new Variable(); var.Name = ns; exp.Lhs = var; exp.Postfix = mae.Postfix; // 递归生成合并后的表达式 GenExpr(exp, table, il); } else if (mae.Postfix is CallExpr) { // 调用C#模块中的方法 CallExpr ce = (CallExpr)mae.Postfix; // 在所有模块中间查找类型和方法 Type type = FirstMatchType(name, table); if (type != null) { // 载入参数 List <Type> typelist = new List <Type>(); foreach (var arg in ce.Args) { typelist.Add(TypeOfExpr(arg, table)); GenExpr(arg, table, il); } // 调用函数 Reflect.MethodInfo mi = type.GetMethod(mae.Ident, typelist.ToArray()); if (mi != null) { il.Emit(OpCodes.Call, mi); } else { throw new Exception(String.Format("方法{0}未发现", mae.Ident)); } } else { throw new Exception(String.Format("类型{0}未发现", name)); } } else { //此时 Postfix == null // 访问属性 // 例如 a.Length throw new NotImplementedException(); } } } else { // TODO OO语言中,可以考虑在字面量上访问方法 // 例如 10.to_s() => "10" throw new NotImplementedException(); } } else if (expr is BinaryExpr) { BinaryExpr be = (BinaryExpr)expr; // 赋值 if (be.Op.Equals("=")) { GenExpr(be.Right, table, il); if (be.Left is Variable) { Store(((Variable)be.Left).Name, table, il); } else { throw new Exception("except a lvalue at assign"); } } else { // 算术运算 // FIXME IL没有一些条件运算,需要单独提出来实现 GenExpr(be.Left, table, il); GenExpr(be.Right, table, il); switch (be.Op) { case "+": il.Emit(OpCodes.Add); break; case "-": il.Emit(OpCodes.Sub); break; case "*": il.Emit(OpCodes.Mul); break; case "/": il.Emit(OpCodes.Div); break; case "%": il.Emit(OpCodes.Rem); break; case "<": il.Emit(OpCodes.Clt); break; case ">": il.Emit(OpCodes.Cgt); break; case "==": il.Emit(OpCodes.Ceq); break; case "<=": //il.Emit(OpCodes.Cgt); // FIXME //break; case ">=": //il.Emit(OpCodes.Clt); // FIXME //break; case "!=": //il.Emit(OpCodes.Ceq); // FIXME //break; default: throw new Exception("Unrecognized operator: " + be.Op); } } } else if (expr is Undefined) { return; } else { throw new Exception("don't know how to generate " + expr.GetType().Name); } }