public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; // (if test then) or (if test then else) if (form.count() > 4) { throw new ParseException("Too many arguments to if"); } if (form.count() < 3) { throw new ParseException("Too few arguments to if"); } Expr testExpr = Compiler.Analyze(pcon.EvalOrExpr().SetAssign(false), RT.second(form)); Expr thenExpr = Compiler.Analyze(pcon.SetAssign(false), RT.third(form)); Expr elseExpr = Compiler.Analyze(pcon.SetAssign(false), RT.fourth(form)); return(new IfExpr((IPersistentMap)Compiler.SourceSpanVar.deref(), testExpr, thenExpr, elseExpr)); }
public void ExplictIPersistentCollectionConsWorks() { MapEntry me = new MapEntry(1, "abc"); IPersistentCollection c = (IPersistentCollection)me; ISeq s = c.cons(2).seq(); Expect(me.count()).To.Equal(2); Expect(me.key()).To.Equal(1); Expect(me.val()).To.Equal("abc"); Expect(s.count()).To.Equal(3); Expect(s.first()).To.Equal(1); Expect(s.next().first()).To.Equal("abc"); Expect(s.next().next().first()).To.Equal(2); Expect(s.next().next().next()).To.Be.Null(); }
public void ExplictIPersistentCollectionConsWorks() { MapEntry me = new MapEntry(1, "abc"); IPersistentCollection c = (IPersistentCollection)me; ISeq s = c.cons(2).seq(); Expect(me.count(), EqualTo(2)); Expect(me.key(), EqualTo(1)); Expect(me.val(), EqualTo("abc")); Expect(s.count(), EqualTo(3)); Expect(s.first(), EqualTo(1)); Expect(s.next().first(), EqualTo("abc")); Expect(s.next().next().first(), EqualTo(2)); Expect(s.next().next().next(), Null); }
public void SeqOnNonEmptyIterates() { Dictionary <int, string> d = new Dictionary <int, string>(); d[1] = "a"; d[2] = "b"; IPersistentMap m = PersistentArrayMap.create(d); ISeq s = m.seq(); IMapEntry me1 = (IMapEntry)s.first(); IMapEntry me2 = (IMapEntry)s.next().first(); ISeq end = s.next().next(); Expect(s.count(), EqualTo(2)); Expect(me1.key(), EqualTo(1) | EqualTo(2)); Expect(me1.val(), EqualTo(((int)me1.key() == 1 ? "a" : "b"))); Expect(me2.key(), EqualTo(1) | EqualTo(2)); Expect(me2.val(), EqualTo(((int)me2.key() == 1 ? "a" : "b"))); Expect(end, Null); }
private static Object process_output(Object o, int level) { if (o is IPersistentCollection) { o = ((IPersistentCollection)o).seq(); } if (o is ISeq) { ISeq r2 = (ISeq)o; object[] outArr = new object[r2.count()]; int i = 0; while (r2 != null) { outArr[i] = level == 1 ? process_output(r2.first(), 0) : cleanValue(r2.first()); i++; r2 = r2.next(); } return(level == 1 ? pack(outArr) : outArr); } else { return(level == 1 ? pack(cleanValue(o)) : cleanValue(o)); } }
public Expr Parse(ParserContext pcon, object frm) { //int line = (int)Compiler.LINE.deref(); ISeq form = (ISeq)frm; // form => (new Typename args ... ) if (form.count() < 2) { throw new ParseException("wrong number of arguments, expecting: (new Typename args ...)"); } Type t = HostExpr.MaybeType(RT.second(form), false); if (t == null) { throw new ParseException("Unable to resolve classname: " + RT.second(form)); } List <HostArg> args = HostExpr.ParseArgs(pcon, RT.next(RT.next(form))); return(new NewExpr(t, args, (IPersistentMap)Compiler.SourceSpanVar.deref())); }
private static object MacroexpandSeq1(ISeq form) { object op = RT.first(form); if (IsSpecial(op)) return form; // macro expansion Var v = IsMacro(op); if (v != null) { try { Var.pushThreadBindings(RT.map(RT.MACRO_META, RT.meta(form))); return v.applyTo(form.next()); } finally { Var.popThreadBindings(); } } else { if (op is Symbol) { Symbol sym = (Symbol)op; string sname = sym.Name; // (.substring s 2 5) => (. x substring 2 5) if (sname[0] == '.') { if (form.count() < 2) throw new ArgumentException("Malformed member expression, expecting (.member target ...)"); Symbol method = Symbol.intern(sname.Substring(1)); // TODO: Figure out why the following change made in Java Rev 1158 breaks ants.clj // Note on that revision: force instance member interpretation of (.method ClassName), e.g. (.getMethods String) works // However, when I do this, it makes ants.clj choke on: (def white-brush (new SolidBrush (.White Color))) object target = RT.second(form); if (MaybeType(target, false) != null) //target = RT.list(IDENTITY, target); target = ((IObj)RT.list(IDENTITY, target)).withMeta(RT.map(RT.TAG_KEY, CLASS)); return RT.listStar(DOT, target, method, form.next().next()); // safe substitute: return RT.listStar(Compiler.DOT, RT.second(form), method, form.next().next()); } else if (NamesStaticMember(sym)) { Symbol target = Symbol.intern(sym.Namespace); Type t = MaybeType(target, false); if (t != null) { Symbol method = Symbol.intern(sym.Name); return RT.listStar(Compiler.DOT, target, method, form.next()); } } else { // (x.substring 2 5) => (. s substring 2 5) int index = sname.LastIndexOf('.'); if (index == sname.Length - 1) return RT.listStar(Compiler.NEW, Symbol.intern(sname.Substring(0, index)), form.next()); } } } return form; }
private static object MacroexpandSeq1(ISeq form) { object op = RT.first(form); if (IsSpecial(op)) return form; // macro expansion Var v = IsMacro(op); if (v != null) { try { return v.applyTo(RT.cons(form, RT.cons(LocalEnvVar.get(), form.next()))); } catch (ArityException e) { // hide the 2 extra params for a macro throw new ArityException(e.Actual - 2, e.Name); } } else { Symbol sym = op as Symbol; if (sym != null) { string sname = sym.Name; // (.substring s 2 5) => (. x substring 2 5) if (sname[0] == '.') { if (form.count() < 2) throw new ArgumentException("Malformed member expression, expecting (.member target ...)"); Symbol method = Symbol.intern(sname.Substring(1)); object target = RT.second(form); if (HostExpr.MaybeType(target, false) != null) target = ((IObj)RT.list(IdentitySym, target)).withMeta(RT.map(RT.TagKey, ClassSym)); // We need to make sure source information gets transferred return MaybeTransferSourceInfo(PreserveTag(form, RT.listStar(DotSym, target, method, form.next().next())), form); } else if (NamesStaticMember(sym)) { Symbol target = Symbol.intern(sym.Namespace); Type t = HostExpr.MaybeType(target, false); if (t != null) { Symbol method = Symbol.intern(sym.Name); // We need to make sure source information gets transferred return MaybeTransferSourceInfo(PreserveTag(form, RT.listStar(Compiler.DotSym, target, method, form.next())), form); } } else { // (x.substring 2 5) => (. x substring 2 5) // also (package.class.name ... ) (. package.class name ... ) int index = sname.LastIndexOf('.'); if (index == sname.Length - 1) // We need to make sure source information gets transferred return MaybeTransferSourceInfo(RT.listStar(Compiler.NewSym, Symbol.intern(sname.Substring(0, index)), form.next()), form); } } } return form; }
public void Range_has_correct_count() { ISeq r = (ISeq)_createFn(2L, 20L); Expect(r.count(), EqualTo(18)); }
private static object MacroexpandSeq1(ISeq form) { object op = RT.first(form); if (IsSpecial(op)) return form; // macro expansion Var v = IsMacro(op); if (v != null) { // TODO: Check this against current code return v.applyTo(RT.cons(form, RT.cons(LOCAL_ENV.get(), form.next()))); } else { if (op is Symbol) { Symbol sym = (Symbol)op; string sname = sym.Name; // (.substring s 2 5) => (. x substring 2 5) if (sname[0] == '.') { if (form.count() < 2) throw new ArgumentException("Malformed member expression, expecting (.member target ...)"); Symbol method = Symbol.intern(sname.Substring(1)); object target = RT.second(form); if (HostExpr.MaybeType(target, false) != null) target = ((IObj)RT.list(IDENTITY, target)).withMeta(RT.map(RT.TAG_KEY, CLASS)); // We need to make sure source information gets transferred return MaybeTransferSourceInfo(PreserveTag(form, RT.listStar(DOT, target, method, form.next().next())), form); } else if (NamesStaticMember(sym)) { Symbol target = Symbol.intern(sym.Namespace); Type t = HostExpr.MaybeType(target, false); if (t != null) { Symbol method = Symbol.intern(sym.Name); // We need to make sure source information gets transferred return MaybeTransferSourceInfo(PreserveTag(form, RT.listStar(Compiler.DOT, target, method, form.next())), form); } } else { // (x.substring 2 5) => (. x substring 2 5) // also (package.class.name ... ) (. package.class name ... ) int index = sname.LastIndexOf('.'); if (index == sname.Length - 1) // We need to make sure source information gets transferred return MaybeTransferSourceInfo(RT.listStar(Compiler.NEW, Symbol.intern(sname.Substring(0, index)), form.next()), form); } } } return form; }
private static Expression GenerateIfExpr(ISeq form) { if (form.count() > 4) throw new Exception("Too many arguments to if"); if (form.count() < 3) throw new Exception("Too few arguments to if"); object test = RT.second(form); object trueClause = RT.third(form); object falseClause = RT.fourth(form); // TODO: if test has Boolean type, no need to box, just test directly. Expression realExpr = Expression.Call(Method_RT_IsTrue, MaybeBox(Generate(test))); Expression thenExpr = Generate(trueClause); Expression elseExpr = Generate(falseClause); if (thenExpr.Type != elseExpr.Type) { // Try to reconcile if (thenExpr.Type.IsAssignableFrom(elseExpr.Type) && elseExpr.Type != typeof(void)) elseExpr = Expression.Convert(elseExpr, thenExpr.Type); else if (elseExpr.Type.IsAssignableFrom(thenExpr.Type) && thenExpr.Type != typeof(void)) thenExpr = Expression.Convert(thenExpr, elseExpr.Type); else { if (thenExpr.Type == typeof(void)) thenExpr = Expression.Block(thenExpr, Expression.Default(elseExpr.Type)); else if (elseExpr.Type == typeof(void)) elseExpr = Expression.Block(elseExpr, Expression.Default(thenExpr.Type)); else { // TODO: Can we find a common ancestor? probably not. thenExpr = Expression.Convert(thenExpr, typeof(object)); elseExpr = Expression.Convert(elseExpr, typeof(object)); } } } return Expression.Condition(realExpr, thenExpr, elseExpr); }
private static Expression GenerateHostExpr(ISeq form) { // form is one of: // (. x fieldname-sym) // (. x 0-ary-method) // (. x propertyname-sym) // (. x methodname-sym args+) // (. x (methodname-sym args?)) if (RT.Length(form) < 3) throw new ArgumentException("Malformed member expression, expecting (. target member ... )"); // determine static or instance // static target must be symbol, either fully.qualified.Typename or Typename that has been imported Type t = MaybeType(RT.second(form),false); // at this point, t will be non-null if static Expression instance = null; if (t == null) instance = Generate(RT.second(form)); if ( form.count() == 3 && RT.third(form) is Symbol ) { Symbol sym = (Symbol) RT.third(form); if ( t != null ) { FieldInfo f = t.GetField(sym.Name, BindingFlags.Static | BindingFlags.Public); if (f != null) return Expression.Field(null, f); PropertyInfo p = t.GetProperty(sym.Name, BindingFlags.Static | BindingFlags.Public); if (p != null) return Expression.Property(null, p); } else { // I doubt that this will work. We will have to do a runtime determination FieldInfo f = instance.Type.GetField(sym.Name, BindingFlags.Instance | BindingFlags.Public); if (f != null) return Expression.Field(instance, f); PropertyInfo p = instance.Type.GetProperty(sym.Name, BindingFlags.Instance | BindingFlags.Public); if (p != null) return Expression.Property(instance, p); } } ISeq call = RT.third(form) is ISeq ? (ISeq)RT.third(form) : RT.next(RT.next(form)); if (!(RT.first(call) is Symbol)) throw new ArgumentException("Malformed member exception"); string methodName = ((Symbol)RT.first(call)).Name; int numArgs = call.count() - 1; Expression[] args = new Expression[numArgs]; int i = 0; for (ISeq s = call.next(); s != null; s = s.next(), i++) args[i] = Generate(s.first()); BindingFlags flags = BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.InvokeMethod; if (t != null) flags |= BindingFlags.Static; else flags |= BindingFlags.Instance; Type targetType = t ?? instance.Type; //DEBUG: //IEnumerable<MethodInfo> einfo1 = targetType.GetMethods(); //List<MethodInfo> infos1 = new List<MethodInfo>(einfo1); IEnumerable<MethodInfo> einfo = targetType.GetMethods(flags).Where(info => info.Name == methodName && info.GetParameters().Length == args.Length); List<MethodInfo> infos = new List<MethodInfo>(einfo); if (t != null && infos.Count == 0) throw new InvalidOperationException(string.Format("No method named: {0} in type: {1}", methodName, targetType.Name)); else if (infos.Count == 1) { // TODO: if t is not null, but instance isn't typed, we may be missing overloads. So I added a t != null. // We can improve this when we add better type info propagation. // we have a unique match, generate call directly if (t != null) return AstUtils.SimpleCallHelper(infos[0], args); else //return Expression.Call(instance, infos[0], args); //asdf-tag return AstUtils.SimpleCallHelper(instance,infos[0], args); } else { if (RT.booleanCast(RT.WARN_ON_REFLECTION.deref())) { // TODO: use DLR IO ((TextWriter)RT.ERR.deref()).WriteLine(string.Format("Reflection warning, line: {0} - call to {1} can't be resolved.\n", /* line ,*/0, methodName)); } Expression[] moreArgs = new Expression[3]; moreArgs[0] = Expression.Constant(methodName); moreArgs[1] = t != null ? Expression.Constant(t) : instance; moreArgs[2] = Expression.NewArrayInit(typeof(object), MaybeBox(args)); if (t != null) return Expression.Call(Method_Reflector_CallStaticMethod, moreArgs); else return Expression.Call(Method_Reflector_CallInstanceMethod, moreArgs); } }
private static Expression GenerateDefExpr(ISeq form) { if (form.count() > 3) throw new Exception("Too many arguments to def"); if (form.count() < 2) throw new Exception("Too few arguments to def"); Symbol sym = RT.second(form) as Symbol; bool initProvided = form.count() == 3; if (sym == null) throw new Exception("Second argument to def must be a Symbol."); Var v = lookupVar(sym, true); if (v == null) throw new Exception("Can't refer to qualified var that doesn't exist"); if (!v.Namespace.Equals(CurrentNamespace)) { if (sym.Namespace == null) throw new Exception(string.Format("Name conflict, can't def {0} because namespace: {1} refers to: {2}", sym, CurrentNamespace.Name, v)); else throw new Exception("Can't create defs outside of current namespace"); } IPersistentMap mm = sym.meta(); // TODO: add source line info metadata. //mm = (IPersistentMap) RT.assoc(RT.LINE_KEY, LINE.get()).assoc(RT.FILE_KEY, SOURCE.get()); // Bizarrely, we don't have to do anything to actually create the var, the lookupVar did that for us. // Will this work in a compiled class file? List<Expression> exprs = new List<Expression>(); Expression varExpr = GenerateConstExpr(v); if (initProvided) exprs.Add(Expression.Call(varExpr, Method_Var_BindRoot, MaybeBox(Generate(RT.third(form))))); ; if (mm != null) exprs.Add(Expression.Call(varExpr, Method_Var_SetMeta, GenerateMapExpr(mm))); exprs.Add(varExpr); return Expression.Block(exprs); }
private static Expression GenerateAssignExpr(ISeq form) { if (form.count() != 3) throw new ArgumentException("Malformed assignment, expecting (set! target val)"); object target = RT.second(form); object init = RT.third(form); Var v; if ( (v = FindAsVar(target)) != null) return GenerateVarAssignExpr(v, init); Type t; if ((t = FindAsDirectStaticFieldReference(target)) != null) return GenerateDirectStaticFieldAssignExpr(t, (target as Symbol).Name, init); if ( IsFieldReference(target)) return GenerateFieldAssignExpr(RT.second((ISeq)target),(string) RT.third((ISeq)target),init); throw new ArgumentException("Invalid assignment target"); }
private static Expression GenerateNewExpr(ISeq form) { // form => (new Classname args ... ) if (form.count() < 2) throw new Exception("wrong number of arguments, expecting: (new Classname args ...)"); Type t = MaybeType(RT.second(form), false); if (t == null) throw new ArgumentException("Unable to resolve classname: " + RT.second(form)); int numArgs = form.count() - 2; Expression[] args = new Expression[numArgs]; int i = 0; for (ISeq s = RT.next(RT.next(form)); s != null; s = s.next(), i++) args[i] = Generate(s.first()); List<ConstructorInfo> cinfos = new List<ConstructorInfo>(t.GetConstructors().Where(x => x.GetParameters().Length == numArgs && x.IsPublic)); if (cinfos.Count == 0) throw new InvalidOperationException(string.Format("No constructor in type: {0} with {1} arguments", t.Name, numArgs)); else if (cinfos.Count == 1) { // we have a unique match, generate directly // Need to try to convert the arguments, or the call to Expression.New will choke ConstructorInfo info = cinfos[0]; Expression[] convArgs = new Expression[numArgs]; for ( i=0; i < numArgs; i++ ) convArgs[i] = Expression.Convert(args[i],info.GetParameters()[i].ParameterType); return Expression.New(info, convArgs); } else { // we must defer to runtime if (RT.booleanCast(RT.WARN_ON_REFLECTION.deref())) { // TODO: use DLR IO ((TextWriter)RT.ERR.deref()).WriteLine(string.Format("Reflection warning, line: {0} - call to new can't be resolved.\n", /* line ,*/0)); } Expression[] moreArgs = new Expression[2]; moreArgs[0] = Expression.Constant(t); moreArgs[1] = Expression.NewArrayInit(typeof(object), MaybeBox(args)); return Expression.Call(Method_Reflector_InvokeConstructor, moreArgs); } }