Exemple #1
0
        public BoundStatement BindStatement(AST.Statement stmt)
        {
            Debug.Assert(stmt != null);

            if (stmt is AST.EchoStmt) return new BoundExpressionStatement(new BoundEcho(BindArguments(((AST.EchoStmt)stmt).Parameters))) { PhpSyntax = stmt };
            if (stmt is AST.ExpressionStmt) return new BoundExpressionStatement(BindExpression(((AST.ExpressionStmt)stmt).Expression, BoundAccess.None)) { PhpSyntax = stmt };
            if (stmt is AST.JumpStmt) return BindJumpStmt((AST.JumpStmt)stmt);
            if (stmt is AST.FunctionDecl) return new BoundFunctionDeclStatement(stmt.GetProperty<SourceFunctionSymbol>());  // see SourceDeclarations.PopulatorVisitor
            if (stmt is AST.TypeDecl) return new BoundTypeDeclStatement(stmt.GetProperty<SourceTypeSymbol>());  // see SourceDeclarations.PopulatorVisitor
            if (stmt is AST.GlobalStmt) return new BoundGlobalVariableStatement(
                ((AST.GlobalStmt)stmt).VarList.Cast<AST.DirectVarUse>()
                    .Select(s => (BoundGlobalVariable)_locals.BindVariable(s.VarName, VariableKind.GlobalVariable, null))
                    .ToImmutableArray());
            if (stmt is AST.StaticStmt) return new BoundStaticVariableStatement(
                ((AST.StaticStmt)stmt).StVarList
                    .Select(s => (BoundStaticLocal)_locals.BindVariable(s.Variable, VariableKind.StaticVariable,
                        () => (s.Initializer != null ? BindExpression(s.Initializer) : null)))
                    .ToImmutableArray())
            { PhpSyntax = stmt };
            if (stmt is AST.UnsetStmt) return new BoundUnset(
                ((AST.UnsetStmt)stmt).VarList
                    .Select(v => (BoundReferenceExpression)BindExpression(v, BoundAccess.Unset))
                    .ToImmutableArray())
            { PhpSyntax = stmt };
            if (stmt is AST.ThrowStmt) return new BoundThrowStatement(BindExpression(((AST.ThrowStmt)stmt).Expression, BoundAccess.Read)) { PhpSyntax = stmt };
            if (stmt is AST.PHPDocStmt) return new BoundEmptyStatement();

            throw new NotImplementedException(stmt.GetType().FullName);
        }
Exemple #2
0
 /// <summary>
 /// Gets type mask corresponding to <c>self</c> with <c>includesSubclasses</c> flag set whether type is not final.
 /// </summary>
 private TypeRefMask GetTypeCtxMask(AST.TypeDecl typeCtx)
 {
     if (typeCtx != null)
     {
         var typeIsFinal = (typeCtx.MemberAttributes & PhpMemberAttributes.Final) != 0;
         return GetTypeMask(new ClassTypeRef(NameUtils.MakeQualifiedName(typeCtx)), !typeIsFinal);
     }
     else
     {
         return TypeRefMask.AnyType;
     }
 }
Exemple #3
0
        BoundExpression BindUnaryEx(AST.UnaryEx expr, BoundAccess access)
        {
            var operandAccess = BoundAccess.Read;

            switch (expr.Operation)
            {
                case AST.Operations.AtSign:
                    operandAccess = access;
                    break;
                case AST.Operations.UnsetCast:
                    operandAccess = BoundAccess.None;
                    break;
            }

            return new BoundUnaryEx(BindExpression(expr.Expr, operandAccess), expr.Operation)
                .WithAccess(access);
        }
Exemple #4
0
 BoundExpression BindInstanceOfEx(AST.InstanceOfEx x)
 {
     return new BoundInstanceOfEx(BindExpression(x.Expression, BoundAccess.Read), BindTypeRef(x.ClassNameRef));
 }
Exemple #5
0
 BoundExpression BindBinaryEx(AST.BinaryEx expr)
 {
     if (expr.Operation == AST.Operations.Concat)
     {
         return new BoundConcatEx(BindArguments(new[] { expr.LeftExpr, expr.RightExpr }));
     }
     else
     {
         return new BoundBinaryEx(
             BindExpression(expr.LeftExpr, BoundAccess.Read),
             BindExpression(expr.RightExpr, BoundAccess.Read),
             expr.Operation);
     }
 }
