/// <summary> /// Try to find constant by given <paramref name="name"/> in compile time. /// </summary> /// <param name="analyzer">Actual <see cref="Analyzer"/>.</param> /// <param name="name">Constant name, including class constants.</param> /// <param name="exists">Outputs <c>true</c> or <c>false</c> if the existance of the constant was determined.</param> /// <returns>Constant descriptor.</returns> private static PHP.Core.Reflection.DConstant EvaluateConstant(Analyzer analyzer, string name, out bool? exists) { if (name == null) name = string.Empty; // try global constant: QualifiedName? alias; var constant = analyzer.SourceUnit.ResolveConstantName(new QualifiedName(new Name(name)), analyzer.CurrentScope, out alias, null, PHP.Core.Parsers.Position.Invalid, false); if (constant != null) { exists = true; // we surely know, the constant is defined. return constant; } // try class constant: string typename, constname; if (Name.IsClassMemberSyntax(name, out typename, out constname)) { var type = analyzer.SourceUnit.ResolveTypeName(new QualifiedName(new Name(typename)), analyzer.CurrentScope, out alias, null, PHP.Core.Parsers.Position.Invalid, false); if (type != null && !type.IsUnknown) { Core.Reflection.ClassConstant classconst; type.GetConstant(new VariableName(constname), null /* class constants are global only */, out classconst); Debug.Assert(classconst == null || classconst.IsPublic, "Class constant are expected to be public only."); exists = (classconst != null); // we surely know, wheter the constant is or is not defined. return classconst; } } // special constants defined in runtime, but definitely defined: if (name == "PHALANGER") { exists = true; return null; } // do not evaluate in compile time exists = null; // we are not sure about existance of this constant. return null; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Statement.Analyze"]/*'/> internal override Statement/*!*/ Analyze(Analyzer/*!*/ analyzer) { if (analyzer.IsThisCodeUnreachable()) { analyzer.ReportUnreachableCode(position); return EmptyStmt.Unreachable; } Evaluation cond_eval = condExpr.Analyze(analyzer, ExInfoFromParent.DefaultExInfo); if (cond_eval.HasValue) { if (Convert.ObjectToBoolean(cond_eval.Value)) { // unbounded loop: condExpr = null; } else { // unreachable body: if (type == Type.While) { body.ReportUnreachable(analyzer); return EmptyStmt.Unreachable; } } } condExpr = cond_eval.Literalize(); analyzer.EnterLoopBody(); body = body.Analyze(analyzer); analyzer.LeaveLoopBody(); return this; }
internal void AnalyzeDocComment(Analyzer/*!*/ analyzer, XmlDocFileBuilder/*!*/ builder) { // TODO }
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo Defined_Analyze(Analyzer analyzer, string name) { bool? exists; var constant = EvaluateConstant(analyzer, name, out exists); if (exists != null) return new Core.Compiler.AST.FunctionCallEvaluateInfo() { value = exists.Value // constant existance is known in compile time }; // check in run time: return null; }
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo Exists_Analyze(Analyzer analyzer, string name) { QualifiedName? alias; DRoutine routine = analyzer.SourceUnit.ResolveFunctionName( new QualifiedName(new Name(name)), analyzer.CurrentScope, out alias, null, PHP.Core.Parsers.Position.Invalid, false); if (routine == null || routine.IsUnknown) return null; // function is not known at the compilation time. However it can be defined at the runtime (dynamic include, script library, etc). return new PHP.Core.Compiler.AST.FunctionCallEvaluateInfo() { value = true // function is definitely known the the compilation time }; }
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo GetParentClass_Analyze(Analyzer analyzer, string name) { QualifiedName? alias; DType type = analyzer.SourceUnit.ResolveTypeName( new QualifiedName(new Name(name)), analyzer.CurrentScope, out alias, null, PHP.Core.Parsers.Position.Invalid, false); if (type == null || type.IsUnknown) return null; // type is not known at the compilation time. However it can be defined at the runtime (dynamic include, script library, etc). // type is definitely known the the compilation time var parent_type = type.Base; return new PHP.Core.Compiler.AST.FunctionCallEvaluateInfo() { value = (parent_type == null ? null : parent_type.FullName) }; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Statement.Analyze"]/*'/> internal override Statement/*!*/ Analyze(Analyzer/*!*/ analyzer) { if (analyzer.IsThisCodeUnreachable()) { analyzer.ReportUnreachableCode(position); return EmptyStmt.Unreachable; } ExInfoFromParent info = ExInfoFromParent.DefaultExInfo; Statement result = this; bool is_first = true; int remaining = conditions.Count; int last_non_null = -1; for (int i = 0; i < conditions.Count; i++) { // "else": if (conditions[i].Condition == null) { Debug.Assert(i > 0); if (!is_first) analyzer.EnterConditionalCode(); conditions[i].Statement = conditions[i].Statement.Analyze(analyzer); if (!is_first) analyzer.LeaveConditionalCode(); last_non_null = i; break; } // all but the condition before the first non-evaluable including are conditional: if (!is_first) analyzer.EnterConditionalCode(); Evaluation cond_eval = conditions[i].Condition.Analyze(analyzer, info); if (!is_first) analyzer.LeaveConditionalCode(); if (cond_eval.HasValue) { if (Convert.ObjectToBoolean(cond_eval.Value)) { // condition is evaluated to be true // // analyze the first statement unconditionally, the the others conditionally: if (!is_first) analyzer.EnterConditionalCode(); conditions[i].Statement = conditions[i].Statement.Analyze(analyzer); if (!is_first) analyzer.LeaveConditionalCode(); // the remaining conditions are unreachable: for (int j = i + 1; j < conditions.Count; j++) { conditions[j].Statement.ReportUnreachable(analyzer); conditions[j] = null; remaining--; } conditions[i].Condition = null; last_non_null = i; break; } else { // condition is evaluated to be false // // remove the condition, report unreachable code: conditions[i].Statement.ReportUnreachable(analyzer); conditions[i] = null; remaining--; } } else { // condition is not evaluable: conditions[i].Condition = cond_eval.Expression; // analyze statement conditinally: analyzer.EnterConditionalCode(); conditions[i].Statement = conditions[i].Statement.Analyze(analyzer); analyzer.LeaveConditionalCode(); is_first = false; last_non_null = i; } } if (remaining == 0) return EmptyStmt.Skipped; Debug.Assert(last_non_null != -1 && conditions[last_non_null] != null); // only "else" remained: if (remaining == 1 && conditions[last_non_null].Condition == null) return conditions[last_non_null].Statement; // compact the list (remove nulls): if (remaining < conditions.Count) { List<ConditionalStmt> compacted = new List<ConditionalStmt>(remaining); foreach (ConditionalStmt condition in conditions) { if (condition != null) compacted.Add(condition); } conditions = compacted; } return this; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Statement.Analyze"]/*'/> internal override Statement/*!*/ Analyze(Analyzer/*!*/ analyzer) { if (analyzer.IsThisCodeUnreachable()) { analyzer.ReportUnreachableCode(position); return EmptyStmt.Unreachable; } //next version: array.SetSeqPoint(); enumeree.Analyze(analyzer, ExInfoFromParent.DefaultExInfo); if (keyVariable != null) keyVariable.Analyze(analyzer); valueVariable.Analyze(analyzer); analyzer.EnterLoopBody(); body = body.Analyze(analyzer); analyzer.LeaveLoopBody(); return this; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Statement.Analyze"]/*'/> internal override Statement Analyze(Analyzer analyzer) { if (analyzer.IsThisCodeUnreachable()) { analyzer.ReportUnreachableCode(position); return EmptyStmt.Unreachable; } ExInfoFromParent info = new ExInfoFromParent(this); info.Access = AccessType.None; for (int i = 0; i < initExList.Count; i++) { initExList[i] = initExList[i].Analyze(analyzer, info).Literalize(); } if (condExList.Count > 0) { // all but the last expression is evaluated and the result is ignored (AccessType.None), // the last is read: for (int i = 0; i < condExList.Count - 1; i++) { condExList[i] = condExList[i].Analyze(analyzer, info).Literalize(); } condExList[condExList.Count - 1] = condExList[condExList.Count - 1].Analyze(analyzer, ExInfoFromParent.DefaultExInfo).Literalize(); } for (int i = 0; i < actionExList.Count; i++) { actionExList[i] = actionExList[i].Analyze(analyzer, info).Literalize(); } analyzer.EnterLoopBody(); body = body.Analyze(analyzer); analyzer.LeaveLoopBody(); return this; }
internal override int ResolveOverload(Analyzer/*!*/ analyzer, CallSignature callSignature, Position position, out RoutineSignature overloadSignature) { if (callSignature.GenericParams.Count > 0) { analyzer.ErrorSink.Add(Errors.GenericCallToLibraryFunction, analyzer.SourceUnit, position); callSignature = new CallSignature(callSignature.Parameters, TypeRef.EmptyList); } bool exact_match; int result = ResolveOverload(callSignature.Parameters.Count, out exact_match); if (!exact_match) { // library function with wrong number of actual arguments: analyzer.ErrorSink.Add(Errors.InvalidArgumentCountForFunction, analyzer.SourceUnit, position, FullName); } overloadSignature = overloads[result]; return result; }
/// <summary> /// Finds most suitable overload. Returns <see cref="InvalidOverloadIndex"/> and /// <see cref="UnknownSignature.Default"/> in <c>overloadSignature</c> if no suitable overload exists. /// </summary> internal abstract int ResolveOverload(Analyzer/*!*/ analyzer, CallSignature callSignature, Position position, out RoutineSignature overloadSignature);
internal override int ResolveOverload(Analyzer/*!*/ analyzer, CallSignature callSignature, Position position, out RoutineSignature overloadSignature) { if (callSignature.Parameters.Count < signature.MandatoryParamCount) { if (IsConstructor) { analyzer.ErrorSink.Add(Warnings.TooFewCtorParameters, analyzer.SourceUnit, position, DeclaringType.FullName, signature.MandatoryParamCount, callSignature.Parameters.Count); } else if (IsStatic) { analyzer.ErrorSink.Add(Warnings.TooFewMethodParameters, analyzer.SourceUnit, position, DeclaringType.FullName, this.FullName, signature.MandatoryParamCount.ToString(), callSignature.Parameters.Count.ToString()); } } overloadSignature = signature; return 0; }
internal override int ResolveOverload(Analyzer/*!*/ analyzer, CallSignature callSignature, Position position, out RoutineSignature overloadSignature) { if (callSignature.Parameters.Count < signature.MandatoryParamCount) { analyzer.ErrorSink.Add(Warnings.TooFewFunctionParameters, analyzer.SourceUnit, position, qualifiedName, signature.MandatoryParamCount, callSignature.Parameters.Count); } overloadSignature = signature; return 0; }
public static PHP.Core.AST.DirectFcnCall.EvaluateInfo ClassExists_Analyze_1(Analyzer analyzer, string name) { QualifiedName? alias; DType type = analyzer.SourceUnit.ResolveTypeName( new QualifiedName(new Name(name)), analyzer.CurrentScope, out alias, null, PHP.Core.Parsers.Position.Invalid, false); if (type == null || type.IsUnknown) return null; // type is not known at the compilation time. However it can be defined at the runtime (dynamic include, script library, etc). return new PHP.Core.AST.DirectFcnCall.EvaluateInfo() { value = true // type is definitely known the the compilation time }; }
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo Constant_Analyze(Analyzer analyzer, string name) { bool? exists; var constant = EvaluateConstant(analyzer, name, out exists); if (constant != null && constant.HasValue) return new Core.Compiler.AST.FunctionCallEvaluateInfo() { value = constant.Value // evaluated value in compile time }; // check in run time: return null; }
internal override void Analyze(Analyzer analyzer) { if (!this.analyzed) { base.Analyze(analyzer); // check some special constants (ignoring namespace) if (this.Name.Value == GlobalConstant.Null.FullName || this.Name.Value == GlobalConstant.False.FullName || this.Name.Value == GlobalConstant.True.FullName) analyzer.ErrorSink.Add(FatalErrors.ConstantRedeclared, analyzer.SourceUnit, Position, this.Name.Value); } }
internal void Analyze(Analyzer/*!*/ analyzer) { analyzer.LeaveUnreachableCode(); ExInfoFromParent info = new ExInfoFromParent(this); // analyze auto-prepended inclusion (no code reachability checks): if (prependedInclusion != null) { info.Access = AccessType.None; prependedInclusion.Analyze(analyzer, info); } for (int i = 0; i < statements.Count; i++) { if (analyzer.IsThisCodeUnreachable() && statements[i].IsDeclaration) { //unreachable declarations in global code are valid analyzer.LeaveUnreachableCode(); statements[i] = statements[i].Analyze(analyzer); analyzer.EnterUnreachableCode(); } else { statements[i] = statements[i].Analyze(analyzer); } } if (!sourceUnit.CompilationUnit.IsPure) Analyzer.ValidateLabels(analyzer.ErrorSink, sourceUnit, labels); // analyze auto-prepended inclusion (no code reachability checks): if (appendedInclusion != null) { info.Access = AccessType.Read; appendedInclusion.Analyze(analyzer, info); } analyzer.LeaveUnreachableCode(); }
internal override int ResolveOverload(Analyzer/*!*/ analyzer, CallSignature callSignature, Position position, out RoutineSignature/*!*/ overloadSignature) { if (overloads.Count == 0) { if (DeclaringType.TypeDesc is ClrDelegateDesc) { overloadSignature = UnknownSignature.Delegate; return 0; } // structures without ctor: if (DeclaringType.TypeDesc.RealType.IsValueType) { overloadSignature = UnknownSignature.Default; return 0; } Debug.Assert(this.IsConstructor, "Only constructors can have no overload."); overloadSignature = UnknownSignature.Default; return DRoutine.InvalidOverloadIndex; } int i = 0; bool found = false; Overload overload; while (i < overloads.Count && (overload = overloads[i]).MandatoryParamCount <= callSignature.Parameters.Count) { if (overload.MandatoryParamCount == callSignature.Parameters.Count || (overload.Flags & OverloadFlags.IsVararg) != 0) { found = true; break; } i++; } // TODO: by type resolving // evaluate arguments? if (!found) { analyzer.ErrorSink.Add(Warnings.InvalidArgumentCountForMethod, analyzer.SourceUnit, position, this.DeclaringType.FullName, this.FullName); if (i > 0) i--; overloadSignature = overloads[i]; return i; } overloadSignature = overloads[i]; return i; }
internal void Analyze(Analyzer analyzer) { ExInfoFromParent info = new ExInfoFromParent(this); if (alias) info.Access = AccessType.WriteRef; else info.Access = AccessType.Write; //retval not needed variable.Analyze(analyzer, info); }
internal override int ResolveOverload(Analyzer analyzer, CallSignature callSignature, Position position, out RoutineSignature overloadSignature) { overloadSignature = signature; return 0; }
internal override int ResolveOverload(Analyzer/*!*/ analyzer, CallSignature callSignature, Position position, out RoutineSignature overloadSignature) { overloadSignature = UnknownSignature.Default; return 0; }
internal override int ResolveOverload(Analyzer/*!*/ analyzer, CallSignature callSignature, Position position, out RoutineSignature overloadSignature) { // no ctor defined => default is to be used => should have no parameters; // do not report errors if the declaring type is open type (constructed or a generic parameter); if (declaringType.IsDefinite && IsConstructor && declaringType.IsClosed && callSignature.Parameters.Count > 0) { analyzer.ErrorSink.Add(Warnings.NoCtorDefined, analyzer.SourceUnit, position, declaringType.FullName); declaringType.ReportError(analyzer.ErrorSink, Warnings.RelatedLocation); } overloadSignature = UnknownSignature.Default; return 0; }
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo ClassExists_Analyze_2(Analyzer analyzer, string name, bool autoload) { // ignore autoload at the compile time return ClassExists_Analyze_1(analyzer, name); }
internal override Statement/*!*/ Analyze(Analyzer/*!*/ analyzer) { analyzer.EnterNamespace(this); this.Statements.Analyze(analyzer); analyzer.LeaveNamespace(); return this; }
public static bool ExtensionLoaded_Analyze(Analyzer/*!*/analyzer, string extension) { Debug.Assert(analyzer != null); foreach (var loadedExtension in analyzer.Context.ApplicationContext.GetLoadedExtensions()) if (String.Compare(loadedExtension, extension, StringComparison.CurrentCultureIgnoreCase) == 0) return true; return false; }
internal override Statement/*!*/ Analyze(Analyzer/*!*/ analyzer) { attributes.AnalyzeMembers(analyzer, analyzer.CurrentScope); attributes.Analyze(analyzer, this); bool is_unreachable = analyzer.IsThisCodeUnreachable(); foreach (GlobalConstantDecl cd in constants) { cd.GlobalConstant.Declaration.IsUnreachable = is_unreachable; // cd.Constant.CustomAttributes = attributes; cd.Analyze(analyzer); } if (is_unreachable) { analyzer.ReportUnreachableCode(position); return EmptyStmt.Unreachable; } else { return this; } }
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo CreateFunction_Analyze( Analyzer analyzer, PHP.Core.AST.CallSignature callSignature, string args, string body) { if (analyzer.IsInsideIncompleteClass()) return null; // in this case, the DirectFnCall will not be Emitted. Therefore the lambda routine will not be declared and compilation will fail when emitting not fully declared lambda FunctionDecl. // has to be a valid identifier: // actually this name is never used then string function_name = "__" + Guid.NewGuid().ToString().Replace('-', '_'); //DynamicCode.GenerateLambdaName(args, body); string prefix1, prefix2; DynamicCode.GetLamdaFunctionCodePrefixes(function_name, args, out prefix1, out prefix2); PHP.Core.Parsers.Position pos_args = callSignature.Parameters[0].Position; PHP.Core.Parsers.Position pos_body = callSignature.Parameters[1].Position; // function __XXXXXX(<args>){<fill><body>} string fill = GetInlinedLambdaCodeFill(pos_args, pos_body); string code = String.Concat(prefix2, fill, body, "}"); // the position of the first character of the parsed code: // (note that escaped characters distort position a little bit, which cannot be eliminated so easily) PHP.Core.Parsers.Position pos = PHP.Core.Parsers.Position.Initial; pos.FirstOffset = pos_args.FirstOffset - prefix1.Length + 1; pos.FirstColumn = pos_args.FirstColumn - prefix1.Length + 1; pos.FirstLine = pos_args.FirstLine; // parses function source code: var counter = new PHP.Core.Parsers.Parser.ReductionsCounter(); var ast = analyzer.BuildAst(pos, code, counter); if (ast == null || ast.Statements == null) return null; // the function cannot be parsed Debug.Assert(counter.FunctionCount == 1); var decl_node = (PHP.Core.AST.FunctionDecl)ast.Statements[0]; // adds declaration to the end of the global code statement list: analyzer.AddLambdaFcnDeclaration(decl_node); // return new PHP.Core.Compiler.AST.FunctionCallEvaluateInfo() { //.inlined = InlinedFunction.CreateFunction; emitDeclareLamdaFunction = true, // modify declaration: newRoutine = Core.Compiler.AST.FunctionDeclCompilerHelper.ConvertToLambda(decl_node, analyzer), }; }
public bool AnalyzeDfsTree(PhpSourceFile/*!*/ rootSourceFile) { CompilationUnit root = GetNode(rootSourceFile); ScriptCompilationUnit rootScript = root as ScriptCompilationUnit; if (rootScript != null && rootScript.State == CompilationUnit.States.Initial) { Analyzer analyzer = null; try { // builds the tree of parsed units via DFS: ProcessNode(rootScript); // finishes pending inclusions via MFP: ProcessPendingInclusions(); analyzer = new Analyzer(context); // pre-analysis: rootScript.PreAnalyzeRecursively(analyzer); // member analysis: rootScript.AnalyzeMembersRecursively(analyzer); if (context.Errors.AnyFatalError) return false; // full analysis: rootScript.AnalyzeRecursively(analyzer); if (context.Errors.AnyFatalError) return false; // perform post analysis: analyzer.PostAnalyze(); if (context.Errors.AnyError) return false; // TODO: // define constructed types: analyzer.DefineConstructedTypeBuilders(); } catch (CompilerException) { root.State = CompilationUnit.States.Erroneous; return false; } if (context.Errors.AnyError) return false; } else if (root.State != CompilationUnit.States.Analyzed && root.State != CompilationUnit.States.Reflected) { return false; } return true; }