Semantics
- bound statement, body and methods - lazy syntax bind - SourceCompiler class - cleanup and more implementations
This commit is contained in:
Родитель
34f3bd5131
Коммит
dfc647f2b1
|
@ -2,6 +2,7 @@
|
|||
using Microsoft.CodeAnalysis.CodeGen;
|
||||
using Microsoft.CodeAnalysis.Emit;
|
||||
using Pchp.CodeAnalysis.Emit;
|
||||
using Pchp.CodeAnalysis.Semantics;
|
||||
using Pchp.CodeAnalysis.Symbols;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -23,9 +24,8 @@ namespace Pchp.CodeAnalysis.CodeGen
|
|||
|
||||
internal static MethodBody GenerateMethodBody(
|
||||
PEModuleBuilder moduleBuilder,
|
||||
MethodSymbol method,
|
||||
SourceBaseMethodSymbol method,
|
||||
int methodOrdinal,
|
||||
//BoundStatement block,
|
||||
//ImmutableArray<LambdaDebugInfo> lambdaDebugInfo,
|
||||
//ImmutableArray<ClosureDebugInfo> closureDebugInfo,
|
||||
//StateMachineTypeSymbol stateMachineTypeOpt,
|
||||
|
@ -54,6 +54,7 @@ namespace Pchp.CodeAnalysis.CodeGen
|
|||
{
|
||||
Cci.AsyncMethodBodyDebugInfo asyncDebugInfo = null;
|
||||
|
||||
var block = method.BoundBlock;
|
||||
//var codeGen = new CodeGenerator(method, block, builder, moduleBuilder, diagnosticsForThisMethod, optimizations, emittingPdb);
|
||||
|
||||
//if (diagnosticsForThisMethod.HasAnyErrors())
|
||||
|
|
|
@ -45,11 +45,6 @@ namespace Pchp.CodeAnalysis
|
|||
/// </summary>
|
||||
private ReferenceManager _referenceManager;
|
||||
|
||||
/// <summary>
|
||||
/// Cache of special types symbol.
|
||||
/// </summary>
|
||||
readonly ConcurrentDictionary<SpecialType, INamedTypeSymbol> _specialTypesCache = new ConcurrentDictionary<SpecialType, INamedTypeSymbol>();
|
||||
|
||||
/// <summary>
|
||||
/// COR library containing base system types.
|
||||
/// </summary>
|
||||
|
@ -317,8 +312,6 @@ namespace Pchp.CodeAnalysis
|
|||
string fileVersion = //sourceAssembly.FileVersion ??
|
||||
sourceAssembly.Identity.Version.ToString();
|
||||
|
||||
// TODO: uncomment when SourceAssemblySymbol is implemented
|
||||
|
||||
Win32ResourceConversions.AppendVersionToResourceStream(resourceStream,
|
||||
!this.Options.OutputKind.IsApplication(),
|
||||
fileVersion: fileVersion,
|
||||
|
@ -382,20 +375,23 @@ namespace Pchp.CodeAnalysis
|
|||
|
||||
protected override INamedTypeSymbol CommonGetSpecialType(SpecialType specialType)
|
||||
{
|
||||
return _specialTypesCache.GetOrAdd(specialType, (type) =>
|
||||
var name = SpecialTypes.GetMetadataName(specialType);
|
||||
if (name != null && this.CorLibrary != null)
|
||||
{
|
||||
var name = SpecialTypes.GetMetadataName(type);
|
||||
if (name != null && this.CorLibrary != null)
|
||||
{
|
||||
return this.CorLibrary.GlobalNamespace.GetTypeMembers(name).FirstOrDefault();
|
||||
}
|
||||
return this.CorLibrary.GlobalNamespace.GetTypeMembers(name).FirstOrDefault();
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override INamedTypeSymbol CommonGetTypeByMetadataName(string metadataName)
|
||||
{
|
||||
//return CommonGetBoundReferenceManager().GetReferencedAssemblies()
|
||||
// + this.SourceAssembly
|
||||
// .Select(pair => pair.Value)
|
||||
// .SelectMany(a => a.GlobalNamespace.GetTypeMembers(metadataName))
|
||||
// .FirstOrDefault();
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
@ -492,22 +488,13 @@ namespace Pchp.CodeAnalysis
|
|||
// Use a temporary bag so we don't have to refilter pre-existing diagnostics.
|
||||
DiagnosticBag methodBodyDiagnosticBag = DiagnosticBag.GetInstance();
|
||||
|
||||
moduleBeingBuilt.SourceModule.SymbolTables.GetFunctions()
|
||||
.Concat(moduleBeingBuilt.SourceModule.SymbolTables.GetTypes().SelectMany(t => t.GetMembers().OfType<MethodSymbol>()))
|
||||
.Foreach((m) =>
|
||||
{
|
||||
var body = CodeGen.MethodGenerator.GenerateMethodBody(moduleBeingBuilt, (MethodSymbol)m, 0, null, methodBodyDiagnosticBag, false);
|
||||
moduleBeingBuilt.SetMethodBody(m, body);
|
||||
});
|
||||
|
||||
//MethodCompiler.CompileMethodBodies(
|
||||
// this,
|
||||
// moduleBeingBuilt,
|
||||
// emittingPdb,
|
||||
// hasDeclarationErrors,
|
||||
// diagnostics: methodBodyDiagnosticBag,
|
||||
// filterOpt: filterOpt,
|
||||
// cancellationToken: cancellationToken);
|
||||
SourceCompiler.CompileMethodBodies(
|
||||
this,
|
||||
moduleBeingBuilt,
|
||||
emittingPdb,
|
||||
hasDeclarationErrors,
|
||||
methodBodyDiagnosticBag,
|
||||
cancellationToken);
|
||||
|
||||
SetupWin32Resources(moduleBeingBuilt, win32Resources, methodBodyDiagnosticBag);
|
||||
|
||||
|
@ -657,10 +644,45 @@ namespace Pchp.CodeAnalysis
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filter out warnings based on the compiler options (/nowarn, /warn and /warnaserror) and the pragma warning directives.
|
||||
/// 'incoming' is freed.
|
||||
/// </summary>
|
||||
/// <returns>True when there is no error or warning treated as an error.</returns>
|
||||
internal override bool FilterAndAppendAndFreeDiagnostics(DiagnosticBag accumulator, ref DiagnosticBag incoming)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
return true;
|
||||
bool result = FilterAndAppendDiagnostics(accumulator, incoming.AsEnumerableWithoutResolution());
|
||||
incoming.Free();
|
||||
incoming = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filter out warnings based on the compiler options (/nowarn, /warn and /warnaserror) and the pragma warning directives.
|
||||
/// </summary>
|
||||
/// <returns>True when there is no error.</returns>
|
||||
private bool FilterAndAppendDiagnostics(DiagnosticBag accumulator, IEnumerable<Diagnostic> incoming)
|
||||
{
|
||||
bool hasError = false;
|
||||
bool reportSuppressedDiagnostics = Options.ReportSuppressedDiagnostics;
|
||||
|
||||
foreach (Diagnostic d in incoming)
|
||||
{
|
||||
var filtered = _options.FilterDiagnostic(d);
|
||||
if (filtered == null ||
|
||||
(!reportSuppressedDiagnostics && filtered.IsSuppressed))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (filtered.Severity == DiagnosticSeverity.Error)
|
||||
{
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
accumulator.Add(filtered);
|
||||
}
|
||||
|
||||
return !hasError;
|
||||
}
|
||||
|
||||
internal override int GetSyntaxTreeOrdinal(SyntaxTree tree)
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
using Microsoft.CodeAnalysis;
|
||||
using Pchp.CodeAnalysis.CodeGen;
|
||||
using Pchp.CodeAnalysis.Emit;
|
||||
using Pchp.CodeAnalysis.Symbols;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Pchp.CodeAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs compilation of all source methods.
|
||||
/// </summary>
|
||||
internal static class SourceCompiler
|
||||
{
|
||||
public static void CompileMethodBodies(
|
||||
PhpCompilation compilation,
|
||||
PEModuleBuilder module,
|
||||
bool emittingPdb,
|
||||
bool hasDeclarationErrors,
|
||||
DiagnosticBag diagnostics,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var sourcesymbols = compilation.SourceSymbolTables;
|
||||
// var callgraph = new ...
|
||||
// var worklist = new ... // parralel worklist algorithm
|
||||
|
||||
// 1.Bind Syntax & Symbols to Operations (CFG)
|
||||
// a.equivalent to building CFG
|
||||
// b.most generic types(and empty type - mask)
|
||||
// c.inline syntax like traits
|
||||
|
||||
// 2.Analyze Operations + Synthetize(magic)
|
||||
// a.synthetize entry point, getters, setters, ctors, dispose, magic methods, …
|
||||
// b.type analysis(converge type - mask), resolve symbols
|
||||
// c.update types(from type-mask)
|
||||
|
||||
// 3. Emit method bodies
|
||||
|
||||
// debug:
|
||||
var methods = sourcesymbols.GetFunctions()
|
||||
.Concat(sourcesymbols.GetTypes().SelectMany(t => t.GetMembers()))
|
||||
.OfType<SourceBaseMethodSymbol>();
|
||||
|
||||
methods.Foreach(m =>
|
||||
{
|
||||
var body = MethodGenerator.GenerateMethodBody(module, m, 0, null, diagnostics, emittingPdb);
|
||||
module.SetMethodBody(m, body);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,6 +49,10 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Compilation\SourceCompiler.cs" />
|
||||
<Compile Include="Semantics\BoundMethodBody.cs" />
|
||||
<Compile Include="Semantics\SemanticsBinder.cs" />
|
||||
<Compile Include="Semantics\Statements.cs" />
|
||||
<Compile Include="CodeGen\MethodGenerator.cs" />
|
||||
<Compile Include="CommandLine\PhpCommandLineArguments.cs" />
|
||||
<Compile Include="CommandLine\PhpCommandLineParser.cs" />
|
||||
|
@ -106,10 +110,7 @@
|
|||
<ItemGroup>
|
||||
<None Include="project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Binder\" />
|
||||
<Folder Include="BoundTree\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="PhpResources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
using Microsoft.CodeAnalysis.Semantics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using System.Collections.Immutable;
|
||||
using Pchp.CodeAnalysis.Symbols;
|
||||
using Pchp.Syntax.AST;
|
||||
|
||||
namespace Pchp.CodeAnalysis.Semantics
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a method semantics.
|
||||
/// </summary>
|
||||
public class BoundMethodBody : BoundBlock
|
||||
{
|
||||
// type context
|
||||
|
||||
// locals state
|
||||
|
||||
protected ImmutableArray<ILocalSymbol> _locals;
|
||||
|
||||
/// <summary>
|
||||
/// Array of local variables.
|
||||
/// </summary>
|
||||
public override ImmutableArray<ILocalSymbol> Locals => _locals;
|
||||
|
||||
public BoundMethodBody(IEnumerable<IStatement> statements)
|
||||
: this(statements, ImmutableArray<ILocalSymbol>.Empty)
|
||||
{ }
|
||||
|
||||
public BoundMethodBody(IEnumerable<IStatement> statements, ImmutableArray<ILocalSymbol> locals)
|
||||
:base(statements)
|
||||
{
|
||||
_locals = locals;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using Microsoft.CodeAnalysis.Semantics;
|
||||
using Pchp.Syntax.AST;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Pchp.CodeAnalysis.Semantics
|
||||
{
|
||||
/// <summary>
|
||||
/// Binds syntax nodes to semantic nodes (CFG).
|
||||
/// </summary>
|
||||
internal static class SemanticsBinder
|
||||
{
|
||||
public static IEnumerable<IStatement> BindStatements(IList<Statement>/*!*/statements)
|
||||
{
|
||||
Debug.Assert(statements != null);
|
||||
|
||||
for (int i = 0; i < statements.Count; i++)
|
||||
yield return BindStatement(statements[i]);
|
||||
}
|
||||
|
||||
public static IStatement BindStatement(Statement/*!*/stmt)
|
||||
{
|
||||
Debug.Assert(stmt != null);
|
||||
|
||||
return new BoundEmptyStatement(); // TODO
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
using Microsoft.CodeAnalysis.Semantics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using System.Collections.Immutable;
|
||||
using Pchp.Syntax.AST;
|
||||
|
||||
namespace Pchp.CodeAnalysis.Semantics
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class representing a statement semantic.
|
||||
/// </summary>
|
||||
public abstract class BoundStatement : IStatement
|
||||
{
|
||||
public virtual bool IsInvalid => false;
|
||||
|
||||
public abstract OperationKind Kind { get; }
|
||||
|
||||
public SyntaxNode Syntax => null;
|
||||
|
||||
public abstract void Accept(OperationVisitor visitor);
|
||||
|
||||
public abstract TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument);
|
||||
}
|
||||
|
||||
public sealed class BoundEmptyStatement : BoundStatement
|
||||
{
|
||||
public override OperationKind Kind => OperationKind.EmptyStatement;
|
||||
|
||||
public override void Accept(OperationVisitor visitor)
|
||||
=> visitor.VisitEmptyStatement(this);
|
||||
|
||||
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
|
||||
=> visitor.VisitEmptyStatement(this, argument);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Code block semantic.
|
||||
/// </summary>
|
||||
public class BoundBlock : BoundStatement, IBlockStatement
|
||||
{
|
||||
ImmutableArray<IStatement> _statements;
|
||||
|
||||
public BoundBlock(IEnumerable<IStatement> statements)
|
||||
{
|
||||
_statements = statements.AsImmutable();
|
||||
}
|
||||
|
||||
public override OperationKind Kind => OperationKind.BlockStatement;
|
||||
|
||||
/// <summary>
|
||||
/// Array of local variables within this code block.
|
||||
/// All PHP local variables are declared within the method scope.
|
||||
/// </summary>
|
||||
public virtual ImmutableArray<ILocalSymbol> Locals => ImmutableArray<ILocalSymbol>.Empty;
|
||||
|
||||
public ImmutableArray<IStatement> Statements => _statements;
|
||||
|
||||
public override void Accept(OperationVisitor visitor)
|
||||
=> visitor.VisitBlockStatement(this);
|
||||
|
||||
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
|
||||
=> visitor.VisitBlockStatement(this, argument);
|
||||
}
|
||||
}
|
|
@ -680,13 +680,7 @@ namespace Pchp.CodeAnalysis.Symbols
|
|||
}
|
||||
}
|
||||
|
||||
internal override bool IsMetadataAbstract
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_flags & TypeAttributes.Abstract) != 0;
|
||||
}
|
||||
}
|
||||
internal override bool IsMetadataAbstract => (_flags & TypeAttributes.Abstract) != 0;
|
||||
|
||||
public override bool IsSealed
|
||||
{
|
||||
|
@ -698,21 +692,9 @@ namespace Pchp.CodeAnalysis.Symbols
|
|||
}
|
||||
}
|
||||
|
||||
internal override bool IsMetadataSealed
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_flags & TypeAttributes.Sealed) != 0;
|
||||
}
|
||||
}
|
||||
internal override bool IsMetadataSealed => (_flags & TypeAttributes.Sealed) != 0;
|
||||
|
||||
internal TypeAttributes Flags
|
||||
{
|
||||
get
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
}
|
||||
internal TypeAttributes Flags => _flags;
|
||||
|
||||
internal NamedTypeSymbol GetDeclaredBaseType(ConsList<Symbol> basesBeingResolved)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@ using System.Reflection.Metadata;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Pchp.Syntax;
|
||||
|
||||
namespace Pchp.CodeAnalysis.Symbols
|
||||
{
|
||||
|
@ -15,7 +16,7 @@ namespace Pchp.CodeAnalysis.Symbols
|
|||
/// The base class to represent a namespace imported from a PE/module. Namespaces that differ
|
||||
/// only by casing in name are not merged.
|
||||
/// </summary>
|
||||
internal abstract class PENamespaceSymbol : NamespaceSymbol
|
||||
internal abstract class PENamespaceSymbol : NamespaceSymbol, ISymbolTables
|
||||
{
|
||||
/// <summary>
|
||||
/// A map of types immediately contained within this namespace
|
||||
|
@ -126,5 +127,22 @@ namespace Pchp.CodeAnalysis.Symbols
|
|||
Interlocked.CompareExchange(ref _types, typesDict, null);
|
||||
}
|
||||
}
|
||||
|
||||
INamedTypeSymbol ISymbolTables.GetType(QualifiedName name)
|
||||
{
|
||||
var types = this.GetTypeMembers(name.ClrName());
|
||||
if (types.Length == 0)
|
||||
return null;
|
||||
if (types.Length == 1)
|
||||
return types[0];
|
||||
|
||||
throw new NotImplementedException(); // merged type
|
||||
}
|
||||
|
||||
IEnumerable<INamedTypeSymbol> ISymbolTables.GetTypes() => this.GetTypeMembers();
|
||||
|
||||
IMethodSymbol ISymbolTables.GetFunction(QualifiedName name) => null;
|
||||
|
||||
IEnumerable<IMethodSymbol> ISymbolTables.GetFunctions() => ImmutableArray<IMethodSymbol>.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Semantics;
|
||||
using Pchp.CodeAnalysis.Semantics;
|
||||
using Pchp.Syntax.AST;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -12,25 +13,15 @@ namespace Pchp.CodeAnalysis.Symbols
|
|||
{
|
||||
internal abstract class SourceBaseMethodSymbol : MethodSymbol
|
||||
{
|
||||
IBlockStatement _block; // TODO: BoundMethodBody
|
||||
BoundMethodBody _block;
|
||||
|
||||
/// <summary>
|
||||
/// Bound block containing method semantics.
|
||||
/// Gets lazily bound block containing method semantics.
|
||||
/// Entry point of analysis and emitting.
|
||||
/// </summary>
|
||||
public IBlockStatement GetOrBindBlock
|
||||
{
|
||||
get
|
||||
{
|
||||
var block = _block;
|
||||
if (block == null)
|
||||
{
|
||||
// TODO: bind block
|
||||
}
|
||||
public BoundMethodBody BoundBlock => _block ?? (_block = CreateBoundBlock());
|
||||
|
||||
return block;
|
||||
}
|
||||
}
|
||||
protected abstract BoundMethodBody CreateBoundBlock();
|
||||
|
||||
readonly protected ImmutableArray<ParameterSymbol> _params;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Pchp.CodeAnalysis.Semantics;
|
||||
using Pchp.Syntax.AST;
|
||||
|
||||
namespace Pchp.CodeAnalysis.Symbols
|
||||
|
@ -27,6 +28,9 @@ namespace Pchp.CodeAnalysis.Symbols
|
|||
_syntax = syntax;
|
||||
}
|
||||
|
||||
protected override BoundMethodBody CreateBoundBlock()
|
||||
=> new BoundMethodBody(SemanticsBinder.BindStatements(_syntax.Body).AsImmutable());
|
||||
|
||||
public override string Name => NameUtils.MakeQualifiedName(_syntax.Name, _syntax.Namespace).ClrName();
|
||||
|
||||
public override Symbol ContainingSymbol => _compilation.SourceModule;
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Pchp.Syntax.AST;
|
||||
using Pchp.CodeAnalysis.Semantics;
|
||||
|
||||
namespace Pchp.CodeAnalysis.Symbols
|
||||
{
|
||||
|
@ -27,6 +28,9 @@ namespace Pchp.CodeAnalysis.Symbols
|
|||
_syntax = syntax;
|
||||
}
|
||||
|
||||
protected override BoundMethodBody CreateBoundBlock()
|
||||
=> new BoundMethodBody(SemanticsBinder.BindStatements(_syntax.Body).AsImmutable());
|
||||
|
||||
public override string Name => _syntax.Name.Value;
|
||||
|
||||
public override Symbol ContainingSymbol => _type;
|
||||
|
|
Загрузка…
Ссылка в новой задаче