private void BuildCode(IndexerSymbol indexerSymbol)
        {
            if (indexerSymbol.IsAbstract)
            {
                return;
            }

            ImplementationBuilder implBuilder = new ImplementationBuilder(_options, _errorHandler);

            indexerSymbol.AddImplementation(implBuilder.BuildIndexerGetter(indexerSymbol), /* getter */ true);
            _implementations.Add(indexerSymbol.GetterImplementation);

            if (indexerSymbol.IsReadOnly == false)
            {
                indexerSymbol.AddImplementation(implBuilder.BuildPropertySetter(indexerSymbol), /* getter */ false);
                _implementations.Add(indexerSymbol.SetterImplementation);
            }

            if (indexerSymbol.AnonymousMethods != null)
            {
                foreach (AnonymousMethodSymbol anonymousMethod in indexerSymbol.AnonymousMethods)
                {
                    Debug.Assert(anonymousMethod.Implementation != null);

                    _implementations.Add(anonymousMethod.Implementation);
                }
            }
        }
Пример #2
0
        public SymbolImplementation BuildIndexerSetter(IndexerSymbol indexerSymbol)
        {
            AccessorNode       setterNode   = ((IndexerDeclarationNode)indexerSymbol.ParseContext).SetAccessor;
            BlockStatementNode accessorBody = setterNode.Implementation;

            return(BuildImplementation((ISymbolTable)indexerSymbol.Parent,
                                       indexerSymbol, accessorBody, /* addAllParameters */ true));
        }
Пример #3
0
        public IndexerExpression(Expression objectReference, IndexerSymbol indexer)
            : base(ExpressionType.Indexer, indexer.AssociatedType, SymbolFilter.Public | SymbolFilter.InstanceMembers)
        {
            Indexer         = indexer;
            ObjectReference = objectReference;

            indices = new Collection <Expression>();
        }
