internal static FnMethod Parse(FnExpr fn, ISeq form, object retTag) { // ([args] body ... ) IPersistentVector parms = (IPersistentVector)RT.first(form); ISeq body = RT.next(form); try { FnMethod method = new FnMethod(fn, (ObjMethod)Compiler.MethodVar.deref()); method.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); Var.pushThreadBindings(RT.mapUniqueKeys( Compiler.MethodVar, method, Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.LoopLocalsVar, null, Compiler.NextLocalNumVar, 0)); method._prim = PrimInterface(parms); //if (method._prim != null) // method._prim = method._prim.Replace('.', '/'); if (retTag is String) { retTag = Symbol.intern(null, (string)retTag); } if (!(retTag is Symbol)) { retTag = null; } if (retTag != null) { string retStr = ((Symbol)retTag).Name; if (!(retStr.Equals("long") || retStr.Equals("double"))) { retTag = null; } } method._retType = Compiler.TagType(Compiler.TagOf(parms) ?? retTag); if (method._retType.IsPrimitive) { if (!(method._retType == typeof(double) || method._retType == typeof(long))) { throw new ParseException("Only long and double primitives are supported"); } } else { method._retType = typeof(object); } // register 'this' as local 0 Compiler.RegisterLocalThis(Symbol.intern(fn.ThisName ?? "fn__" + RT.nextID()), null, null); ParamParseState paramState = ParamParseState.Required; IPersistentVector argLocals = PersistentVector.EMPTY; List <Type> argTypes = new List <Type>(); int parmsCount = parms.count(); for (int i = 0; i < parmsCount; i++) { if (!(parms.nth(i) is Symbol)) { throw new ParseException("fn params must be Symbols"); } Symbol p = (Symbol)parms.nth(i); if (p.Namespace != null) { throw new ParseException("Can't use qualified name as parameter: " + p); } if (p.Equals(Compiler.AmpersandSym)) { if (paramState == ParamParseState.Required) { paramState = ParamParseState.Rest; } else { throw new ParseException("Invalid parameter list"); } } else { Type pt = Compiler.PrimType(Compiler.TagType(Compiler.TagOf(p))); if (pt.IsPrimitive && !(pt == typeof(double) || pt == typeof(long))) { throw new ParseException("Only long and double primitives are supported: " + p); } if (paramState == ParamParseState.Rest && Compiler.TagOf(p) != null) { throw new ParseException("& arg cannot have type hint"); } if (paramState == ParamParseState.Rest && method.Prim != null) { throw new ParseException("fns taking primitives cannot be variadic"); } if (paramState == ParamParseState.Rest) { pt = typeof(ISeq); } argTypes.Add(pt); LocalBinding b = pt.IsPrimitive ? Compiler.RegisterLocal(p, null, new MethodParamExpr(pt), pt, true) : Compiler.RegisterLocal(p, paramState == ParamParseState.Rest ? Compiler.ISeqSym : Compiler.TagOf(p), null, pt, true); argLocals = argLocals.cons(b); switch (paramState) { case ParamParseState.Required: method._reqParms = method._reqParms.cons(b); break; case ParamParseState.Rest: method._restParm = b; paramState = ParamParseState.Done; break; default: throw new ParseException("Unexpected parameter"); } } } if (method.RequiredArity > Compiler.MaxPositionalArity) { throw new ParseException(string.Format("Can't specify more than {0} parameters", Compiler.MaxPositionalArity)); } Compiler.LoopLocalsVar.set(argLocals); method.ArgLocals = argLocals; method._argTypes = argTypes.ToArray(); method.Body = (new BodyExpr.Parser()).Parse(new ParserContext(RHC.Return), body); return(method); } finally { Var.popThreadBindings(); } }
internal static FnMethod Parse(FnExpr fn, ISeq form) { // ([args] body ... ) IPersistentVector parms = (IPersistentVector)RT.first(form); ISeq body = RT.next(form); try { FnMethod method = new FnMethod(fn, (FnMethod)Compiler.METHODS.deref()); // TODO: method.line = (Integer) LINE.deref(); Var.pushThreadBindings(RT.map( Compiler.METHODS, method, Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(), Compiler.LOOP_LOCALS, null, Compiler.NEXT_LOCAL_NUM, 0)); // register 'this' as local 0 method._thisBinding = Compiler.RegisterLocal(Symbol.intern(fn.ThisName ?? "fn__" + RT.nextID()), null, null); ParamParseState paramState = ParamParseState.Required; IPersistentVector argLocals = PersistentVector.EMPTY; int parmsCount = parms.count(); for (int i = 0; i < parmsCount; i++) { if (!(parms.nth(i) is Symbol)) { throw new ArgumentException("fn params must be Symbols"); } Symbol p = (Symbol)parms.nth(i); if (p.Namespace != null) { throw new Exception("Can't use qualified name as parameter: " + p); } if (p.Equals(Compiler._AMP_)) { if (paramState == ParamParseState.Required) { paramState = ParamParseState.Rest; } else { throw new Exception("Invalid parameter list"); } } else { LocalBinding b = Compiler.RegisterLocal(p, paramState == ParamParseState.Rest ? Compiler.ISEQ : Compiler.TagOf(p), null); // asdf-tag argLocals = argLocals.cons(b); switch (paramState) { case ParamParseState.Required: method._reqParms = method._reqParms.cons(b); break; case ParamParseState.Rest: method._restParm = b; paramState = ParamParseState.Done; break; default: throw new Exception("Unexpected parameter"); } } } if (method.NumParams > Compiler.MAX_POSITIONAL_ARITY) { throw new Exception(string.Format("Can't specify more than {0} parameters", Compiler.MAX_POSITIONAL_ARITY)); } Compiler.LOOP_LOCALS.set(argLocals); method._argLocals = argLocals; method._body = (new BodyExpr.Parser()).Parse(body); return(method); } finally { Var.popThreadBindings(); } }