Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions src/AXSharp.compiler/src/AXSharp.Compiler/AXSharpProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,28 @@ public void Generate()
{
Log.Logger.Information($"Compilation of project '{AxProject.SrcFolder}' started");

var projectSources = AxProject.Sources.Select(p => (parseTree: STParser.ParseTextAsync(p).Result, source: p));
IEnumerable<(ISyntaxTree parseTree, SourceFileText source)> projectSources = AxProject.Sources.Select(p => (parseTree: STParser.ParseTextAsync(p).Result, source: p));

TargetProject.ProvisionProjectStructure();

var refParseTrees = GetReferences();
var refParseTrees = GetReferences().DistinctBy(p => p.GetText());


var toCompile = refParseTrees.Concat(projectSources.Select(p => p.parseTree));


//var packageProvider = AX.Package.DefaultPackageProvider.Empty as DefaultPackageProvider;

//var compilationResult =
// Compilation.Create(projectSources.Select(p => p.parseTree),
// new List<ISemanticAnalyzer>(),
// new Compilation.Settings(packageProvider, FeatureFlags.None, SemanticOptions.CompileToLib)).Result;

var compilationResult = Compilation.Create(toCompile, new List<ISemanticAnalyzer>(), Compilation.Settings.Default).Result;

compilationResult.Compilation.GetDiagnostics().Where(o => o.Severity == AX.Text.Diagnostics.DiagnosticSeverity.Error).ToList()
.ForEach(p => Log.Logger.Information($"{p.Severity} : {p.Location} : {p.Message.ToString()}"));

this.CleanOutput(this.OutputFolder);

foreach (var origin in projectSources)
Expand Down Expand Up @@ -405,12 +416,12 @@ private static string CreateMetaType(ITypeDeclaration type)
var kind = type.Kind;
var sb = new StringBuilder();


var hasNamespace = type.ContainingNamespace != null;
if (hasNamespace) sb.Append($"NAMESPACE {type.ContainingNamespace!.FullyQualifiedName}\n\n");

type?.Pragmas?.ToList().ForEach(p => sb.Append($"{{{p.Content}}}\n"));

switch (kind)
{
case DeclarationKind.Struct:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,69 @@ public static bool IsMemberEligibleForTranspile(this IFieldDeclaration field, IS
}


/// <summary>
/// Finds type declaration.
/// </summary>
/// <param name="compilation">Compilation object</param>
/// <param name="typeAccess">Required type</param>
/// <returns>Required type if found.</returns>
public static ITypeDeclaration FindTypeDeclaration(this Compilation compilation, AX.ST.Semantic.Model.ISemanticTypeAccess? typeAccess)
{
// This is to resolve fully qualified type name when the type cannot be determined propeprly form the semantic tree.
// TODO: This workaround should be removed once we can properly use project dependencies in the stc.
if (typeAccess == null)
{
return null;
}

var fullyQualified = compilation.GetSemanticTree().Types.DistinctBy(p => p.FullyQualifiedName).Where(p => p.FullyQualifiedName == typeAccess.Type.FullyQualifiedName).FirstOrDefault();

if (fullyQualified != null)
{
return fullyQualified;
}

var candidates = compilation.GetSemanticTree().Types.DistinctBy(p => p.FullyQualifiedName).Where(p => p.Name == typeAccess.TypeSymbol.Name);
if (candidates.Count() == 1)
{
return candidates.First();
}

if (candidates.Count() == 0)
{
Log.Logger.Warning($"Type '{typeAccess?.ToString()}' not found in the semantic tree.");
}

if (candidates.Count() > 1)
{
Log.Logger.Warning($"Multiple types found for '{typeAccess?.ToString()}' in the semantic tree. You may need to fully qualify the declaration.");
}

return null;
}

/// <summary>
/// Determines fully qualified name of the declaration.
/// </summary>
/// <param name="declaration">Field declaration</param>
/// <param name="compilation">Compilation object.</param>
/// <returns>Fully qualified name of the declaration.</returns>
public static string? DetermineFullyQualifiedName(this IFieldDeclaration declaration, Compilation compilation)
{
return compilation.FindTypeDeclaration(declaration.TypeAccess)?.FullyQualifiedName;
}

/// <summary>
/// Determines fully qualified name of the declaration.
/// </summary>
/// <param name="declaration">Variable declaration</param>
/// <param name="compilation">Compilation object.</param>
/// <returns>Fully qualified name of the declaration.</returns>
public static string? DetermineFullyQualifiedName(this IVariableDeclaration declaration, Compilation compilation)
{
return compilation.FindTypeDeclaration(declaration.TypeAccess)?.FullyQualifiedName;
}

private static bool IsToBeOmitted(this IStorageDeclaration fieldDeclaration, ISourceBuilder sourceBuilder, string coBuilder)
{

Expand Down Expand Up @@ -89,8 +152,7 @@ public static bool IsEligibleForTranspile(this IFieldDeclaration fieldDeclaratio
type is IStringTypeDeclaration ||
type is IStructuredTypeDeclaration ||
type is INamedValueTypeDeclaration ||
sourceBuilder.Compilation.GetSemanticTree().Types.Any(p =>
p.FullyQualifiedName == type.FullyQualifiedName));
sourceBuilder.Compilation.FindTypeDeclaration(fieldDeclaration.TypeAccess) != null);

if(!isEligible)
{
Expand All @@ -117,8 +179,7 @@ public static bool IsEligibleForTranspile(this IVariableDeclaration variableDecl
type is IStringTypeDeclaration ||
type is IStructuredTypeDeclaration ||
type is INamedValueTypeDeclaration ||
sourceBuilder.Compilation.GetSemanticTree().Types.Any(p =>
p.FullyQualifiedName == type.FullyQualifiedName));
sourceBuilder.Compilation.FindTypeDeclaration(variableDeclaration.TypeAccess) != null);

if (!isEligible)
{
Expand Down Expand Up @@ -147,8 +208,7 @@ public static bool IsEligibleForTranspile(this IArrayTypeDeclaration arrayTypeDe
arrayTypeDeclaration.ElementTypeAccess.Type is IStringTypeDeclaration ||
arrayTypeDeclaration.ElementTypeAccess.Type is IStructuredTypeDeclaration ||
arrayTypeDeclaration.ElementTypeAccess.Type is INamedValueTypeDeclaration ||
sourceBuilder.Compilation.GetSemanticTree().Types.Any(p =>
p.FullyQualifiedName == arrayTypeDeclaration.ElementTypeAccess.Type.FullyQualifiedName));
sourceBuilder.Compilation.FindTypeDeclaration(arrayTypeDeclaration.ElementTypeAccess) != null);

return isEligibleType && singleDimensionalArray;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,35 @@ public void CreateFieldDeclaration(IFieldDeclaration fieldDeclaration, IxNodeVis
AddToSource("{get;}");
}
break;
case UndefinedTypeDeclaration undef:
break;
default:
AddToSource($"{fieldDeclaration.AccessModifier.Transform()} ");
fieldDeclaration.Type.Accept(visitor, this);
AddToSource($" {fieldDeclaration.Name}");
AddToSource("{get;}");
// This is a workaround for ambiguous types.
// We do not require the stc build to be able to resolve the type when not fully qualified.
// STC compilation here may produce errors wich are ignored at this point. This may result in ambiguous types
// wich resolved here.
// TODO: Once we are able to correctly load dependencies for the stc compilation we should remove this workaround.
if (fieldDeclaration.Type.Kind == DeclarationKind.Ambiguous)
{
var fqn = fieldDeclaration.DetermineFullyQualifiedName(this.SourceBuilder.Compilation);

if (fqn != null)
{
AddToSource($"{fieldDeclaration.AccessModifier.Transform()} ");
AddToSource($"{fqn} ");
AddToSource($" {fieldDeclaration.Name}");
AddToSource("{get;}");
}
}
else
{
AddToSource($"{fieldDeclaration.AccessModifier.Transform()} ");
fieldDeclaration.Type.Accept(visitor, this);
AddToSource($" {fieldDeclaration.Name}");
AddToSource("{get;}");
}


break;
}
}
Expand Down Expand Up @@ -170,10 +194,31 @@ public void CreateVariableDeclaration(IVariableDeclaration semantics, IxNodeVisi
}
break;
default:
AddToSource($"public");
semantics.Type.Accept(visitor, this);
AddToSource($" {semantics.Name}");
AddToSource("{get;}");
// This is a workaround for ambiguous types.
// We do not require the stc build to be able to resolve the type when not fully qualified.
// STC compilation here may produce errors wich are ignored at this point. This may result in ambiguous types
// wich resolved here.
// TODO: Once we are able to correctly load dependencies for the stc compilation we should remove this workaround.
if (semantics.Type.Kind == DeclarationKind.Ambiguous)
{
var fqn = semantics.DetermineFullyQualifiedName(this.SourceBuilder.Compilation);

if (fqn != null)
{
AddToSource($"public");
AddToSource($"{fqn} ");
AddToSource($" {semantics.Name}");
AddToSource("{get;}");
}
}
else
{
AddToSource($"public");
semantics.Type.Accept(visitor, this);
AddToSource($" {semantics.Name}");
AddToSource("{get;}");
}