Exemple #6
0
        static ConstantValue CreateConstant(AST.GlobalConstUse expr)
        {
            if (expr.Name == QualifiedName.Null) return ConstantValue.Null;
            if (expr.Name == QualifiedName.True) return ConstantValue.True;
            if (expr.Name == QualifiedName.False) return ConstantValue.False;

            return null;
        }
Exemple #7
0
 BoundExpression BindConcatEx(AST.ConcatEx x)
 {
     return new BoundConcatEx(BindArguments(x.Expressions));
 }
Exemple #8
0
        BoundExpression BindListEx(AST.ListEx expr)
        {
            var vars = expr.Items
                .Select(lval => (lval != null) ? (BoundReferenceExpression)BindExpression(((AST.ValueItem)lval).ValueExpr, BoundAccess.Write) : null)
                .ToArray();

            return new BoundListEx(vars).WithAccess(BoundAccess.Write);
        }
Exemple #9
0
        public static ConstantValue TryGetConstantValue(PhpCompilation compilation, AST.Expression value)
        {
            if (value is AST.Literal) return CreateConstant((AST.Literal)value);
            if (value is AST.GlobalConstUse) return CreateConstant((AST.GlobalConstUse)value);

            return null;
        }
Exemple #10
0
        BoundExpression BindNew(AST.NewEx x, BoundAccess access)
        {
            Debug.Assert(access.IsRead || access.IsReadRef || access.IsNone);

            return new BoundNewEx(BindTypeRef(x.ClassNameRef), BindArguments(x.CallSignature.Parameters))
                .WithAccess(access);
        }
Exemple #11
0
        BoundExpression BindArrayEx(AST.ArrayEx x, BoundAccess access)
        {
            Debug.Assert(access.IsRead && !access.IsReadRef);

            return new BoundArrayEx(BindArrayItems(x.Items)) { PhpSyntax = x }.WithAccess(access);
        }
Exemple #12
0
        BoundExpression BindIncDec(AST.IncDecEx expr)
        {
            // bind variable reference
            var varref = (BoundReferenceExpression)BindExpression(expr.Variable, BoundAccess.ReadAndWrite);

            // resolve kind
            UnaryOperationKind kind;
            if (expr.Inc)
                kind = (expr.Post) ? UnaryOperationKind.OperatorPostfixIncrement : UnaryOperationKind.OperatorPrefixIncrement;
            else
                kind = (expr.Post) ? UnaryOperationKind.OperatorPostfixDecrement : UnaryOperationKind.OperatorPrefixDecrement;

            //
            return new BoundIncDecEx(varref, kind);
        }
Exemple #13
0
        BoundExpression BindVarLikeConstructUse(AST.VarLikeConstructUse expr, BoundAccess access)
        {
            if (expr is AST.SimpleVarUse) return BindSimpleVarUse((AST.SimpleVarUse)expr, access);
            if (expr is AST.FunctionCall) return BindFunctionCall((AST.FunctionCall)expr, access);
            if (expr is AST.NewEx) return BindNew((AST.NewEx)expr, access);
            if (expr is AST.ArrayEx) return BindArrayEx((AST.ArrayEx)expr, access);
            if (expr is AST.ItemUse) return BindItemUse((AST.ItemUse)expr, access);
            if (expr is AST.StaticFieldUse) return BindFieldUse((AST.StaticFieldUse)expr, access);
            if (expr is AST.ListEx) return BindListEx((AST.ListEx)expr).WithAccess(access);


            throw new NotImplementedException(expr.GetType().FullName);
        }
Exemple #14
0
 BoundExpression BindConditionalEx(AST.ConditionalEx expr)
 {
     return new BoundConditionalEx(
         BindExpression(expr.CondExpr),
         (expr.TrueExpr != null) ? BindExpression(expr.TrueExpr) : null,
         BindExpression(expr.FalseExpr));
 }
Exemple #15
0
        public BoundTypeRef BindTypeRef(AST.TypeRef tref)
        {
            var bound = new BoundTypeRef(tref);

            if (tref is AST.IndirectTypeRef)
            {
                bound.TypeExpression = BindExpression(((AST.IndirectTypeRef)tref).ClassNameVar);
            }

            return bound;
        }
