- bound statement, body and methods
- lazy syntax bind
- SourceCompiler class
- cleanup and more implementations
This commit is contained in:
Jakub Míšek 2016-02-18 01:35:32 +01:00
Родитель 34f3bd5131
Коммит dfc647f2b1
12 изменённых файлов: 293 добавлений и 75 удалений

Просмотреть файл

@ -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;