break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,13 @@ public void CreateClassDeclaration(IClassDeclarationSyntax classDeclarationSynta
AddToSource(":");

var isExtended = false;
var extendedType = classDeclaration.ExtendedTypeAccesses.FirstOrDefault();
if (Compilation.GetSemanticTree().Types
.Any(p => p.FullyQualifiedName == extendedType?.Type.FullyQualifiedName))
{
AddToSource($"{extendedType.Type.FullyQualifiedName}{ReplaceGenericSignature(classDeclaration)}");
AX.ST.Semantic.Model.ISemanticTypeAccess? extendedType = classDeclaration.ExtendedTypeAccesses.FirstOrDefault();

//TODO: Workaround for not fully qualified declarations. To be addressed with proper dependency handling in stc.
var extend = Compilation.FindTypeDeclaration(extendedType);
if (extend != null)
{
AddToSource($"{extend.FullyQualifiedName}{ReplaceGenericSignature(classDeclaration)}");
isExtended = true;
}
else
Expand Down
3 changes: 2 additions & 1 deletion src/AXSharp.compiler/src/ixc/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
},
"ixc-simple-template": {
"commandName": "Project",
"workingDirectory": "c:\\W\\Develop\\gh\\inxton\\_axopen\\axopen.templates\\axopen.template.simple\\ax"
"commandLineArgs": "--skip-deps",
"workingDirectory": "C:\\W\\Develop\\gh\\inxton\\simatic-ax\\axopen.templates\\axopen.template.simple\\ax"
},
"ixc-template-ref": {
"commandName": "Project",
Expand Down