Exemple #16
0
        BoundRoutineCall BindFunctionCall(AST.FunctionCall x, BoundAccess access)
        {
            if (!access.IsRead && !access.IsNone)
            {
                throw new NotSupportedException();
            }

            var boundinstance = (x.IsMemberOf != null) ? BindExpression(x.IsMemberOf, BoundAccess.Read/*Object?*/) : null;
            var boundargs = BindArguments(x.CallSignature.Parameters);

            if (x is AST.DirectFcnCall)
            {
                var f = (AST.DirectFcnCall)x;
                var fname = f.FullName;

                if (f.IsMemberOf == null)
                {
                    return new BoundGlobalFunctionCall(fname.Name, fname.FallbackName, boundargs)
                        .WithAccess(access);
                }
                else
                {
                    Debug.Assert(fname.FallbackName.HasValue == false);
                    Debug.Assert(fname.Name.QualifiedName.IsSimpleName);
                    return new BoundInstanceFunctionCall(boundinstance, fname.Name, boundargs)
                        .WithAccess(access);
                }
            }
            else if (x is AST.IndirectFcnCall)
            {
                var f = (AST.IndirectFcnCall)x;
                var nameExpr = BindExpression(f.NameExpr);
                return ((f.IsMemberOf == null)
                    ? (BoundRoutineCall)new BoundGlobalFunctionCall(nameExpr, boundargs)
                    : new BoundInstanceFunctionCall(boundinstance, new BoundUnaryEx(nameExpr, AST.Operations.StringCast), boundargs))
                        .WithAccess(access);
            }
            else if (x is AST.StaticMtdCall)
            {
                var f = (AST.StaticMtdCall)x;
                Debug.Assert(f.IsMemberOf == null);

                var boundname = (f is AST.DirectStMtdCall)
                    ? new BoundRoutineName(new QualifiedName(((AST.DirectStMtdCall)f).MethodName))
                    : new BoundRoutineName(new BoundUnaryEx(BindExpression(((AST.IndirectStMtdCall)f).MethodNameVar), AST.Operations.StringCast));

                return new BoundStaticFunctionCall(BindTypeRef(f.TargetType), boundname, boundargs)
                    .WithAccess(access);
            }

            //
            throw new NotImplementedException(x.GetType().FullName);
        }
Exemple #17
0
        BoundExpression BindAssignEx(AST.AssignEx expr, BoundAccess access)
        {
            var target = (BoundReferenceExpression)BindExpression(expr.LValue, BoundAccess.Write);
            BoundExpression value;

            // bind value (read as value or as ref)
            if (expr is AST.ValueAssignEx)
            {
                value = BindExpression(((AST.ValueAssignEx)expr).RValue, BoundAccess.Read);
            }
            else
            {
                Debug.Assert(expr is AST.RefAssignEx);
                Debug.Assert(expr.Operation == AST.Operations.AssignRef);
                target.Access = target.Access.WithWriteRef(0); // note: analysis will write the write type
                value = BindExpression(((AST.RefAssignEx)expr).RValue, BoundAccess.ReadRef);
            }

            //
            if (expr.Operation == AST.Operations.AssignValue || expr.Operation == AST.Operations.AssignRef)
            {
                return new BoundAssignEx(target, value).WithAccess(access);
            }
            else
            {
                target.Access = target.Access.WithRead();   // Read & Write on target

                return new BoundCompoundAssignEx(target, value, expr.Operation);
            }
        }
Exemple #18
0
        IEnumerable<KeyValuePair<BoundExpression, BoundExpression>> BindArrayItems(AST.Item[] items)
        {
            foreach (var x in items)
            {
                var boundIndex = (x.Index != null) ? BindExpression(x.Index, BoundAccess.Read) : null;
                var boundValue = (x is AST.RefItem)
                    ? BindExpression(((AST.RefItem)x).RefToGet, BoundAccess.ReadRef)
                    : BindExpression(((AST.ValueItem)x).ValueExpr, BoundAccess.Read);

                yield return new KeyValuePair<BoundExpression, BoundExpression>(boundIndex, boundValue);
            }
        }
Exemple #19
0
 BoundExpression BindExpression(AST.Expression expr) => BindExpression(expr, BoundAccess.Read);
