public JsExpression CallBase(IMethod method, IEnumerable <JsExpression> thisAndArguments, IRuntimeContext context) { var impl = _metadataImporter.GetMethodSemantics(method); JsExpression jsMethod = JsExpression.Member(JsExpression.Member(GetScriptType(method.DeclaringType, TypeContext.GetScriptType, context), "prototype"), impl.Name); if (method is SpecializedMethod && !impl.IgnoreGenericArguments) { jsMethod = InstantiateGenericMethod(jsMethod, ((SpecializedMethod)method).TypeArguments, context); } if (impl.ExpandParams) { var args = thisAndArguments.ToList(); if (args[args.Count - 1] is JsArrayLiteralExpression) { return(JsExpression.Invocation(JsExpression.Member(jsMethod, "call"), args.Take(args.Count - 1).Concat(((JsArrayLiteralExpression)args[args.Count - 1]).Elements))); } else { return(JsExpression.Invocation(JsExpression.Member(jsMethod, "apply"), args[0], args.Count == 2 ? args[1] : JsExpression.Invocation(JsExpression.Member(JsExpression.ArrayLiteral(args.Skip(1).Take(args.Count - 2)), "concat"), args[args.Count - 1]))); } } else { return(JsExpression.Invocation(JsExpression.Member(jsMethod, "call"), thisAndArguments)); } }
public static JsExpression ResolveTypeParameter(ITypeParameter tp, ITypeDefinition currentType, IMethod currentMethod, IMetadataImporter metadataImporter, IErrorReporter errorReporter, INamer namer) { bool unusable = false; switch (tp.OwnerType) { case EntityType.TypeDefinition: unusable = metadataImporter.GetTypeSemantics(currentType).IgnoreGenericArguments; break; case EntityType.Method: { var sem = metadataImporter.GetMethodSemantics(currentMethod); unusable = sem.Type != MethodScriptSemantics.ImplType.InlineCode && metadataImporter.GetMethodSemantics(currentMethod).IgnoreGenericArguments; break; } default: errorReporter.InternalError("Invalid owner " + tp.OwnerType + " for type parameter " + tp); return(JsExpression.Null); } if (unusable) { errorReporter.Message(Messages._7536, tp.Name, tp.OwnerType == EntityType.TypeDefinition ? "type" : "method", tp.OwnerType == EntityType.TypeDefinition ? currentType.FullName : currentMethod.FullName); return(JsExpression.Null); } return(JsExpression.Identifier(namer.GetTypeParameterName(tp))); }
private MethodScriptSemantics GetMethodSemantics(IMethod m) { if (m.IsAccessor) { var prop = m.AccessorOwner as IProperty; if (prop != null) { var psem = _metadataImporter.GetPropertySemantics(prop); if (psem.Type != PropertyScriptSemantics.ImplType.GetAndSetMethods) { throw new InvalidOperationException("Property " + prop.Name + " should be implemented with get/set methods"); } if (m.Equals(prop.Getter)) { return(psem.GetMethod); } else if (m.Equals(prop.Setter)) { return(psem.SetMethod); } else { throw new Exception(m + " is neither the getter nor the setter for " + prop); } } var evt = m.AccessorOwner as IEvent; if (evt != null) { var esem = _metadataImporter.GetEventSemantics(evt); if (esem.Type != EventScriptSemantics.ImplType.AddAndRemoveMethods) { throw new InvalidOperationException("Event " + prop.Name + " should be implemented with add/remove methods"); } if (m.Equals(evt.AddAccessor)) { return(esem.AddMethod); } else if (m.Equals(evt.RemoveAccessor)) { return(esem.RemoveMethod); } else { throw new Exception(m + " is neither the adder nor the remover for " + evt); } } throw new ArgumentException("Invalid accessor owner " + m.AccessorOwner + " on member " + m); } else { return(_metadataImporter.GetMethodSemantics(m)); } }
public override JsExpression VisitOperatorResolveResult(OperatorResolveResult rr, object data) { bool isUserDefined = (rr.UserDefinedOperatorMethod != null && _metadataImporter.GetMethodSemantics(rr.UserDefinedOperatorMethod).Type != MethodScriptSemantics.ImplType.NativeOperator); var arguments = new JsExpression[rr.Operands.Count + 1]; for (int i = 0; i < rr.Operands.Count; i++) arguments[i] = VisitResolveResult(rr.Operands[i], null); arguments[arguments.Length - 1] = isUserDefined ? _getMember(rr.UserDefinedOperatorMethod) : _instantiateType(rr.Type); if (rr.OperatorType == ExpressionType.Conditional) return CompileFactoryCall("Condition", new[] { typeof(Expression), typeof(Expression), typeof(Expression), typeof(Type) }, arguments); else { return CompileFactoryCall(rr.OperatorType.ToString(), rr.Operands.Count == 1 ? new[] { typeof(Expression), isUserDefined ? typeof(MethodInfo) : typeof(Type) } : new[] { typeof(Expression), typeof(Expression), isUserDefined ? typeof(MethodInfo) : typeof(Type) }, arguments); } }
private JsStatement InvokeEntryPoint(IMethod entryPoint) { if (entryPoint.Parameters.Count > 0) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7800, entryPoint.FullName); return(JsExpression.Null); } else { var sem = _metadataImporter.GetMethodSemantics(entryPoint); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7801, entryPoint.FullName); return(JsExpression.Null); } else { return(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name))); } } }
private static JsExpression ConstructMemberInfo(IMember m, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func <IType, JsExpression> instantiateType, bool includeDeclaringType, MethodScriptSemantics semanticsIfAccessor) { if (m is IMethod && ((IMethod)m).IsConstructor) { return(ConstructConstructorInfo((IMethod)m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType)); } var properties = GetCommonMemberInfoProperties(m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType); if (m.IsStatic) { properties.Add(new JsObjectLiteralProperty("isStatic", JsExpression.True)); } if (m is IMethod) { var method = (IMethod)m; var sem = semanticsIfAccessor ?? metadataImporter.GetMethodSemantics(method); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7201, m.FullName, "method"); return(JsExpression.Null); } if ((sem.Type == MethodScriptSemantics.ImplType.NormalMethod || sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) && sem.ExpandParams) { properties.Add(new JsObjectLiteralProperty("exp", JsExpression.True)); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method))); if (sem.Type == MethodScriptSemantics.ImplType.InlineCode) { var usedNames = new HashSet <string>(); var parameters = new List <IVariable>(); var variables = new Dictionary <IVariable, VariableData>(); var arguments = new List <ResolveResult>(); foreach (var p in method.Parameters) { string name = namer.GetVariableName(p.Name, usedNames); usedNames.Add(name); var variable = new SimpleVariable(p.Type, p.Name, DomRegion.Empty); parameters.Add(variable); variables.Add(variable, new VariableData(name, null, false)); arguments.Add(new LocalResolveResult(variable)); } var tokens = InlineCodeMethodCompiler.Tokenize(method, sem.LiteralCode, _ => {}); var compileResult = Compile(CreateMethodInvocationResolveResult(method, method.IsStatic ? (ResolveResult) new TypeResolveResult(method.DeclaringType) : new ThisResolveResult(method.DeclaringType), arguments), method.DeclaringTypeDefinition, method, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, true, variables, usedNames); var definition = JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), JsStatement.Block(compileResult.AdditionalStatements.Concat(new[] { JsStatement.Return(compileResult.Expression) }))); if (tokens.Any(t => t.Type == InlineCodeToken.TokenType.TypeParameter && t.OwnerType == SymbolKind.Method)) { definition = JsExpression.FunctionDefinition(method.TypeParameters.Select(namer.GetTypeParameterName), JsStatement.Return(definition)); properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count))); } properties.Add(new JsObjectLiteralProperty("def", definition)); } else { if (IsJsGeneric(method, metadataImporter)) { properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count))); } if (sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) { properties.Add(new JsObjectLiteralProperty("sm", JsExpression.True)); } properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(method.ReturnType))); properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(method.Parameters.Select(p => instantiateType(p.Type))))); } else if (m is IField) { var field = (IField)m; var sem = metadataImporter.GetFieldSemantics(field); if (sem.Type != FieldScriptSemantics.ImplType.Field) { errorReporter.Message(Messages._7201, m.FullName, "field"); return(JsExpression.Null); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Field))); properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(field.ReturnType))); properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } else if (m is IProperty) { var prop = (IProperty)m; var sem = metadataImporter.GetPropertySemantics(prop); properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Property))); properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(prop.ReturnType))); if (prop.Parameters.Count > 0) { properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(prop.Parameters.Select(p => instantiateType(p.Type))))); } switch (sem.Type) { case PropertyScriptSemantics.ImplType.GetAndSetMethods: if (sem.GetMethod != null && sem.GetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.GetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.GetMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "property", "getter"); return(JsExpression.Null); } if (sem.SetMethod != null && sem.SetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.SetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.SetMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "property", "setter"); return(JsExpression.Null); } if (sem.GetMethod != null) { properties.Add(new JsObjectLiteralProperty("getter", ConstructMemberInfo(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.GetMethod))); } if (sem.SetMethod != null) { properties.Add(new JsObjectLiteralProperty("setter", ConstructMemberInfo(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.SetMethod))); } break; case PropertyScriptSemantics.ImplType.Field: if (prop.CanGet) { properties.Add(new JsObjectLiteralProperty("getter", ConstructFieldPropertyAccessor(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: true, includeDeclaringType: includeDeclaringType))); } if (prop.CanSet) { properties.Add(new JsObjectLiteralProperty("setter", ConstructFieldPropertyAccessor(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: false, includeDeclaringType: includeDeclaringType))); } properties.Add(new JsObjectLiteralProperty("fname", JsExpression.String(sem.FieldName))); break; default: errorReporter.Message(Messages._7201, m.FullName, "property"); return(JsExpression.Null); } } else if (m is IEvent) { var evt = (IEvent)m; var sem = metadataImporter.GetEventSemantics(evt); if (sem.Type != EventScriptSemantics.ImplType.AddAndRemoveMethods) { errorReporter.Message(Messages._7201, m.FullName, "event"); return(JsExpression.Null); } if (sem.AddMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.AddMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.AddMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "event", "add accessor"); return(JsExpression.Null); } if (sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "event", "remove accessor"); return(JsExpression.Null); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Event))); properties.Add(new JsObjectLiteralProperty("adder", ConstructMemberInfo(evt.AddAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.AddMethod))); properties.Add(new JsObjectLiteralProperty("remover", ConstructMemberInfo(evt.RemoveAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.RemoveMethod))); } else { throw new ArgumentException("Invalid member " + m); } return(JsExpression.ObjectLiteral(properties)); }
public static bool IsJsGeneric(IMethod method, IMetadataImporter metadataImporter) { return(method.TypeParameters.Count > 0 && !metadataImporter.GetMethodSemantics(method).IgnoreGenericArguments); }
public IList <JsStatement> Process(IEnumerable <JsType> types, IMethod entryPoint) { var result = new List <JsStatement>(); var orderedTypes = OrderByNamespace(types, t => _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name).ToList(); foreach (var t in orderedTypes) { try { string name = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name; bool isGlobal = string.IsNullOrEmpty(name); bool isMixin = MetadataUtils.IsMixin(t.CSharpTypeDefinition); result.Add(new JsComment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName)); var typeRef = JsExpression.Identifier(_namer.GetTypeVariableName(name)); if (t is JsClass) { var c = (JsClass)t; if (isGlobal) { result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(GetRoot(t.CSharpTypeDefinition, exportNonPublic: true), m.Name), m.Definition)))); } else if (isMixin) { result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition)))); } else if (MetadataUtils.IsResources(c.CSharpTypeDefinition)) { result.Add(GenerateResourcesClass(c)); } else { var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement); if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) { var typeParameterNames = c.CSharpTypeDefinition.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList(); var stmts = new List <JsStatement> { new JsVariableDeclarationStatement(InstantiatedGenericTypeVariableName, unnamedCtor) }; AddClassMembers(c, JsExpression.Identifier(InstantiatedGenericTypeVariableName), stmts); stmts.AddRange(c.StaticInitStatements); stmts.Add(new JsReturnStatement(JsExpression.Identifier(InstantiatedGenericTypeVariableName))); var replacer = new GenericSimplifier(c.CSharpTypeDefinition, typeParameterNames, JsExpression.Identifier(InstantiatedGenericTypeVariableName)); for (int i = 0; i < stmts.Count; i++) { stmts[i] = replacer.Process(stmts[i]); } result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(typeParameterNames, new JsBlockStatement(stmts)))); var args = new List <JsExpression> { GetRoot(t.CSharpTypeDefinition), JsExpression.String(name), typeRef, JsExpression.Number(c.CSharpTypeDefinition.TypeParameterCount) }; var metadata = GetMetadataDescriptor(t.CSharpTypeDefinition, false); if (metadata != null) { args.Add(metadata); } result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? RegisterGenericInterface : RegisterGenericClass), args))); } else { result.Add(new JsVariableDeclarationStatement(typeRef.Name, unnamedCtor)); AddClassMembers(c, typeRef, result); } } } else if (t is JsEnum) { var e = (JsEnum)t; result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement))); var values = new List <JsObjectLiteralProperty>(); foreach (var v in e.CSharpTypeDefinition.Fields) { if (v.ConstantValue != null) { var sem = _metadataImporter.GetFieldSemantics(v); if (sem.Type == FieldScriptSemantics.ImplType.Field) { values.Add(new JsObjectLiteralProperty(sem.Name, JsExpression.Number(Convert.ToDouble(v.ConstantValue)))); } else if (sem.Type == FieldScriptSemantics.ImplType.Constant && sem.Name != null) { values.Add(new JsObjectLiteralProperty(sem.Name, sem.Value is string?JsExpression.String((string)sem.Value) : JsExpression.Number(Convert.ToDouble(sem.Value)))); } } else { _errorReporter.Region = v.Region; _errorReporter.InternalError("Enum field " + v.FullName + " is not constant."); } } result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, Prototype), JsExpression.ObjectLiteral(values)))); } } catch (Exception ex) { _errorReporter.Region = t.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName); } } var typesToRegister = orderedTypes .Where(c => !(c is JsClass && MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) && !string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name) && (!MetadataUtils.IsResources(c.CSharpTypeDefinition) || c.CSharpTypeDefinition.IsExternallyVisible()) && // Resources classes are only exported if they are public. !MetadataUtils.IsMixin(c.CSharpTypeDefinition)) .ToList(); result.AddRange(TopologicalSortTypesByInheritance(typesToRegister) .Select(c => { try { string name = _metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name; if (c.CSharpTypeDefinition.Kind == TypeKind.Enum) { return(CreateRegisterEnumCall(c.CSharpTypeDefinition, name, JsExpression.Identifier(_namer.GetTypeVariableName(name)))); } if (MetadataUtils.IsResources(c.CSharpTypeDefinition)) { return(JsExpression.Invocation(JsExpression.Member(_systemScript, RegisterType), GetRoot(c.CSharpTypeDefinition), JsExpression.String(name), JsExpression.Identifier(_namer.GetTypeVariableName(name)))); } if (c.CSharpTypeDefinition.Kind == TypeKind.Interface) { return(CreateRegisterInterfaceCall(c.CSharpTypeDefinition, name, JsExpression.Identifier(_namer.GetTypeVariableName(name)), GetImplementedInterfaces(c.CSharpTypeDefinition.GetDefinition()).ToList())); } else { return(CreateRegisterClassCall(c.CSharpTypeDefinition, name, JsExpression.Identifier(_namer.GetTypeVariableName(name)), GetBaseClass(c.CSharpTypeDefinition), GetImplementedInterfaces(c.CSharpTypeDefinition).ToList())); } } catch (Exception ex) { _errorReporter.Region = c.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + c.CSharpTypeDefinition.FullName); return(JsExpression.Number(0)); } }) .Select(expr => new JsExpressionStatement(expr))); result.AddRange(GetStaticInitializationOrder(orderedTypes.OfType <JsClass>(), 1) .Where(c => !MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter) && !MetadataUtils.IsResources(c.CSharpTypeDefinition)) .SelectMany(c => c.StaticInitStatements)); if (entryPoint != null) { if (entryPoint.Parameters.Count > 0) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7800, entryPoint.FullName); } else { var sem = _metadataImporter.GetMethodSemantics(entryPoint); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7801, entryPoint.FullName); } else { result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name)))); } } } return(result); }
private static JsExpression ConstructMemberInfo(IMember m, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func<IType, JsExpression> instantiateType, bool includeDeclaringType, MethodScriptSemantics semanticsIfAccessor) { if (m is IMethod && ((IMethod)m).IsConstructor) return ConstructConstructorInfo((IMethod)m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType); var properties = GetCommonMemberInfoProperties(m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType); if (m.IsStatic) properties.Add(new JsObjectLiteralProperty("isStatic", JsExpression.True)); if (m is IMethod) { var method = (IMethod)m; var sem = semanticsIfAccessor ?? metadataImporter.GetMethodSemantics(method); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7201, m.FullName, "method"); return JsExpression.Null; } if ((sem.Type == MethodScriptSemantics.ImplType.NormalMethod || sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) && sem.ExpandParams) properties.Add(new JsObjectLiteralProperty("exp", JsExpression.True)); properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method))); if (sem.Type == MethodScriptSemantics.ImplType.InlineCode) { var usedNames = new HashSet<string>(); var parameters = new List<IVariable>(); var variables = new Dictionary<IVariable, VariableData>(); var arguments = new List<ResolveResult>(); foreach (var p in method.Parameters) { string name = namer.GetVariableName(p.Name, usedNames); usedNames.Add(name); var variable = new SimpleVariable(p.Type, p.Name, DomRegion.Empty); parameters.Add(variable); variables.Add(variable, new VariableData(name, null, false)); arguments.Add(new LocalResolveResult(variable)); } var tokens = InlineCodeMethodCompiler.Tokenize(method, sem.LiteralCode, _ => {}); var compileResult = Compile(CreateMethodInvocationResolveResult(method, method.IsStatic ? (ResolveResult)new TypeResolveResult(method.DeclaringType) : new ThisResolveResult(method.DeclaringType), arguments), method.DeclaringTypeDefinition, method, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, true, variables, usedNames); var definition = JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), JsStatement.Block(compileResult.AdditionalStatements.Concat(new[] { JsStatement.Return(compileResult.Expression) }))); if (tokens.Any(t => t.Type == InlineCodeToken.TokenType.TypeParameter && t.OwnerType == SymbolKind.Method)) { definition = JsExpression.FunctionDefinition(method.TypeParameters.Select(namer.GetTypeParameterName), JsStatement.Return(definition)); properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count))); } properties.Add(new JsObjectLiteralProperty("def", definition)); } else { if (IsJsGeneric(method, metadataImporter)) { properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count))); } if (sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) { properties.Add(new JsObjectLiteralProperty("sm", JsExpression.True)); } properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(method.ReturnType))); properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(method.Parameters.Select(p => instantiateType(p.Type))))); } else if (m is IField) { var field = (IField)m; var sem = metadataImporter.GetFieldSemantics(field); if (sem.Type != FieldScriptSemantics.ImplType.Field) { errorReporter.Message(Messages._7201, m.FullName, "field"); return JsExpression.Null; } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Field))); properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(field.ReturnType))); properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } else if (m is IProperty) { var prop = (IProperty)m; var sem = metadataImporter.GetPropertySemantics(prop); properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Property))); properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(prop.ReturnType))); if (prop.Parameters.Count > 0) properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(prop.Parameters.Select(p => instantiateType(p.Type))))); switch (sem.Type) { case PropertyScriptSemantics.ImplType.GetAndSetMethods: if (sem.GetMethod != null && sem.GetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.GetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.GetMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "property", "getter"); return JsExpression.Null; } if (sem.SetMethod != null && sem.SetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.SetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.SetMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "property", "setter"); return JsExpression.Null; } if (sem.GetMethod != null) properties.Add(new JsObjectLiteralProperty("getter", ConstructMemberInfo(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.GetMethod))); if (sem.SetMethod != null) properties.Add(new JsObjectLiteralProperty("setter", ConstructMemberInfo(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.SetMethod))); break; case PropertyScriptSemantics.ImplType.Field: if (prop.CanGet) properties.Add(new JsObjectLiteralProperty("getter", ConstructFieldPropertyAccessor(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: true, includeDeclaringType: includeDeclaringType))); if (prop.CanSet) properties.Add(new JsObjectLiteralProperty("setter", ConstructFieldPropertyAccessor(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: false, includeDeclaringType: includeDeclaringType))); properties.Add(new JsObjectLiteralProperty("fname", JsExpression.String(sem.FieldName))); break; default: errorReporter.Message(Messages._7201, m.FullName, "property"); return JsExpression.Null; } } else if (m is IEvent) { var evt = (IEvent)m; var sem = metadataImporter.GetEventSemantics(evt); if (sem.Type != EventScriptSemantics.ImplType.AddAndRemoveMethods) { errorReporter.Message(Messages._7201, m.FullName, "event"); return JsExpression.Null; } if (sem.AddMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.AddMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.AddMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "event", "add accessor"); return JsExpression.Null; } if (sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "event", "remove accessor"); return JsExpression.Null; } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Event))); properties.Add(new JsObjectLiteralProperty("adder", ConstructMemberInfo(evt.AddAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.AddMethod))); properties.Add(new JsObjectLiteralProperty("remover", ConstructMemberInfo(evt.RemoveAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.RemoveMethod))); } else { throw new ArgumentException("Invalid member " + m); } return JsExpression.ObjectLiteral(properties); }
public static bool IsJsGeneric(IMethod method, IMetadataImporter metadataImporter) { return method.TypeParameters.Count > 0 && !metadataImporter.GetMethodSemantics(method).IgnoreGenericArguments; }
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { var resolveResult = _resolver.Resolve(methodDeclaration); if (!(resolveResult is MemberResolveResult)) { _errorReporter.Region = methodDeclaration.GetRegion(); _errorReporter.InternalError("Method declaration " + methodDeclaration.Name + " does not resolve to a member."); return; } var method = ((MemberResolveResult)resolveResult).Member as IMethod; if (method == null) { _errorReporter.Region = methodDeclaration.GetRegion(); _errorReporter.InternalError("Method declaration " + methodDeclaration.Name + " does not resolve to a method (resolves to " + resolveResult.ToString() + ")"); return; } var jsClass = GetJsClass(method.DeclaringTypeDefinition); if (jsClass == null) { return; } if (method.IsAbstract || !methodDeclaration.Body.IsNull) // The second condition is used to ignore partial method parts without definitions. { MaybeCompileAndAddMethodToType(jsClass, methodDeclaration, methodDeclaration.Body, method, _metadataImporter.GetMethodSemantics(method)); } }
public virtual MethodScriptSemantics GetMethodSemantics(IMethod method) { return(_prev.GetMethodSemantics(method)); }
public static JsExpression ResolveTypeParameter(ITypeParameter tp, ITypeDefinition currentType, IMethod currentMethod, IMetadataImporter metadataImporter, IErrorReporter errorReporter, INamer namer) { bool unusable = false; switch (tp.OwnerType) { case EntityType.TypeDefinition: unusable = metadataImporter.GetTypeSemantics(currentType).IgnoreGenericArguments; break; case EntityType.Method: { var sem = metadataImporter.GetMethodSemantics(currentMethod); unusable = sem.Type != MethodScriptSemantics.ImplType.InlineCode && metadataImporter.GetMethodSemantics(currentMethod).IgnoreGenericArguments; break; } default: errorReporter.InternalError("Invalid owner " + tp.OwnerType + " for type parameter " + tp); return JsExpression.Null; } if (unusable) { errorReporter.Message(Messages._7536, tp.Name, tp.OwnerType == EntityType.TypeDefinition ? "type" : "method", tp.OwnerType == EntityType.TypeDefinition ? currentType.FullName : currentMethod.FullName); return JsExpression.Null; } return JsExpression.Identifier(namer.GetTypeParameterName(tp)); }
private MethodScriptSemantics FindMethod(string name) { return(_metadata.GetMethodSemantics(_compilation.FindType(new FullTypeName("C")).GetMethods().Single(p => p.Name == name))); }
public IList <JsStatement> Process(IEnumerable <JsType> types, IMethod entryPoint) { var result = new List <JsStatement>(); var orderedTypes = OrderByNamespace(types, t => _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name).ToList(); var exportedNamespacesByRoot = new Dictionary <string, HashSet <string> >(); foreach (var t in orderedTypes) { try { string name = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name; bool isGlobal = string.IsNullOrEmpty(name); bool isMixin = MetadataUtils.IsMixin(t.CSharpTypeDefinition); bool export = t.CSharpTypeDefinition.IsExternallyVisible(); result.Add(JsStatement.Comment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName)); string typevarName = _namer.GetTypeVariableName(name); if (t is JsClass) { var c = (JsClass)t; if (isGlobal) { result.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(JsExpression.Identifier(GetRoot(t.CSharpTypeDefinition)), m.Name), m.Definition))); export = false; } else if (isMixin) { result.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition))); export = false; } else if (MetadataUtils.IsResources(c.CSharpTypeDefinition)) { result.Add(GenerateResourcesClass(c)); } else { var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock); if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) { var typeParameterNames = c.CSharpTypeDefinition.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList(); var stmts = new List <JsStatement> { JsStatement.Var(InstantiatedGenericTypeVariableName, unnamedCtor) }; AddClassMembers(c, InstantiatedGenericTypeVariableName, stmts); stmts.AddRange(c.StaticInitStatements); stmts.Add(JsStatement.Return(JsExpression.Identifier(InstantiatedGenericTypeVariableName))); var replacer = new GenericSimplifier(c.CSharpTypeDefinition, typeParameterNames, JsExpression.Identifier(InstantiatedGenericTypeVariableName)); for (int i = 0; i < stmts.Count; i++) { stmts[i] = replacer.Process(stmts[i]); } result.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(typeParameterNames, JsStatement.Block(stmts)))); result.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name))); var args = new List <JsExpression> { JsExpression.Identifier(typevarName), JsExpression.Number(c.CSharpTypeDefinition.TypeParameterCount) }; result.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? InitGenericInterface : InitGenericClass), args)); } else { result.Add(JsStatement.Var(typevarName, unnamedCtor)); result.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name))); AddClassMembers(c, typevarName, result); } } } else if (t is JsEnum) { var e = (JsEnum)t; result.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock))); result.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(e.CSharpTypeDefinition).Name))); } if (export) { string root = GetRoot(t.CSharpTypeDefinition); var split = SplitIntoNamespaceAndName(name); if (!string.IsNullOrEmpty(split.Item1)) { HashSet <string> hs; if (!exportedNamespacesByRoot.TryGetValue(root, out hs)) { hs = exportedNamespacesByRoot[root] = new HashSet <string>(); } hs.Add(split.Item1); } result.Add(JsExpression.Assign(MakeNestedMemberAccess(name, JsExpression.Identifier(root)), JsExpression.Identifier(typevarName))); } } catch (Exception ex) { _errorReporter.Region = t.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName); } } result.InsertRange(0, exportedNamespacesByRoot.OrderBy(x => x.Key).SelectMany(x => CreateNamespaces(JsExpression.Identifier(x.Key), x.Value)).ToList()); var typesToRegister = TopologicalSortTypesByInheritance(orderedTypes) .Where(c => !(c is JsClass && MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) && !string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name) && !MetadataUtils.IsResources(c.CSharpTypeDefinition) && !MetadataUtils.IsMixin(c.CSharpTypeDefinition)) .ToList(); foreach (var t in typesToRegister) { try { string name = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name; string typevarName = _namer.GetTypeVariableName(name); if (t.CSharpTypeDefinition.Kind == TypeKind.Enum) { result.Add(CreateInitEnumCall((JsEnum)t, typevarName)); } else { var c = (JsClass)t; if (t.CSharpTypeDefinition.Kind == TypeKind.Interface) { result.Add(CreateInitInterfaceCall(c, typevarName, GetImplementedInterfaces(t.CSharpTypeDefinition.GetDefinition()).ToList())); } else { result.Add(CreateInitClassCall(c, typevarName, GetBaseClass(t.CSharpTypeDefinition), GetImplementedInterfaces(t.CSharpTypeDefinition).ToList())); if (c.NamedConstructors.Count > 0) { result.Add(AssignNamedConstructorPrototypes(c, JsExpression.Identifier(_namer.GetTypeVariableName(name)))); } } } } catch (Exception ex) { _errorReporter.Region = t.CSharpTypeDefinition.Region; _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName); } } foreach (var t in orderedTypes) { var metadata = GetMetadataDescriptor(t.CSharpTypeDefinition, false); if (metadata != null) { result.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, SetMetadata), JsExpression.Identifier(_namer.GetTypeVariableName(_metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name)), metadata)); } } result.AddRange(GetStaticInitializationOrder(orderedTypes.OfType <JsClass>(), 1) .Where(c => !MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter) && !MetadataUtils.IsResources(c.CSharpTypeDefinition)) .SelectMany(c => c.StaticInitStatements)); if (entryPoint != null) { if (entryPoint.Parameters.Count > 0) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7800, entryPoint.FullName); } else { var sem = _metadataImporter.GetMethodSemantics(entryPoint); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod) { _errorReporter.Region = entryPoint.Region; _errorReporter.Message(Messages._7801, entryPoint.FullName); } else { result.Add(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name))); } } } return(result); }