Пример #4
0
        //TODO: Investigate removing these.
        private void ImportPseudoMembers(PseudoClassMembers memberSet, ClassSymbol classSymbol)
        {
            // Import pseudo members that go on the class but aren't defined in mscorlib.dll
            // These are meant to be used by internal compiler-generated transformations etc.
            // and aren't meant to be referenced directly in C# code.

            if (memberSet == PseudoClassMembers.Script)
            {
                AddScriptSymbolPseudoMembers(classSymbol);

                return;
            }

            if (memberSet == PseudoClassMembers.Arguments)
            {
                TypeSymbol objectType =
                    (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol(nameof(Object), null,
                                                                                   SymbolFilter.Types);
                Debug.Assert(objectType != null);

                IndexerSymbol indexer = new IndexerSymbol(classSymbol, objectType,
                                                          MemberVisibility.Public | MemberVisibility.Static);
                indexer.SetScriptIndexer();
                classSymbol.AddMember(indexer);

                return;
            }

            if (memberSet == PseudoClassMembers.Dictionary)
            {
                TypeSymbol intType =
                    (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol(nameof(Int32), null, SymbolFilter.Types);
                Debug.Assert(intType != null);

                TypeSymbol stringType =
                    (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol(nameof(String), null,
                                                                                   SymbolFilter.Types);
                Debug.Assert(stringType != null);

                // Define Dictionary.Keys
                MethodSymbol getKeysMethod = new MethodSymbol("GetKeys", classSymbol,
                                                              symbols.CreateArrayTypeSymbol(stringType), MemberVisibility.Public | MemberVisibility.Static);
                getKeysMethod.SetTransformName(DSharpStringResources.ScriptExportMember("keys"));
                classSymbol.AddMember(getKeysMethod);

                // Define Dictionary.Values
                MethodSymbol getValuesMethod = new MethodSymbol("GetValues", classSymbol,
                                                                symbols.CreateArrayTypeSymbol(stringType), MemberVisibility.Public | MemberVisibility.Static);
                getValuesMethod.SetTransformName(DSharpStringResources.ScriptExportMember("values"));
                classSymbol.AddMember(getValuesMethod);

                // Define Dictionary.GetCount
                MethodSymbol countMethod = new MethodSymbol("GetKeyCount", classSymbol, intType,
                                                            MemberVisibility.Public | MemberVisibility.Static);
                countMethod.SetTransformName(DSharpStringResources.ScriptExportMember("keyCount"));
                classSymbol.AddMember(countMethod);
            }
        }
Пример #5
0
        public IndexerSymbol CreateIndexer(Name name, ParentSymbol parent, Name realName)
        {
            IndexerSymbol sym = (IndexerSymbol)newBasicSym(SYMKIND.SK_IndexerSymbol, name, parent);

            sym.setKind(SYMKIND.SK_PropertySymbol);
            sym.isOperator = true;

            Debug.Assert(sym != null);
            return(sym);
        }
Пример #6
0
        private ParameterSymbol BuildParameter(ParameterNode parameterNode, IndexerSymbol indexerSymbol)
        {
            TypeSymbol parameterType = indexerSymbol.SymbolSet.ResolveType(parameterNode.Type, _symbolTable, indexerSymbol);

            Debug.Assert(parameterType != null);

            if (parameterType != null)
            {
                return(new ParameterSymbol(parameterNode.Name, indexerSymbol, parameterType, ParameterMode.In));
            }

            return(null);
        }
        public static void GenerateScript(ScriptGenerator generator, IndexerSymbol symbol, bool getter)
        {
            SymbolImplementation accessorImpl;

            if (getter)
            {
                accessorImpl = symbol.GetterImplementation;
            }
            else
            {
                accessorImpl = symbol.SetterImplementation;
            }
            GenerateImplementationScript(generator, symbol, accessorImpl);
        }
Пример #8
0
        private IndexerSymbol BuildIndexer(IndexerDeclarationNode indexerNode, TypeSymbol typeSymbol)
        {
            TypeSymbol indexerType = typeSymbol.SymbolSet.ResolveType(indexerNode.Type, _symbolTable, typeSymbol);

            Debug.Assert(indexerType != null);

            if (indexerType != null)
            {
                IndexerSymbol indexer = new IndexerSymbol(typeSymbol, indexerType);
                BuildMemberDetails(indexer, typeSymbol, indexerNode, indexerNode.Attributes);

                if (AttributeNode.FindAttribute(indexerNode.Attributes, "IntrinsicProperty") != null)
                {
                    indexer.SetIntrinsic();
                }

                SymbolImplementationFlags implFlags = SymbolImplementationFlags.Regular;
                if (indexerNode.SetAccessor == null)
                {
                    implFlags |= SymbolImplementationFlags.ReadOnly;
                }
                if ((indexerNode.Modifiers & Modifiers.Abstract) != 0)
                {
                    implFlags |= SymbolImplementationFlags.Abstract;
                }
                else if ((indexerNode.Modifiers & Modifiers.Override) != 0)
                {
                    implFlags |= SymbolImplementationFlags.Override;
                }

                indexer.SetImplementationState(implFlags);

                Debug.Assert(indexerNode.Parameters.Count != 0);
                foreach (ParameterNode parameterNode in indexerNode.Parameters)
                {
                    ParameterSymbol paramSymbol = BuildParameter(parameterNode, indexer);
                    if (paramSymbol != null)
                    {
                        paramSymbol.SetParseContext(parameterNode);
                        indexer.AddParameter(paramSymbol);
                    }
                }

                indexer.AddParameter(new ParameterSymbol("value", indexer, indexerType, ParameterMode.In));

                return(indexer);
            }

            return(null);
        }
        private static void GenerateIndexerComment(ScriptTextWriter writer, IndexerSymbol indexerSymbol)
        {
            GenerateSummaryComment(writer, indexerSymbol);

            if (indexerSymbol.Parameters != null)
            {
                foreach (ParameterSymbol parameterSymbol in indexerSymbol.Parameters)
                {
                    GenerateParameterComment(writer, parameterSymbol);
                }
            }

            GenerateReturnsComment(writer, indexerSymbol.AssociatedType);
        }
Пример #10
0
 private bool Equals(IndexerSymbol other)
 {
     return(base.Equals(other) && IndexType.Equals(other.IndexType) && ValueType.Equals(other.ValueType) && ReadOnly == other.ReadOnly);
 }
Пример #11
0
        protected Symbol newBasicSym(
            SYMKIND kind,
            Name name,
            ParentSymbol parent)
        {
            // The parser creates names with PN_MISSING when attempting to recover from errors
            // To prevent spurious errors, we create SYMs with a different name (PN_MISSINGSYM)
            // so that they are never found when doing lookup.
            if (name == m_pMissingNameNode)
            {
                name = m_pMissingNameSym;
            }

            Symbol sym;
            switch (kind)
            {
                case SYMKIND.SK_NamespaceSymbol:
                    sym = new NamespaceSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_NamespaceDeclaration:
                    sym = new NamespaceDeclaration();
                    sym.name = name;
                    break;
                case SYMKIND.SK_AssemblyQualifiedNamespaceSymbol:
                    sym = new AssemblyQualifiedNamespaceSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_AggregateSymbol:
                    sym = new AggregateSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_AggregateDeclaration:
                    sym = new AggregateDeclaration();
                    sym.name = name;
                    break;
                case SYMKIND.SK_TypeParameterSymbol:
                    sym = new TypeParameterSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_FieldSymbol:
                    sym = new FieldSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_LocalVariableSymbol:
                    sym = new LocalVariableSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_MethodSymbol:
                    sym = new MethodSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_PropertySymbol:
                    sym = new PropertySymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_EventSymbol:
                    sym = new EventSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_TransparentIdentifierMemberSymbol:
                    sym = new TransparentIdentifierMemberSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_Scope:
                    sym = new Scope();
                    sym.name = name;
                    break;
                case SYMKIND.SK_LabelSymbol:
                    sym = new LabelSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_GlobalAttributeDeclaration:
                    sym = new GlobalAttributeDeclaration();
                    sym.name = name;
                    break;
                case SYMKIND.SK_UnresolvedAggregateSymbol:
                    sym = new UnresolvedAggregateSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_InterfaceImplementationMethodSymbol:
                    sym = new InterfaceImplementationMethodSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_IndexerSymbol:
                    sym = new IndexerSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_ParentSymbol:
                    sym = new ParentSymbol();
                    sym.name = name;
                    break;
                case SYMKIND.SK_IteratorFinallyMethodSymbol:
                    sym = new IteratorFinallyMethodSymbol();
                    sym.name = name;
                    break;
                default:
                    throw Error.InternalCompilerError();
            }

            sym.setKind(kind);

            if (parent != null)
            {
                // Set the parent element of the child symbol.
                parent.AddToChildList(sym);
                m_pSymTable.InsertChild(parent, sym);
            }

            return (sym);
        }
Пример #12
0
 private void ErrAppendIndexer(IndexerSymbol indexer, SubstContext pctx)
 {
     ErrAppendString("this[");
     ErrAppendParamList(GetTypeManager().SubstTypeArray(indexer.Params, pctx), false, indexer.isParamArray);
     ErrAppendChar(']');
 }
Пример #13
0
        private static void GenerateBinaryExpression(ScriptGenerator generator, MemberSymbol symbol,
                                                     BinaryExpression expression)
        {
            ScriptTextWriter writer = generator.Writer;

            if (expression.Operator == Operator.Equals)
            {
                if (expression.LeftOperand is PropertyExpression propExpression)
                {
                    Debug.Assert(propExpression.Type == ExpressionType.PropertySet);

                    if (propExpression.ObjectReference is BaseExpression)
                    {
                        ClassSymbol classSymbol = (ClassSymbol)symbol.Parent;
                        writer.Write($"{DSharpStringResources.ScriptExportMember("baseProperty")}(");
                        writer.Write(classSymbol.FullGeneratedName);
                        writer.Write(", '");
                        writer.Write(propExpression.Property.GeneratedName);
                        writer.Write("').set.call(");
                        writer.Write(generator.CurrentImplementation.ThisIdentifier);
                        writer.Write(", ");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                        writer.Write(")");
                    }
                    else
                    {
                        GenerateExpression(generator, symbol, propExpression.ObjectReference);
                        writer.Write(".");
                        writer.Write(propExpression.Property.GeneratedName);
                        writer.Write(" = ");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                    }

                    propExpression.Property.IncrementReferenceCount();
                    return;
                }

                if (expression.LeftOperand is IndexerExpression indexExpression)
                {
                    IndexerSymbol indexerSymbol = indexExpression.Indexer;

                    if (!indexerSymbol.UseScriptIndexer)
                    {
                        Debug.Assert(indexExpression.Type == ExpressionType.Indexer);

                        if (indexExpression.ObjectReference is BaseExpression objectReference)
                        {
                            writer.Write(objectReference.EvaluatedType.FullGeneratedName);
                            writer.Write(".prototype.set_");
                            writer.Write(indexerSymbol.GeneratedName);
                            writer.Write(".call(");
                            writer.Write(generator.CurrentImplementation.ThisIdentifier);
                            writer.Write(", ");
                            GenerateExpressionList(generator, symbol, indexExpression.Indices);
                            writer.Write(", ");
                            GenerateExpression(generator, symbol, expression.RightOperand);
                            writer.Write(")");
                        }
                        else
                        {
                            GenerateExpression(generator, symbol, indexExpression.ObjectReference);
                            writer.Write(".set_");
                            writer.Write(indexerSymbol.GeneratedName);
                            writer.Write("(");
                            GenerateExpressionList(generator, symbol, indexExpression.Indices);
                            writer.Write(", ");
                            GenerateExpression(generator, symbol, expression.RightOperand);
                            writer.Write(")");
                        }

                        indexExpression.Indexer.IncrementReferenceCount();
                        return;
                    }
                    else if (indexerSymbol.Parent is TypeSymbol typeSymbol && !typeSymbol.IsNativeArray)
                    {
                        writer.Write($"ss.setItem(");
                        GenerateExpression(generator, symbol, indexExpression.ObjectReference);
                        writer.Write(", ");
                        GenerateExpressionList(generator, symbol, indexExpression.Indices);
                        writer.Write(", ");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                        writer.Write(")");

                        return;
                    }
                }
            }
            else if (expression.Operator == Operator.PlusEquals ||
                     expression.Operator == Operator.MinusEquals ||
                     expression.Operator == Operator.MultiplyEquals ||
                     expression.Operator == Operator.DivideEquals ||
                     expression.Operator == Operator.ModEquals ||
                     expression.Operator == Operator.BitwiseOrEquals ||
                     expression.Operator == Operator.BitwiseAndEquals ||
                     expression.Operator == Operator.BitwiseXorEquals ||
                     expression.Operator == Operator.ShiftLeftEquals ||
                     expression.Operator == Operator.ShiftRightEquals ||
                     expression.Operator == Operator.UnsignedShiftRightEquals)
            {
                if (expression.LeftOperand is PropertyExpression propExpression)
                {
                    Debug.Assert(propExpression.Type == ExpressionType.PropertyGet);

                    GenerateExpression(generator, symbol, propExpression.ObjectReference);
                    writer.Write(".");
                    writer.Write(propExpression.Property.GeneratedName);
                    writer.Write(" = ");
                    GenerateExpression(generator, symbol, propExpression.ObjectReference);
                    writer.Write(OperatorConverter.OperatorToString(expression.Operator - 1));
                    GenerateExpression(generator, symbol, expression.RightOperand);

                    propExpression.Property.IncrementReferenceCount();
                    return;
                }
            }
            else if (expression.Operator == Operator.Is ||
                     expression.Operator == Operator.As)
            {
                TypeExpression typeExpression = expression.RightOperand as TypeExpression;
                Debug.Assert(typeExpression != null);

                writer.Write(DSharpStringResources.ScriptExportMember(string.Empty));

                if (expression.Operator == Operator.Is)
                {
                    writer.Write("canCast(");
                }
                else
                {
                    writer.Write("safeCast(");
                }

                GenerateExpression(generator, symbol, expression.LeftOperand);

                writer.Write(", ");
                writer.Write(typeExpression.AssociatedType.FullGeneratedName);
                writer.Write(")");
                typeExpression.AssociatedType.IncrementReferenceCount();
                return;
            }
            else if (expression.Operator == Operator.EqualEqualEqual ||
                     expression.Operator == Operator.NotEqualEqual)
            {
                if (expression.RightOperand is LiteralExpression literalExpression)
                {
                    // Optimize generated script to perform loose equality checks for false-y values
                    // (null, false, 0, empty string)

                    // TODO: This should really be happening at compilation time, rather than generation
                    //       time. Because this is happening at generation time, we get something like
                    //       if (!!x) when if(x) would suffice just so we can get
                    //       foo(!!x) where foo is a method expecting a boolean.
                    //       Doing this at compilation time would allow handling if scenarios specially.

                    bool optimizable   = false;
                    bool checkForFalse = false;

                    if (literalExpression.Value is bool compareValue)
                    {
                        optimizable = true;

                        if (compareValue && expression.Operator == Operator.NotEqualEqual ||
                            !compareValue && expression.Operator == Operator.EqualEqualEqual)
                        {
                            checkForFalse = true;
                        }
                    }
                    else if (literalExpression.Value is int i && i == 0)
                    {
                        optimizable   = true;
                        checkForFalse = expression.Operator == Operator.EqualEqualEqual;
                    }
                    else if (literalExpression.Value is string s && s == string.Empty)
                    {
                        optimizable   = true;
                        checkForFalse = expression.Operator == Operator.EqualEqualEqual;
                    }

                    if (optimizable)
                    {
                        bool parenthesize = false;

                        writer.Write(checkForFalse ? "!" : "!!");

                        if (expression.LeftOperand.Parenthesized == false &&
                            (expression.LeftOperand.Type == ExpressionType.Binary ||
                             expression.LeftOperand.Type == ExpressionType.Conditional ||
                             expression.LeftOperand.Type == ExpressionType.InlineScript))
                        {
                            parenthesize = true;
                            writer.Write("(");
                        }

                        GenerateExpression(generator, symbol, expression.LeftOperand);

                        if (parenthesize)
                        {
                            writer.Write(")");
                        }

                        return;
                    }
                }
            }
Пример #14
0
 protected void ErrAppendIndexer(IndexerSymbol indexer, SubstContext pctx)
 {
     ErrAppendString("this[");
     ErrAppendParamList(GetTypeManager().SubstTypeArray(indexer.Params, pctx), false, indexer.isParamArray);
     ErrAppendChar(']');
 }
Пример #15
0
        private static void GenerateBinaryExpression(ScriptGenerator generator, MemberSymbol symbol, BinaryExpression expression)
        {
            ScriptTextWriter writer = generator.Writer;

            if (expression.Operator == Operator.Equals)
            {
                PropertyExpression propExpression = expression.LeftOperand as PropertyExpression;
                if (propExpression != null)
                {
                    Debug.Assert(propExpression.Type == ExpressionType.PropertySet);

                    if (propExpression.ObjectReference is BaseExpression)
                    {
                        Debug.Assert(symbol.Parent is ClassSymbol);

                        writer.Write(((ClassSymbol)symbol.Parent).FullGeneratedName);
                        writer.Write(".callBaseMethod(this, 'set_");
                        writer.Write(propExpression.Property.GeneratedName);
                        writer.Write("',");
                        writer.WriteTrimmed(" [ ");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                        writer.WriteTrimmed(" ])");
                    }
                    else
                    {
                        GenerateExpression(generator, symbol, propExpression.ObjectReference);
                        writer.Write(".set_");
                        writer.Write(propExpression.Property.GeneratedName);
                        writer.Write("(");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                        writer.Write(")");
                    }

                    return;
                }

                IndexerExpression indexExpression = expression.LeftOperand as IndexerExpression;
                if ((indexExpression != null) &&
                    !indexExpression.Indexer.IsIntrinsic)
                {
                    Debug.Assert(indexExpression.Type == ExpressionType.Indexer);

                    if (indexExpression.ObjectReference is BaseExpression)
                    {
                        Debug.Assert(symbol.Parent is ClassSymbol);

                        writer.Write(((ClassSymbol)symbol.Parent).FullGeneratedName);
                        writer.Write(".callBaseMethod(this, 'set_");
                        writer.Write(indexExpression.Indexer.GeneratedName);
                        writer.Write("',");
                        writer.WriteTrimmed(" [ ");
                        GenerateExpressionList(generator, symbol, indexExpression.Indices);
                        writer.WriteTrimmed(", ");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                        writer.WriteTrimmed(" ])");
                    }
                    else
                    {
                        IndexerSymbol indexerSymbol = indexExpression.Indexer;

                        GenerateExpression(generator, symbol, indexExpression.ObjectReference);
                        writer.Write(".set_");
                        writer.Write(indexerSymbol.GeneratedName);
                        writer.Write("(");
                        GenerateExpressionList(generator, symbol, indexExpression.Indices);
                        writer.WriteTrimmed(", ");
                        GenerateExpression(generator, symbol, expression.RightOperand);
                        writer.Write(")");
                    }

                    return;
                }
            }
            else if ((expression.Operator == Operator.PlusEquals) ||
                     (expression.Operator == Operator.MinusEquals) ||
                     (expression.Operator == Operator.MultiplyEquals) ||
                     (expression.Operator == Operator.DivideEquals) ||
                     (expression.Operator == Operator.ModEquals) ||
                     (expression.Operator == Operator.BitwiseOrEquals) ||
                     (expression.Operator == Operator.BitwiseAndEquals) ||
                     (expression.Operator == Operator.BitwiseXorEquals) ||
                     (expression.Operator == Operator.ShiftLeftEquals) ||
                     (expression.Operator == Operator.ShiftRightEquals) ||
                     (expression.Operator == Operator.UnsignedShiftRightEquals))
            {
                PropertyExpression propExpression = expression.LeftOperand as PropertyExpression;
                if (propExpression != null)
                {
                    Debug.Assert(propExpression.Type == ExpressionType.PropertyGet);

                    GenerateExpression(generator, symbol, propExpression.ObjectReference);
                    writer.Write(".set_");
                    writer.Write(propExpression.Property.GeneratedName);
                    writer.Write("(");
                    GenerateExpression(generator, symbol, propExpression.ObjectReference);
                    writer.Write(".get_");
                    writer.Write(propExpression.Property.GeneratedName);
                    writer.WriteTrimmed("()");
                    writer.WriteTrimmed(OperatorConverter.OperatorToString(expression.Operator - 1));
                    GenerateExpression(generator, symbol, expression.RightOperand);
                    writer.Write(")");

                    return;
                }
            }
            else if ((expression.Operator == Operator.Is) ||
                     (expression.Operator == Operator.As))
            {
                TypeExpression typeExpression = expression.RightOperand as TypeExpression;
                Debug.Assert(typeExpression != null);

                writer.Write("Type.");
                if (expression.Operator == Operator.Is)
                {
                    writer.Write("canCast(");
                }
                else
                {
                    writer.Write("safeCast(");
                }

                GenerateExpression(generator, symbol, expression.LeftOperand);

                writer.WriteTrimmed(", ");
                writer.Write(typeExpression.AssociatedType.FullGeneratedName);
                writer.Write(")");

                return;
            }
            else if ((expression.Operator == Operator.EqualEqualEqual) ||
                     (expression.Operator == Operator.NotEqualEqual))
            {
                LiteralExpression literalExpression = expression.RightOperand as LiteralExpression;
                if (literalExpression != null)
                {
                    // Optimize generated script to perform loose equality checks for false-y values
                    // (null, false, 0, empty string)

                    // TODO: This should really be happening at compilation time, rather than generation
                    //       time. Because this is happening at generation time, we get something like
                    //       if (!!x) when if(x) would suffice just so we can get
                    //       foo(!!x) where foo is a method expecting a boolean.
                    //       Doing this at compilation time would allow handling if scenarios specially.

                    bool optimizable   = false;
                    bool checkForFalse = false;

                    if (literalExpression.Value is bool)
                    {
                        optimizable = true;

                        bool compareValue = (bool)literalExpression.Value;
                        if ((compareValue && (expression.Operator == Operator.NotEqualEqual)) ||
                            (!compareValue && (expression.Operator == Operator.EqualEqualEqual)))
                        {
                            checkForFalse = true;
                        }
                    }
                    else if ((literalExpression.Value is int) && (((int)literalExpression.Value) == 0))
                    {
                        optimizable   = true;
                        checkForFalse = (expression.Operator == Operator.EqualEqualEqual);
                    }
                    else if ((literalExpression.Value is string) && ((string)literalExpression.Value == String.Empty))
                    {
                        optimizable   = true;
                        checkForFalse = (expression.Operator == Operator.EqualEqualEqual);
                    }

                    if (optimizable)
                    {
                        bool parenthesize = false;

                        writer.Write(checkForFalse ? "!" : "!!");
                        if ((expression.LeftOperand.Parenthesized == false) &&
                            ((expression.LeftOperand.Type == ExpressionType.Binary) ||
                             (expression.LeftOperand.Type == ExpressionType.Conditional) ||
                             (expression.LeftOperand.Type == ExpressionType.InlineScript)))
                        {
                            parenthesize = true;
                            writer.Write("(");
                        }
                        GenerateExpression(generator, symbol, expression.LeftOperand);
                        if (parenthesize)
                        {
                            writer.Write(")");
                        }
                        return;
                    }
                }
            }

            GenerateExpression(generator, symbol, expression.LeftOperand);
            writer.WriteTrimmed(OperatorConverter.OperatorToString(expression.Operator));
            GenerateExpression(generator, symbol, expression.RightOperand);
        }
Пример #16
0
        private void ImportPseudoMembers(PseudoClassMembers memberSet, ClassSymbol classSymbol)
        {
            // Import pseudo members that go on the class but aren't defined in mscorlib.dll
            // These are meant to be used by internal compiler-generated transformations etc.
            // and aren't meant to be referenced directly in C# code.

            if (memberSet == PseudoClassMembers.Script)
            {
                TypeSymbol boolType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Boolean", null, SymbolFilter.Types);
                Debug.Assert(boolType != null);

                TypeSymbol intType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Int32", null, SymbolFilter.Types);
                Debug.Assert(intType != null);

                TypeSymbol floatType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Single", null, SymbolFilter.Types);
                Debug.Assert(floatType != null);

                TypeSymbol stringType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("String", null, SymbolFilter.Types);
                Debug.Assert(stringType != null);

                // Define the Escape, Unescape, encodeURI, decodeURI, encodeURIComponent, decodeURIComponent methods
                MethodSymbol escapeMethod = new MethodSymbol("Escape", classSymbol, stringType, MemberVisibility.Public | MemberVisibility.Static);
                classSymbol.AddMember(escapeMethod);

                MethodSymbol unescapeMethod = new MethodSymbol("Unescape", classSymbol, stringType, MemberVisibility.Public | MemberVisibility.Static);
                classSymbol.AddMember(unescapeMethod);

                MethodSymbol encodeURIMethod = new MethodSymbol("EncodeUri", classSymbol, stringType, MemberVisibility.Public | MemberVisibility.Static);
                encodeURIMethod.SetTransformedName("encodeURI");
                classSymbol.AddMember(encodeURIMethod);

                MethodSymbol decodeURIMethod = new MethodSymbol("DecodeUri", classSymbol, stringType, MemberVisibility.Public | MemberVisibility.Static);
                decodeURIMethod.SetTransformedName("decodeURI");
                classSymbol.AddMember(decodeURIMethod);

                MethodSymbol encodeURIComponentMethod = new MethodSymbol("EncodeUriComponent", classSymbol, stringType, MemberVisibility.Public | MemberVisibility.Static);
                encodeURIComponentMethod.SetTransformedName("encodeURIComponent");
                classSymbol.AddMember(encodeURIComponentMethod);

                MethodSymbol decodeURIComponentMethod = new MethodSymbol("DecodeUriComponent", classSymbol, stringType, MemberVisibility.Public | MemberVisibility.Static);
                decodeURIComponentMethod.SetTransformedName("decodeURIComponent");
                classSymbol.AddMember(decodeURIComponentMethod);

                return;
            }

            if (memberSet == PseudoClassMembers.Arguments)
            {
                TypeSymbol objectType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Object", null, SymbolFilter.Types);
                Debug.Assert(objectType != null);

                IndexerSymbol indexer = new IndexerSymbol(classSymbol, objectType, MemberVisibility.Public | MemberVisibility.Static);
                indexer.SetIntrinsic();
                classSymbol.AddMember(indexer);

                return;
            }

            if (memberSet == PseudoClassMembers.Type)
            {
                // Define the Type.GetInstanceType static method which provides the functionality of
                // Object.GetType instance method. We don't extend Object.prototype in script to add
                // GetType, since we want to keep Object's protoype clean of any extensions.
                //
                // We create this symbol here, so that later the ExpressionBuilder can transform
                // calls to Object.GetType to this.
                TypeSymbol objectType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Object", null, SymbolFilter.Types);
                Debug.Assert(objectType != null);

                TypeSymbol typeType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Type", null, SymbolFilter.Types);
                Debug.Assert(objectType != null);

                MethodSymbol getTypeMethod = new MethodSymbol("GetInstanceType", classSymbol, typeType, MemberVisibility.Public | MemberVisibility.Static);
                getTypeMethod.AddParameter(new ParameterSymbol("instance", getTypeMethod, objectType, ParameterMode.In));
                classSymbol.AddMember(getTypeMethod);

                return;
            }

            if (memberSet == PseudoClassMembers.Dictionary)
            {
                TypeSymbol intType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Int32", null, SymbolFilter.Types);
                Debug.Assert(intType != null);

                TypeSymbol boolType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Boolean", null, SymbolFilter.Types);
                Debug.Assert(boolType != null);

                TypeSymbol voidType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Void", null, SymbolFilter.Types);
                Debug.Assert(boolType != null);

                TypeSymbol stringType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("String", null, SymbolFilter.Types);
                Debug.Assert(boolType != null);

                // Define Dictionary.Keys
                MethodSymbol getKeysMethod = new MethodSymbol("GetKeys", classSymbol, _symbols.CreateArrayTypeSymbol(stringType), MemberVisibility.Public | MemberVisibility.Static);
                getKeysMethod.SetTransformedName("keys");
                classSymbol.AddMember(getKeysMethod);

                // Define Dictionary.GetCount
                MethodSymbol countMethod = new MethodSymbol("GetKeyCount", classSymbol, intType, MemberVisibility.Public | MemberVisibility.Static);
                classSymbol.AddMember(countMethod);

                // Define Dictionary.ClearKeys
                MethodSymbol clearMethod = new MethodSymbol("ClearKeys", classSymbol, voidType, MemberVisibility.Public | MemberVisibility.Static);
                classSymbol.AddMember(clearMethod);

                // Define Dictionary.DeleteKey
                MethodSymbol deleteMethod = new MethodSymbol("DeleteKey", classSymbol, voidType, MemberVisibility.Public | MemberVisibility.Static);
                classSymbol.AddMember(deleteMethod);

                // Define Dictionary.KeyExists
                MethodSymbol existsMethod = new MethodSymbol("KeyExists", classSymbol, boolType, MemberVisibility.Public | MemberVisibility.Static);
                classSymbol.AddMember(existsMethod);

                return;
            }

            if (memberSet == PseudoClassMembers.String)
            {
                // In script, String.replace replaces only the first occurrence of a string
                // whereas in C# all occurrences are replaced.
                // Replace becomes replaceAll (a method we add) in generated script
                // ReplaceFirst becomes replace in generated script.
                // ReplaceRegex also becomes replace in generated script. (We added ReplaceRegex so
                //   it could be mapped to the native replace method, rather than out replaceAll
                //   extension)

                MethodSymbol replaceFirstMethod = (MethodSymbol)classSymbol.GetMember("ReplaceFirst");
                Debug.Assert(replaceFirstMethod != null);
                replaceFirstMethod.SetTransformedName("replace");

                MethodSymbol replaceMethod = (MethodSymbol)classSymbol.GetMember("Replace");
                Debug.Assert(replaceMethod != null);
                replaceMethod.SetTransformedName("replaceAll");

                MethodSymbol replaceRegexMethod = (MethodSymbol)classSymbol.GetMember("ReplaceRegex");
                Debug.Assert(replaceRegexMethod != null);
                replaceRegexMethod.SetTransformedName("replace");
            }
        }
Пример #17
0
        private void ImportProperties(TypeSymbol typeSymbol)
        {
            TypeDefinition type = (TypeDefinition)typeSymbol.MetadataReference;

            foreach (PropertyDefinition property in type.Properties)
            {
                if (property.IsSpecialName)
                {
                    continue;
                }

                if (property.GetMethod == null)
                {
                    continue;
                }

                if (property.GetMethod.IsPrivate || property.GetMethod.IsAssembly ||
                    property.GetMethod.IsFamilyAndAssembly)
                {
                    continue;
                }

                string propertyName = property.Name;
                bool   scriptField  = MetadataHelpers.ShouldTreatAsScriptField(property);

                // TODO: Why are we ignoring the other bits...
                // bool dummyPreserveName;
                // bool preserveCase;
                // string dummyName = MetadataHelpers.GetScriptName(property, out dummyPreserveName, out preserveCase);

                TypeSymbol propertyType = ResolveType(property.PropertyType);

                if (propertyType == null)
                {
                    continue;
                }

                PropertySymbol propertySymbol = null;

                if (property.Parameters.Count != 0)
                {
                    IndexerSymbol indexerSymbol = new IndexerSymbol(typeSymbol, propertyType);
                    ImportMemberDetails(indexerSymbol, property.GetMethod, property);

                    if (scriptField)
                    {
                        indexerSymbol.SetScriptIndexer();
                    }

                    propertySymbol = indexerSymbol;
                    // propertySymbol.SetNameCasing(preserveCase);
                }
                else
                {
                    if (scriptField)
                    {
                        // Properties marked with this attribute are to be thought of as
                        // fields. If they are read-only, the C# compiler will enforce that,
                        // so we don't have to worry about making them read-write via a field
                        // instead of a property

                        FieldSymbol fieldSymbol = new FieldSymbol(propertyName, typeSymbol, propertyType);
                        ImportMemberDetails(fieldSymbol, property.GetMethod, property);

                        string transformedName = MetadataHelpers.GetTransformedName(property);

                        if (string.IsNullOrEmpty(transformedName) == false)
                        {
                            fieldSymbol.SetTransformName(transformedName);
                        }

                        typeSymbol.AddMember(fieldSymbol);
                    }
                    else
                    {
                        propertySymbol = new PropertySymbol(propertyName, typeSymbol, propertyType);
                        ImportMemberDetails(propertySymbol, property.GetMethod, property);
                        propertySymbol.SetNameCasing(true);

                        string transformedName = MetadataHelpers.GetTransformedName(property.GetMethod);

                        if (string.IsNullOrEmpty(transformedName) == false)
                        {
                            propertySymbol.SetTransformedName(transformedName);
                        }
                    }
                }

                if (propertySymbol != null)
                {
                    SymbolImplementationFlags implFlags = SymbolImplementationFlags.Regular;

                    if (property.SetMethod == null)
                    {
                        implFlags |= SymbolImplementationFlags.ReadOnly;
                    }

                    if (property.GetMethod.IsAbstract)
                    {
                        implFlags |= SymbolImplementationFlags.Abstract;
                    }

                    propertySymbol.SetImplementationState(implFlags);

                    typeSymbol.AddMember(propertySymbol);
                }
            }
        }
Пример #18
0
 public BoundElementAccessExpression(ElementAccessExpressionSyntax syntax, BoundExpression expression, BoundExpression index, IndexerSymbol indexer)
     : base(BoundNodeKind.ElementAccessExpression, syntax)
 {
     Expression = expression;
     Index      = index;
     Type       = indexer.AssociatedType;
 }
Пример #19
0
        private Symbol NewBasicSymbol(
            SYMKIND kind,
            Name name,
            ParentSymbol parent)
        {
            Symbol sym;

            switch (kind)
            {
            case SYMKIND.SK_NamespaceSymbol:
                sym      = new NamespaceSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_AggregateSymbol:
                sym      = new AggregateSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_AggregateDeclaration:
                sym      = new AggregateDeclaration();
                sym.name = name;
                break;

            case SYMKIND.SK_TypeParameterSymbol:
                sym      = new TypeParameterSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_FieldSymbol:
                sym      = new FieldSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_LocalVariableSymbol:
                sym      = new LocalVariableSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_MethodSymbol:
                sym      = new MethodSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_PropertySymbol:
                sym      = new PropertySymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_EventSymbol:
                sym      = new EventSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_Scope:
                sym      = new Scope();
                sym.name = name;
                break;

            case SYMKIND.SK_IndexerSymbol:
                sym      = new IndexerSymbol();
                sym.name = name;
                break;

            default:
                throw Error.InternalCompilerError();
            }

            sym.setKind(kind);

            if (parent != null)
            {
                // Set the parent element of the child symbol.
                parent.AddToChildList(sym);
                _symbolTable.InsertChild(parent, sym);
            }

            return(sym);
        }
Пример #20
0
        private void ImportPseudoMembers(PseudoClassMembers memberSet, ClassSymbol classSymbol)
        {
            // Import pseudo members that go on the class but aren't defined in mscorlib.dll
            // These are meant to be used by internal compiler-generated transformations etc.
            // and aren't meant to be referenced directly in C# code.

            if (memberSet == PseudoClassMembers.Script)
            {
                TypeSymbol objectType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Object", null, SymbolFilter.Types);
                Debug.Assert(objectType != null);

                TypeSymbol stringType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("String", null, SymbolFilter.Types);
                Debug.Assert(stringType != null);

                TypeSymbol boolType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Boolean", null, SymbolFilter.Types);
                Debug.Assert(boolType != null);

                TypeSymbol dateType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Date", null, SymbolFilter.Types);
                Debug.Assert(dateType != null);

                // Enumerate - IEnumerable.GetEnumerator gets mapped to this

                MethodSymbol enumerateMethod = new MethodSymbol("Enumerate", classSymbol, objectType, MemberVisibility.Public | MemberVisibility.Static);
                enumerateMethod.SetAlias("ss.enumerate");
                enumerateMethod.AddParameter(new ParameterSymbol("obj", enumerateMethod, objectType, ParameterMode.In));
                classSymbol.AddMember(enumerateMethod);

                // TypeName - Type.Name gets mapped to this

                MethodSymbol typeNameMethod = new MethodSymbol("GetTypeName", classSymbol, stringType, MemberVisibility.Public | MemberVisibility.Static);
                typeNameMethod.SetAlias("ss.typeName");
                typeNameMethod.AddParameter(new ParameterSymbol("obj", typeNameMethod, objectType, ParameterMode.In));
                classSymbol.AddMember(typeNameMethod);

                // CompareDates - Date equality checks get converted to call to compareDates

                MethodSymbol compareDatesMethod = new MethodSymbol("CompareDates", classSymbol, boolType, MemberVisibility.Public | MemberVisibility.Static);
                compareDatesMethod.SetAlias("ss.compareDates");
                compareDatesMethod.AddParameter(new ParameterSymbol("d1", compareDatesMethod, dateType, ParameterMode.In));
                compareDatesMethod.AddParameter(new ParameterSymbol("d2", compareDatesMethod, dateType, ParameterMode.In));
                classSymbol.AddMember(compareDatesMethod);

                return;
            }

            if (memberSet == PseudoClassMembers.Arguments)
            {
                TypeSymbol objectType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Object", null, SymbolFilter.Types);
                Debug.Assert(objectType != null);

                IndexerSymbol indexer = new IndexerSymbol(classSymbol, objectType, MemberVisibility.Public | MemberVisibility.Static);
                indexer.SetScriptIndexer();
                classSymbol.AddMember(indexer);

                return;
            }

            if (memberSet == PseudoClassMembers.Dictionary)
            {
                TypeSymbol intType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("Int32", null, SymbolFilter.Types);
                Debug.Assert(intType != null);

                TypeSymbol stringType = (TypeSymbol)((ISymbolTable)_symbols.SystemNamespace).FindSymbol("String", null, SymbolFilter.Types);
                Debug.Assert(stringType != null);

                // Define Dictionary.Keys
                MethodSymbol getKeysMethod = new MethodSymbol("GetKeys", classSymbol, _symbols.CreateArrayTypeSymbol(stringType), MemberVisibility.Public | MemberVisibility.Static);
                getKeysMethod.SetAlias("ss.keys");
                classSymbol.AddMember(getKeysMethod);

                // Define Dictionary.GetCount
                MethodSymbol countMethod = new MethodSymbol("GetKeyCount", classSymbol, intType, MemberVisibility.Public | MemberVisibility.Static);
                countMethod.SetAlias("ss.keyCount");
                classSymbol.AddMember(countMethod);

                return;
            }
        }
Пример #21
0
        protected Symbol newBasicSym(
            SYMKIND kind,
            Name name,
            ParentSymbol parent)
        {
            // The parser creates names with PN_MISSING when attempting to recover from errors
            // To prevent spurious errors, we create SYMs with a different name (PN_MISSINGSYM)
            // so that they are never found when doing lookup.
            if (name == m_pMissingNameNode)
            {
                name = m_pMissingNameSym;
            }

            Symbol sym;

            switch (kind)
            {
            case SYMKIND.SK_NamespaceSymbol:
                sym      = new NamespaceSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_NamespaceDeclaration:
                sym      = new NamespaceDeclaration();
                sym.name = name;
                break;

            case SYMKIND.SK_AssemblyQualifiedNamespaceSymbol:
                sym      = new AssemblyQualifiedNamespaceSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_AggregateSymbol:
                sym      = new AggregateSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_AggregateDeclaration:
                sym      = new AggregateDeclaration();
                sym.name = name;
                break;

            case SYMKIND.SK_TypeParameterSymbol:
                sym      = new TypeParameterSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_FieldSymbol:
                sym      = new FieldSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_LocalVariableSymbol:
                sym      = new LocalVariableSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_MethodSymbol:
                sym      = new MethodSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_PropertySymbol:
                sym      = new PropertySymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_EventSymbol:
                sym      = new EventSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_TransparentIdentifierMemberSymbol:
                sym      = new TransparentIdentifierMemberSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_Scope:
                sym      = new Scope();
                sym.name = name;
                break;

            case SYMKIND.SK_LabelSymbol:
                sym      = new LabelSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_GlobalAttributeDeclaration:
                sym      = new GlobalAttributeDeclaration();
                sym.name = name;
                break;

            case SYMKIND.SK_UnresolvedAggregateSymbol:
                sym      = new UnresolvedAggregateSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_InterfaceImplementationMethodSymbol:
                sym      = new InterfaceImplementationMethodSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_IndexerSymbol:
                sym      = new IndexerSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_ParentSymbol:
                sym      = new ParentSymbol();
                sym.name = name;
                break;

            case SYMKIND.SK_IteratorFinallyMethodSymbol:
                sym      = new IteratorFinallyMethodSymbol();
                sym.name = name;
                break;

            default:
                throw Error.InternalCompilerError();
            }

            sym.setKind(kind);

            if (parent != null)
            {
                // Set the parent element of the child symbol.
                parent.AddToChildList(sym);
                m_pSymTable.InsertChild(parent, sym);
            }

            return(sym);
        }
Пример #22
0
 public IndexerSymbolSignature(IndexerSymbol symbol)
 {
     Symbol = symbol;
 }
Пример #23
0
 private bool Equals(IndexerSymbol other)
 {
     return base.Equals(other) && IndexType.Equals(other.IndexType) && ValueType.Equals(other.ValueType) && ReadOnly == other.ReadOnly;
 }