Exemple #20
0
        BoundExpression BindItemUse(AST.ItemUse x, BoundAccess access)
        {
            if (x.IsMemberOf != null)
            {
                Debug.Assert(x.Array.IsMemberOf == null);
                // fix this phalanger ast weirdness:
                x.Array.IsMemberOf = x.IsMemberOf;
                x.IsMemberOf = null;
            }

            var arrayAccess = BoundAccess.Read;

            if (access.IsWrite || access.EnsureObject || access.EnsureArray)
                arrayAccess = arrayAccess.WithEnsureArray();
            if (access.IsQuiet)
                arrayAccess = arrayAccess.WithQuiet();

            var boundArray = BindExpression(x.Array, arrayAccess);

            // boundArray.Access = boundArray.Access.WithRead(typeof(PhpArray))

            return new BoundArrayItemEx(
                boundArray, (x.Index != null) ? BindExpression(x.Index, BoundAccess.Read) : null)
                .WithAccess(access);
        }
Exemple #21
0
        static BoundExpression BindLiteral(AST.Literal expr)
        {
            if (expr is AST.LongIntLiteral) return new BoundLiteral(((AST.LongIntLiteral)expr).Value);
            if (expr is AST.StringLiteral) return new BoundLiteral(((AST.StringLiteral)expr).Value);
            if (expr is AST.DoubleLiteral) return new BoundLiteral(((AST.DoubleLiteral)expr).Value);
            if (expr is AST.BoolLiteral) return new BoundLiteral(((AST.BoolLiteral)expr).Value);
            if (expr is AST.NullLiteral) return new BoundLiteral(null);
            if (expr is AST.BinaryStringLiteral) return new BoundLiteral(((AST.BinaryStringLiteral)expr).Value);

            throw new NotImplementedException();
        }
Exemple #22
0
        BoundStatement BindJumpStmt(AST.JumpStmt stmt)
        {
            if (stmt.Type == AST.JumpStmt.Types.Return)
            {
                return new BoundReturnStatement(
                    (stmt.Expression != null)
                        ? BindExpression(stmt.Expression, BoundAccess.Read)   // ReadRef in case routine returns an aliased value
                        : null)
                { PhpSyntax = stmt };
            }

            throw ExceptionUtilities.Unreachable;
        }
Exemple #23
0
        static ConstantValue CreateConstant(AST.Literal expr)
        {
            if (expr is AST.LongIntLiteral) return ConstantValue.Create(((AST.LongIntLiteral)expr).Value);
            if (expr is AST.StringLiteral) return ConstantValue.Create(((AST.StringLiteral)expr).Value);
            if (expr is AST.DoubleLiteral) return ConstantValue.Create(((AST.DoubleLiteral)expr).Value);
            if (expr is AST.BoolLiteral) return ConstantValue.Create(((AST.BoolLiteral)expr).Value);
            if (expr is AST.NullLiteral) return ConstantValue.Create(null);
            //if (expr is BinaryStringLiteral) return ConstantValue.Create(((BinaryStringLiteral)expr).Value);

            return null;
        }
Exemple #24
0
        /// <summary>
        /// Gets type mask corresponding to given TypeRef within this context.
        /// </summary>
        private TypeRefMask GetTypeMask(AST.IndirectTypeRef/*!*/tref, bool includesSubclasses)
        {
            Contract.ThrowIfNull(tref);

            var dvar = tref.ClassNameVar as AST.DirectVarUse;
            if (dvar != null && dvar.IsMemberOf == null && dvar.VarName.IsThisVariableName)
                return GetThisTypeMask();

            //
            return TypeRefMask.AnyType;
        }
Exemple #25
0
        BoundExpression BindSimpleVarUse(AST.SimpleVarUse expr, BoundAccess access)
        {
            var dexpr = expr as AST.DirectVarUse;
            var iexpr = expr as AST.IndirectVarUse;

            Debug.Assert(dexpr != null || iexpr != null);

            var varname = (dexpr != null)
                ? new BoundVariableName(dexpr.VarName)
                : new BoundVariableName(BindExpression(iexpr.VarNameEx));

            if (expr.IsMemberOf == null)
            {
                return new BoundVariableRef(varname);
            }
            else
            {
                var instanceAccess = BoundAccess.Read;

                if (access.IsWrite || access.EnsureObject || access.EnsureArray)
                    instanceAccess = instanceAccess.WithEnsureObject();

                if (access.IsQuiet)
                    instanceAccess = instanceAccess.WithQuiet();

                return BoundFieldRef.CreateInstanceField(BindExpression(expr.IsMemberOf, instanceAccess), varname).WithAccess(access);
            }
        }
