public static Expr IndexOfString(ICall call) { var ctx = call.Ctx; var expr = new ExprJsResolvedMethod(ctx, ctx.Int32, call.Obj, "indexOf", call.Args); return(expr); }
public static Expr IndexOfChar(ICall call) { var ctx = call.Ctx; var args = call.Args.Select((x, i) => i != 0 ? x : new ExprJsResolvedMethod(ctx, ctx.Char, null, "String.fromCharCode", x)); var expr = new ExprJsResolvedMethod(ctx, ctx.Int32, call.Obj, "indexOf", args); return(expr); }
public static Stmt GetHashCode(Ctx ctx) { var toString = new ExprJsResolvedMethod(ctx, ctx.String, ctx.This, "toExponential"); var getHashCode = new ExprCall(ctx, typeof(string).GetMethod("GetHashCode"), toString); var stmt = new StmtReturn(ctx, getHashCode); return(stmt); }
public static Expr Join(ICall call) { var ctx = call.Ctx; var separator = call.Arg(0, "separator"); var values = call.Arg(1); var sepExpr = new ExprJsExplicit(ctx, "separator || \"\"", ctx.String, separator); var expr = new ExprJsResolvedMethod(ctx, ctx.String, values, "join", sepExpr); return(expr); }
public static Stmt IsWhiteSpace(Ctx ctx) { // See http://msdn.microsoft.com/en-us/library/t809ektx.aspx for list var whiteSpace = " \u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d\u0085\u00a0"; var arg0 = ctx.MethodParameter(0); var c = new ExprJsResolvedMethod(ctx, ctx.String, null, "String.fromCharCode", arg0); var indexOf = new ExprJsResolvedMethod(ctx, ctx.Boolean, ctx.Literal(whiteSpace), "indexOf", c); return(new StmtReturn(ctx, new ExprBinary(ctx, BinaryOp.GreaterThanOrEqual, ctx.Boolean, indexOf, ctx.Literal(0)))); }
public static Expr Copy(ICall call) { // d = arg[0].slice(arg[1],arg[4]+arg[1]) // Array.prototype.splice.apply(arg[2], [arg[3], arg[4]].concat(d)) var ctx = call.Ctx; var src = call.Args.ElementAt(0); var srcIdx = call.Args.ElementAt(1); var dst = call.Args.ElementAt(2); var dstIdx = call.Args.ElementAt(3); var length = call.Args.ElementAt(4); var arrayPart = new ExprJsResolvedMethod(ctx, src.Type, src, "slice", srcIdx, ctx.ExprGen.Add(srcIdx, length)); var spliceFixedArgs = new ExprJsArrayLiteral(ctx, ctx.Object, dstIdx, length); var spliceArgs = new ExprJsResolvedMethod(ctx, spliceFixedArgs.Type, spliceFixedArgs, "concat", arrayPart); var copy = new ExprJsResolvedMethod(ctx, ctx.Void, null, "Array.prototype.splice.apply", dst, spliceArgs); return(copy); }
protected override ICode VisitJsResolvedMethod(ExprJsResolvedMethod e) { if (e.Obj != null) { this.code.Append(e.Obj); this.code.Append("."); } this.code.Append(e.MethodName); this.code.Append("("); if (e.Args.Any()) { foreach (var arg in e.Args) { this.Visit(arg); this.code.Append(", "); } this.code.Length -= 2; } this.code.Append(")"); return(e); }
/// <summary> /// If a call/newobj requires translating to an Expr that is not a call/newobj, then it is done here. /// </summary> /// <param name="call"></param> /// <returns></returns> public static Expr ResolveCallSite(ICall call) { var ctx = call.Ctx; var mRef = call.CallMethod; var tRefDecl = mRef.DeclaringType; var mDef = mRef.Resolve(); // A call to a method in a "JsClass" class - all external methods/properties require translating to JS var tDefDecl = mDef.DeclaringType; var jsClassAttr = tDefDecl.GetCustomAttribute <JsClassAttribute>() ?? tDefDecl.GetCustomAttribute <JsAbstractClassAttribute>(); if (jsClassAttr != null) { if (mDef.IsExternal()) { var jsDetail = mDef.GetCustomAttribute <JsDetailAttribute>(true); var jsDetailName = jsDetail.NullThru(x => (string)x.Properties.FirstOrDefault(y => y.Name == "Name").Argument.Value); var jsDetailIsDomEventProp = jsDetail.NullThru(x => ((bool?)x.Properties.FirstOrDefault(y => y.Name == "IsDomEvent").Argument.Value) ?? false); if (mDef.IsGetter || mDef.IsSetter) { // Property access if (jsDetailIsDomEventProp) { // Special handling of DOM events if (!mDef.IsSetter) { throw new InvalidOperationException("Only setters supported on DOM events"); } if (!mDef.Name.StartsWith("set_On")) { throw new InvalidOperationException("DOM event name must start with 'On'"); } if (call.Args.Count() != 1) { throw new InvalidOperationException("DOM event setter must have exactly one argument"); } var eventName = jsDetailName ?? mDef.Name.Substring(6).ToLowerInvariant(); var eventNameExpr = ctx.Literal(eventName); var safeCallFunction = (Action <object, string, Delegate>)InternalFunctions.SafeAddEventListener; var safeCall = new ExprCall(ctx, safeCallFunction, null, call.Obj, eventNameExpr, call.Args.First()); return(safeCall); } else { var propertyName = jsDetailName ?? JsCase(mDef.Name.Substring(4)); if (mDef.Name.Substring(4) == "Item") { propertyName = null; } else if (mDef.IsStatic) { propertyName = JsCase(mDef.DeclaringType.Name) + "." + propertyName; } var jsProperty = new ExprJsResolvedProperty(ctx, call, propertyName); return(jsProperty); } } else if (mDef.IsConstructor && !mDef.IsStatic) { // Constructor new object call var typeName = jsDetailName ?? (string)jsClassAttr.ConstructorArguments[0].Value; var expr = new ExprJsResolvedCtor(ctx, typeName, tRefDecl, call.Args); return(expr); } else { // Normal method call var methodName = jsDetailName ?? JsCase(mDef.Name); if (mDef.IsStatic) { methodName = JsCase(mDef.DeclaringType.Name) + "." + methodName; } var expr = new ExprJsResolvedMethod(ctx, call.Type, call.Obj, methodName, call.Args); return(expr); } } else { return(null); } } var jsRedirectAttr = mDef.GetCustomAttribute <JsRedirectAttribute>(true); if (jsRedirectAttr != null) { if (jsRedirectAttr.ConstructorArguments[0].Value == null) { return(FindExprReturn(call, call.CallMethod.DeclaringType)); } var redirectToTRef = ((TypeReference)jsRedirectAttr.ConstructorArguments[0].Value).FullResolve(mRef); var redirectToMRef = redirectToTRef.EnumResolvedMethods(mRef).First(x => x.MatchMethodOnly(mRef)); switch (call.ExprType) { case Expr.NodeType.NewObj: return(new ExprNewObj(ctx, redirectToMRef, call.Args)); case Expr.NodeType.Call: return(new ExprCall(ctx, redirectToMRef, call.Obj, call.Args, call.IsVirtualCall, null, call.Type)); default: throw new NotImplementedException("Cannot handle: " + call.ExprType); } } var exprRet = FindExprReturn(call); if (exprRet != null) { return(exprRet); } return(null); }