Exemple #26
0
 BoundExpression BindIncludeEx(AST.IncludingEx x)
 {
     return new BoundIncludeEx(BindExpression(x.Target, BoundAccess.Read), x.InclusionType);
 }
Exemple #27
0
        /// <summary>
        /// Gets type mask corresponding to given TypeRef within this context.
        /// </summary>
        public TypeRefMask GetTypeMask(AST.TypeRef/*!*/tref, bool includesSubclasses = true)
        {
            Contract.ThrowIfNull(tref);

            if (tref != null)
            {
                if (tref is AST.PrimitiveTypeRef)
                {
                    switch (((AST.PrimitiveTypeRef)tref).PrimitiveTypeName)
                    {
                        case AST.PrimitiveTypeRef.PrimitiveType.@int: return GetLongTypeMask();
                        case AST.PrimitiveTypeRef.PrimitiveType.@float: return GetDoubleTypeMask();
                        case AST.PrimitiveTypeRef.PrimitiveType.@string: return GetStringTypeMask();
                        case AST.PrimitiveTypeRef.PrimitiveType.@bool: return GetBooleanTypeMask();
                        case AST.PrimitiveTypeRef.PrimitiveType.array: return GetArrayTypeMask();
                        case AST.PrimitiveTypeRef.PrimitiveType.callable: return GetCallableTypeMask();
                        case AST.PrimitiveTypeRef.PrimitiveType.@void: return 0;
                        case AST.PrimitiveTypeRef.PrimitiveType.iterable: return GetArrayTypeMask() | GetTypeMask(NameUtils.SpecialNames.Traversable, true);   // array | Traversable
                        default: throw new ArgumentException();
                    }
                }
                else if (tref is AST.INamedTypeRef) return GetTypeMask(((AST.INamedTypeRef)tref).ClassName, includesSubclasses);
                else if (tref is AST.ReservedTypeRef) return GetTypeMaskOfReservedClassName(((AST.ReservedTypeRef)tref).QualifiedName.Value.Name); // NOTE: should be translated by parser to AliasedTypeRef
                else if (tref is AST.AnonymousTypeRef) return GetTypeMask(((AST.AnonymousTypeRef)tref).TypeDeclaration.QualifiedName, false);
                else if (tref is AST.MultipleTypeRef)
                {
                    TypeRefMask result = 0;
                    foreach (var x in ((AST.MultipleTypeRef)tref).MultipleTypes)
                    {
                        result |= GetTypeMask(x, includesSubclasses);
                    }
                    return result;
                }
                else if (tref is AST.NullableTypeRef) return GetTypeMask(((AST.NullableTypeRef)tref).TargetType) | this.GetNullTypeMask();
                else if (tref is AST.GenericTypeRef) return GetTypeMask(((AST.GenericTypeRef)tref).TargetType, includesSubclasses);  // TODO: now we are ignoring type args
                else if (tref is AST.IndirectTypeRef) return GetTypeMask((AST.IndirectTypeRef)tref, true);
            }

            return TypeRefMask.AnyType;
        }
Exemple #28
0
        BoundExpression BindFieldUse(AST.StaticFieldUse x, BoundAccess access)
        {
            var typeref = BindTypeRef(x.TargetType);
            BoundVariableName varname;

            if (x is AST.DirectStFldUse)
            {
                var dx = (AST.DirectStFldUse)x;
                varname = new BoundVariableName(dx.PropertyName);
            }
            else if (x is AST.IndirectStFldUse)
            {
                var ix = (AST.IndirectStFldUse)x;
                var fieldNameExpr = BindExpression(ix.FieldNameExpr, BoundAccess.Read);

                varname = new BoundVariableName(fieldNameExpr);
            }
            else
            {
                throw ExceptionUtilities.UnexpectedValue(x);
            }

            return BoundFieldRef.CreateStaticField(typeref, varname);
        }
Exemple #29
0
        BoundExpression BindGlobalConstUse(AST.GlobalConstUse expr)
        {
            // translate built-in constants directly
            if (expr.Name == QualifiedName.True) return new BoundLiteral(true);
            if (expr.Name == QualifiedName.False) return new BoundLiteral(false);
            if (expr.Name == QualifiedName.Null) return new BoundLiteral(null);

            // bind constant
            return new BoundGlobalConst(expr.Name.ToString());
        }
Exemple #30
0
 BoundExpression BindPseudoConst(AST.PseudoConstUse x) => new BoundPseudoConst(x.Type);