├── source ├── WebIde │ ├── wwwroot │ │ ├── .nojekyll │ │ ├── css │ │ │ └── open-iconic │ │ │ │ ├── font │ │ │ │ └── fonts │ │ │ │ │ ├── open-iconic.eot │ │ │ │ │ ├── open-iconic.otf │ │ │ │ │ ├── open-iconic.ttf │ │ │ │ │ └── open-iconic.woff │ │ │ │ └── ICON-LICENSE │ │ ├── 404.html │ │ └── index.html │ ├── Backend │ │ ├── IRequiresAsyncLoad.cs │ │ ├── WasmMetadataReferenceProvider.cs │ │ └── EditorEngine.cs │ ├── LinkerConfig.xml │ ├── App.razor │ ├── _Imports.razor │ ├── Properties │ │ └── launchSettings.json │ ├── WebIde.csproj │ └── Program.cs ├── flc.Tests.Integration │ ├── Data │ │ └── FluentLang.Runtime.dll │ ├── flc.Tests.Integration.csproj │ └── FileAssemblyLoaderTests.cs ├── Compiler │ ├── IVTs.cs │ ├── Compilation │ │ ├── CompilationResultStatus.cs │ │ ├── IAssemblyCompiler.cs │ │ ├── CompilationResult.cs │ │ └── AssemblyCompiler.cs │ ├── Symbols │ │ ├── Interfaces │ │ │ ├── MethodBody │ │ │ │ ├── ILocal.cs │ │ │ │ ├── IParameterLocal.cs │ │ │ │ ├── IDeclaredLocal.cs │ │ │ │ ├── IObjectPatch.cs │ │ │ │ ├── IExpression.cs │ │ │ │ ├── IStatement.cs │ │ │ │ ├── IInvocationExpression.cs │ │ │ │ ├── Operator.cs │ │ │ │ ├── INewObjectExpression.cs │ │ │ │ ├── ILiteralExpression.cs │ │ │ │ ├── IMixinPatch.cs │ │ │ │ ├── IReturnStatement.cs │ │ │ │ ├── ILocalReferenceExpression.cs │ │ │ │ ├── IPrefixUnaryOperatorExpression.cs │ │ │ │ ├── IBinaryOperatorExpression.cs │ │ │ │ ├── IConditionalExpression.cs │ │ │ │ ├── IMethodPatch.cs │ │ │ │ ├── IMemberInvocationExpression.cs │ │ │ │ ├── IMatchExpression.cs │ │ │ │ ├── IMatchExpressionArm.cs │ │ │ │ ├── IDeclarationStatement.cs │ │ │ │ ├── IObjectPatchingExpression.cs │ │ │ │ └── IStaticInvocationExpression.cs │ │ │ ├── ISymbol.cs │ │ │ ├── IDocument.cs │ │ │ ├── IType.cs │ │ │ ├── IParameter.cs │ │ │ ├── ITypeParameter.cs │ │ │ ├── IInterfaceMethod.cs │ │ │ ├── IUnion.cs │ │ │ ├── IAssembly.cs │ │ │ ├── Version.cs │ │ │ └── IMethod.cs │ │ ├── ErrorSymbols │ │ │ ├── IErrorType.cs │ │ │ ├── ErrorParameter.cs │ │ │ ├── ErrorInterfaceMethod.cs │ │ │ ├── ErrorType.cs │ │ │ ├── ErrorInterface.cs │ │ │ └── ErrorMethod.cs │ │ ├── Visitor │ │ │ ├── IVisitableSymbol.cs │ │ │ ├── SymbolExtensions.cs │ │ │ └── ISymbolVisitor.cs │ │ ├── DocumentFactory.cs │ │ ├── Source │ │ │ ├── MethodBody │ │ │ │ ├── ParameterLocal.cs │ │ │ │ ├── DeclaredLocal.cs │ │ │ │ ├── NewObjectExpression.cs │ │ │ │ ├── EmptyInterface.cs │ │ │ │ ├── MethodBodySymbolContextExtensions.cs │ │ │ │ ├── ReturnStatement.cs │ │ │ │ ├── MethodBodySymbolContext.cs │ │ │ │ ├── MixinPatch.cs │ │ │ │ ├── MethodPatch.cs │ │ │ │ ├── LocalReferenceExpression.cs │ │ │ │ ├── CharParser.cs │ │ │ │ ├── StaticInvocationExpression.cs │ │ │ │ ├── StaticInvocationMethodBinder.cs │ │ │ │ ├── PrefixUnaryOperatorExpression.cs │ │ │ │ └── MatchExpressionArm.cs │ │ │ ├── SymbolBase.cs │ │ │ ├── SourceParameter.cs │ │ │ ├── SourceSymbolContext.cs │ │ │ ├── SourceDocument.cs │ │ │ ├── SourceUnion.cs │ │ │ ├── SourceTypeParameter.cs │ │ │ ├── SourceInterfaceMethod.cs │ │ │ └── SourceNamedInterface.cs │ │ ├── SymbolHelpers.cs │ │ ├── Substituted │ │ │ ├── SubstitutedParameter.cs │ │ │ ├── SubstitutedUnion.cs │ │ │ ├── ConstructedInterface.cs │ │ │ ├── SubstitutedInterfaceMethod.cs │ │ │ └── SubstitutedInterface.cs │ │ ├── Metadata │ │ │ ├── Utils.cs │ │ │ └── MetadataNamedInterface.cs │ │ ├── AssemblyFactory.cs │ │ ├── QualifiedName.cs │ │ └── Primitive.cs │ ├── Diagnostics │ │ ├── IDiagnosticFormatter.cs │ │ ├── Diagnostic.cs │ │ ├── DiagnosticFormatter.cs │ │ ├── ErrorCode.cs │ │ ├── DiagnosticBag.cs │ │ └── Location.cs │ ├── Emit │ │ ├── IMetadataReferenceProvider.cs │ │ ├── Utils.cs │ │ ├── CSharpNameEscaper.cs │ │ ├── DictionaryExtensions.cs │ │ ├── FluentlangToCSharpEmitter.MethodKeyOrParamName.cs │ │ └── LocalSystemDllsMetadataReferenceProvider.cs │ ├── GlobalSuppressions.cs │ ├── Parsing │ │ ├── DiagnosticErrorListener.cs │ │ └── ParserFactory.cs │ ├── Compiler.csproj │ └── Generated │ │ ├── FluentLangLexer.tokens │ │ └── FluentLangParser.tokens ├── nuget.config ├── Shared │ ├── SpanLinq.cs │ ├── ArrayExtensions.cs │ ├── StreamExtensions.cs │ ├── AsyncEnumerableExtensions.cs │ ├── Shared.csproj │ ├── ImmutableArrayExtensions.cs │ ├── Release.cs │ └── ImmutableArrayDictionary.cs ├── Runtime │ ├── Metadata │ │ ├── AssemblyNameAttribute.cs │ │ ├── DependencyAttribute.cs │ │ ├── MethodSignatureAttribute.cs │ │ └── InterfaceAttribute.cs │ ├── MethodKey.cs │ ├── Union.cs │ ├── Runtime.csproj │ └── FLObject.cs ├── flc │ ├── DependencyLoading │ │ ├── IAssemblyLoader.cs │ │ ├── AssemblyLoadResult.cs │ │ ├── IProjectLoader.cs │ │ ├── DependencyAttributeReader.cs │ │ ├── IDependencyLoader.cs │ │ ├── Dependency.cs │ │ ├── GlobalPackagesFolderProvider.cs │ │ └── FileAssemblyLoader.cs │ ├── DependencyInjection │ │ ├── FlcContainer.cs │ │ └── FlcModule.cs │ ├── ProjectSystem │ │ ├── Version.cs │ │ ├── SolutionInfo.cs │ │ ├── Reference.cs │ │ ├── ProjectInfo.cs │ │ └── SolutionFactory.cs │ ├── FlcException.cs │ ├── flc.csproj │ ├── Testing │ │ ├── TestRunner.cs │ │ └── TestResult.cs │ └── Program.cs ├── TestUtils │ ├── TestUtils.csproj │ ├── WorkItemAttribute.cs │ ├── TestInterface.cs │ ├── XunitLogger.cs │ ├── TextToken.cs │ └── TestBase.cs ├── Compiler.Tests.Unit │ ├── Parsing │ │ └── ParserErrorTests.cs │ ├── Compiler.Tests.Unit.csproj │ ├── Symbols │ │ ├── SourceSymbols │ │ │ ├── MethodBodyTests │ │ │ │ ├── NewObjectExpressionTests.cs │ │ │ │ ├── PipedStaticInvocationExpressionTests.cs │ │ │ │ └── ReturnStatementTests.cs │ │ │ └── SourceUnionTests.cs │ │ ├── Interfaces │ │ │ └── VersionTests.cs │ │ ├── Subtyping │ │ │ └── PrimitiveTests.cs │ │ └── Equivalence │ │ │ └── PrimitiveTests.cs │ └── Emit │ │ ├── MetadataTests.cs │ │ └── RegressionTests.cs └── flc.Tests.Unit │ ├── flc.Tests.Unit.csproj │ ├── DependencyInjectionTests.cs │ ├── DependencyLoading │ └── DependencyAttributeReaderTests.cs │ └── ProjectSystem │ └── ProjectDependencyOrganizerTests.cs ├── .gitignore └── LICENSE /source/WebIde/wwwroot/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YairHalberstadt/fluentlang/HEAD/.gitignore -------------------------------------------------------------------------------- /source/flc.Tests.Integration/Data/FluentLang.Runtime.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YairHalberstadt/fluentlang/HEAD/source/flc.Tests.Integration/Data/FluentLang.Runtime.dll -------------------------------------------------------------------------------- /source/WebIde/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YairHalberstadt/fluentlang/HEAD/source/WebIde/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /source/WebIde/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YairHalberstadt/fluentlang/HEAD/source/WebIde/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /source/WebIde/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YairHalberstadt/fluentlang/HEAD/source/WebIde/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /source/WebIde/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YairHalberstadt/fluentlang/HEAD/source/WebIde/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /source/Compiler/IVTs.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Compiler.Tests.Unit")] 4 | [assembly: InternalsVisibleTo("flc.Tests.Unit")] 5 | [assembly: InternalsVisibleTo("TestUtils")] -------------------------------------------------------------------------------- /source/WebIde/Backend/IRequiresAsyncLoad.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace FluentLang.WebIde.Backend 4 | { 5 | public interface IRequiresAsyncInitialize 6 | { 7 | public ValueTask InitializeAsync(); 8 | } 9 | } -------------------------------------------------------------------------------- /source/Compiler/Compilation/CompilationResultStatus.cs: -------------------------------------------------------------------------------- 1 | namespace FluentLang.Compiler.Compilation 2 | { 3 | public enum CompilationResultStatus 4 | { 5 | CodeErrors, 6 | InternalErrors, 7 | Succeeded, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/ILocal.cs: -------------------------------------------------------------------------------- 1 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 2 | { 3 | public interface ILocal 4 | { 5 | public string Identifier { get; } 6 | public IType Type { get; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IParameterLocal.cs: -------------------------------------------------------------------------------- 1 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 2 | { 3 | public interface IParameterLocal : ILocal 4 | { 5 | public IParameter Parameter { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IDeclaredLocal.cs: -------------------------------------------------------------------------------- 1 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 2 | { 3 | public interface IDeclaredLocal : ILocal 4 | { 5 | public IDeclarationStatement Declaration { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IObjectPatch.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | 3 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 4 | { 5 | public interface IObjectPatch : IVisitableSymbol 6 | { 7 | 8 | } 9 | } -------------------------------------------------------------------------------- /source/nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /source/Compiler/Diagnostics/IDiagnosticFormatter.cs: -------------------------------------------------------------------------------- 1 | namespace FluentLang.Compiler.Diagnostics 2 | { 3 | public interface IDiagnosticFormatter 4 | { 5 | string CreateDiagnosticMessage(Diagnostic diagnostic); 6 | string CreateLocationMessage(Diagnostic diagnostic); 7 | } 8 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/ErrorSymbols/IErrorType.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using System.Collections.Generic; 3 | 4 | namespace FluentLang.Compiler.Symbols.ErrorSymbols 5 | { 6 | public interface IErrorSymbol : ISymbol 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | 3 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 4 | { 5 | public interface IExpression : IVisitableSymbol 6 | { 7 | public IType Type { get; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IStatement.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | 3 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 4 | { 5 | public interface IStatement : IVisitableSymbol 6 | { 7 | int OrdinalPositionInMethod { get; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/WebIde/LinkerConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /source/Compiler/Emit/IMetadataReferenceProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using System.Collections.Immutable; 3 | 4 | namespace FluentLang.Compiler.Emit 5 | { 6 | public interface IMetadataReferenceProvider 7 | { 8 | public ImmutableArray MetadataReferences { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IInvocationExpression.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | 3 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 4 | { 5 | public interface IInvocationExpression : IExpression 6 | { 7 | public ImmutableArray Arguments { get; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/Compiler/Emit/Utils.cs: -------------------------------------------------------------------------------- 1 | namespace FluentLang.Compiler.Emit 2 | { 3 | internal static class Utils 4 | { 5 | private const string ASSEMBLY_LEVEL_METHODS = "_AssemblyLevelMethods"; 6 | public static string GetAssemblyLevelMethodsClassName(string assemblyName) 7 | => assemblyName + ASSEMBLY_LEVEL_METHODS; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/Shared/SpanLinq.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluentLang.Shared 4 | { 5 | public static class SpanLinq 6 | { 7 | public static bool Any(this ReadOnlySpan span, Func func) 8 | { 9 | foreach (var t in span) 10 | { 11 | if (func(t)) 12 | return true; 13 | } 14 | return false; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Visitor/IVisitableSymbol.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FluentLang.Compiler.Symbols.Visitor 7 | { 8 | public interface IVisitableSymbol : ISymbol 9 | { 10 | public T Visit(ISymbolVisitor visitor); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/DocumentFactory.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using FluentLang.Compiler.Symbols.Source; 3 | 4 | namespace FluentLang.Compiler.Symbols 5 | { 6 | public static class DocumentFactory 7 | { 8 | public static IDocument FromString(string source) 9 | { 10 | return new SourceDocument(source); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/ISymbol.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using System.Collections.Immutable; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces 5 | { 6 | public interface ISymbol 7 | { 8 | internal void EnsureAllLocalDiagnosticsCollected(); 9 | 10 | public ImmutableArray AllDiagnostics { get; } 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /source/Shared/ArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace FluentLang.Shared 5 | { 6 | public static class ArrayExtensions 7 | { 8 | public static ImmutableArray UnsafeAsImmutableArray(this T[] array) 9 | { 10 | return Unsafe.As>(ref array); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/Operator.cs: -------------------------------------------------------------------------------- 1 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 2 | { 3 | public enum Operator 4 | { 5 | Plus, 6 | Minus, 7 | Multiply, 8 | Divide, 9 | Remainder, 10 | LessThan, 11 | GreaterThan, 12 | Equal, 13 | NotEqual, 14 | LessThanOrEqualTo, 15 | GreaterThanOrEqualTo, 16 | And, 17 | Or, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /source/Runtime/Metadata/AssemblyNameAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluentLang.Runtime.Metadata 4 | { 5 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] 6 | public class AssemblyNameAttribute : Attribute 7 | { 8 | public AssemblyNameAttribute(string name) 9 | { 10 | Name = name; 11 | } 12 | 13 | public string Name { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /source/WebIde/App.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Sorry, there's nothing at this address. 8 | 9 | 10 | -------------------------------------------------------------------------------- /source/WebIde/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using Microsoft.AspNetCore.Components.WebAssembly.Http 7 | @using Microsoft.JSInterop 8 | @using WebIde 9 | @using WebIde.Shared 10 | @using WebIde.Backend 11 | -------------------------------------------------------------------------------- /source/Shared/StreamExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using System.IO; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace FluentLang.Shared 6 | { 7 | public static class StreamExtensions 8 | { 9 | public static ImmutableArray ToImmutableArray(this MemoryStream stream) 10 | { 11 | return stream.ToArray().UnsafeAsImmutableArray(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/INewObjectExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface INewObjectExpression : IExpression 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/ILiteralExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface ILiteralExpression : IExpression 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | object? Value { get; } 12 | } 13 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IMixinPatch.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface IMixinPatch : IObjectPatch 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | 12 | IExpression Expression { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IReturnStatement.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface IReturnStatement : IStatement 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | IExpression Expression { get; } 12 | } 13 | } -------------------------------------------------------------------------------- /source/flc/DependencyLoading/IAssemblyLoader.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.Loader; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace FluentLang.flc.DependencyLoading 7 | { 8 | public interface IAssemblyLoader 9 | { 10 | ValueTask TryLoadAssemblyAsync(AssemblyLoadContext assemblyLoadContext, Dependency dependency, CancellationToken cancellationToken = default); 11 | } 12 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/IDocument.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using System.Collections.Immutable; 3 | using static FluentLang.Compiler.Generated.FluentLangParser; 4 | 5 | namespace FluentLang.Compiler.Symbols.Interfaces 6 | { 7 | public interface IDocument 8 | { 9 | public string FullName { get; } 10 | public Compilation_unitContext SyntaxTree { get; } 11 | public ImmutableArray Diagnostics { get; } 12 | } 13 | } -------------------------------------------------------------------------------- /source/Runtime/Metadata/DependencyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluentLang.Runtime.Metadata 4 | { 5 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] 6 | public class DependencyAttribute : Attribute 7 | { 8 | public DependencyAttribute(string name, string version) 9 | { 10 | Name = name; 11 | Version = version; 12 | } 13 | 14 | public string Name { get; } 15 | public string Version { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /source/flc/DependencyInjection/FlcContainer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using StrongInject; 3 | 4 | namespace FluentLang.flc.DependencyInjection 5 | { 6 | [RegisterModule(typeof(FlcModule))] 7 | public partial class FlcContainer : IAsyncContainer 8 | { 9 | [Instance] private readonly LogLevel _logLevel; 10 | 11 | public FlcContainer(LogLevel logLevel) 12 | { 13 | _logLevel = logLevel; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /source/flc/ProjectSystem/Version.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | 4 | namespace FluentLang.flc.ProjectSystem 5 | { 6 | public class Version 7 | { 8 | [JsonConstructor] 9 | public Version(int major, int minor, string? suffix = null) 10 | { 11 | Major = major; 12 | Minor = minor; 13 | Suffix = suffix; 14 | } 15 | 16 | public int Major { get; } 17 | public int Minor { get; } 18 | public string? Suffix { get; } 19 | } 20 | } -------------------------------------------------------------------------------- /source/Compiler/Emit/CSharpNameEscaper.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols; 2 | 3 | namespace FluentLang.Compiler.Emit 4 | { 5 | public static class CSharpNameEscaper 6 | { 7 | public static string Escape(QualifiedName name) => 8 | name.ToString().Replace("_", "__").Replace(".", "_dot_"); 9 | public static QualifiedName Unescape(string name) => 10 | QualifiedName.Parse(name.Replace("__", "$").Replace("_dot_", ".").Replace("$", "_")); 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /source/flc/DependencyLoading/AssemblyLoadResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using System.Reflection; 3 | 4 | namespace FluentLang.flc.DependencyLoading 5 | { 6 | public class AssemblyLoadResult 7 | { 8 | public AssemblyLoadResult(Assembly assembly, ImmutableArray bytes) 9 | { 10 | Assembly = assembly; 11 | Bytes = bytes; 12 | } 13 | 14 | public Assembly Assembly { get; } 15 | 16 | public ImmutableArray Bytes { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /source/Compiler/Compilation/IAssemblyCompiler.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using System.IO; 3 | using System.Threading; 4 | 5 | namespace FluentLang.Compiler.Compilation 6 | { 7 | public interface IAssemblyCompiler 8 | { 9 | CompilationResult CompileAssembly( 10 | IAssembly assembly, 11 | Stream outputStream, 12 | Stream? csharpOutputStream = null, 13 | Stream? pdbStream = null, 14 | CancellationToken cancellationToken = default); 15 | } 16 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/ILocalReferenceExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface ILocalReferenceExpression : IExpression 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | string Identifier { get; } 12 | ILocal Local { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IPrefixUnaryOperatorExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface IPrefixUnaryOperatorExpression : IExpression 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | Operator Operator { get; } 12 | IExpression Expression { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IBinaryOperatorExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface IBinaryOperatorExpression : IExpression 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | 12 | IExpression Left { get; } 13 | Operator Operator { get; } 14 | IExpression Right { get; } 15 | } 16 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IConditionalExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface IConditionalExpression : IExpression 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | IExpression Condition { get; } 12 | IExpression IfFalse { get; } 13 | IExpression IfTrue { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IMethodPatch.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Collections.Immutable; 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 6 | { 7 | public interface IMethodPatch : IObjectPatch 8 | { 9 | [return: MaybeNull] 10 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 11 | => visitor.Visit(this); 12 | 13 | IMethod Method { get; } 14 | ImmutableArray TypeArguments { get; } 15 | } 16 | } -------------------------------------------------------------------------------- /source/flc/FlcException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace FluentLang.flc 5 | { 6 | [Serializable] 7 | public class FlcException : Exception 8 | { 9 | public FlcException(string? message) : base(message) 10 | { 11 | } 12 | 13 | public FlcException(string? message, Exception? innerException) : base(message, innerException) 14 | { 15 | } 16 | 17 | protected FlcException(SerializationInfo info, StreamingContext context) : base(info, context) 18 | { 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IMemberInvocationExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface IMemberInvocationExpression : IInvocationExpression 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | IExpression Expression { get; } 12 | IInterfaceMethod Method { get; } 13 | string MemberName { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IMatchExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Collections.Immutable; 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 6 | { 7 | public interface IMatchExpression : IExpression 8 | { 9 | [return: MaybeNull] 10 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 11 | => visitor.Visit(this); 12 | 13 | IExpression Expression { get; } 14 | 15 | ImmutableArray Arms { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IMatchExpressionArm.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface IMatchExpressionArm : IVisitableSymbol 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | IType Type { get; } 12 | string? IdentifierName { get; } 13 | ILocal? Local { get; } 14 | IExpression Expression { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/MethodBody/ParameterLocal.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using FluentLang.Compiler.Symbols.Interfaces.MethodBody; 3 | 4 | namespace FluentLang.Compiler.Symbols.Source.MethodBody 5 | { 6 | public class ParameterLocal : IParameterLocal 7 | { 8 | public ParameterLocal(IParameter parameter) 9 | { 10 | Parameter = parameter; 11 | } 12 | 13 | public string Identifier => Parameter.Name; 14 | 15 | public IType Type => Parameter.Type; 16 | 17 | public IParameter Parameter { get; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /source/Compiler/Emit/DictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FluentLang.Compiler.Emit 5 | { 6 | internal static class DictionaryExtensions 7 | { 8 | public static TValue GetOrAdd( 9 | this Dictionary dict, 10 | TKey key, 11 | Func valueGenerator) 12 | { 13 | if (dict.TryGetValue(key, out var value)) 14 | { 15 | return value; 16 | } 17 | var result = valueGenerator(key); 18 | dict.Add(key, result); 19 | return result; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /source/Runtime/Metadata/MethodSignatureAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluentLang.Runtime.Metadata 4 | { 5 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] 6 | public class MethodSignatureAttribute : Attribute 7 | { 8 | public MethodSignatureAttribute(string signature, string[] requireMethodKeySignatures) 9 | { 10 | Signature = signature; 11 | RequireMethodKeySignatures = requireMethodKeySignatures; 12 | } 13 | 14 | public string Signature { get; } 15 | public string[] RequireMethodKeySignatures { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/SymbolHelpers.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols 5 | { 6 | public static class SymbolHelpers 7 | { 8 | public static bool TryFindBestType(IType a, IType b, [NotNullWhen(true)] out IType? type) 9 | { 10 | if (a.IsSubtypeOf(b)) 11 | { 12 | type = b; 13 | return true; 14 | } 15 | if (b.IsSubtypeOf(a)) 16 | { 17 | type = a; 18 | return true; 19 | } 20 | type = null; 21 | return false; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /source/Shared/AsyncEnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.Immutable; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace FluentLang.Shared 8 | { 9 | public static class AsyncEnumerableExtensions 10 | { 11 | public static async ValueTask> ToImmutableArrayAsync(this IAsyncEnumerable @this, CancellationToken cancellationToken = default) 12 | { 13 | return (await @this.ToArrayAsync(cancellationToken)).UnsafeAsImmutableArray(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /source/flc/DependencyLoading/IProjectLoader.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using FluentLang.flc.ProjectSystem; 3 | using System.Collections.Generic; 4 | using System.Runtime.Loader; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace FluentLang.flc.DependencyLoading 9 | { 10 | public interface IProjectLoader 11 | { 12 | ValueTask LoadProjectAsync(ProjectInfo projectInfo, AssemblyLoadContext assemblyLoadContext, IEnumerable alreadyLoadedProjects, CancellationToken cancellationToken = default); 13 | } 14 | } -------------------------------------------------------------------------------- /source/TestUtils/TestUtils.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | FluentLang.TestUtils 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /source/flc/DependencyLoading/DependencyAttributeReader.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Metadata; 2 | using FluentLang.Runtime.Metadata; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | namespace FluentLang.flc.DependencyLoading 8 | { 9 | public class DependencyAttributeReader 10 | { 11 | public IEnumerable ReadDependencies(Assembly assembly) 12 | { 13 | return 14 | assembly 15 | .GetAttributes() 16 | .Select(x => new Dependency(x.Name, x.Version)); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /source/Shared/Shared.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | FluentLang.Shared 6 | latest 7 | enable 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IDeclarationStatement.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 5 | { 6 | public interface IDeclarationStatement : IStatement 7 | { 8 | [return: MaybeNull] 9 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 10 | => visitor.Visit(this); 11 | IExpression Expression { get; } 12 | string? IdentifierName { get; } 13 | IType? DeclaredType { get; } 14 | IType Type { get; } 15 | IDeclaredLocal? Local { get; } 16 | } 17 | } -------------------------------------------------------------------------------- /source/TestUtils/WorkItemAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluentLang.TestUtils 4 | { 5 | /// 6 | /// Used to tag test methods or types which are created for a given WorkItem 7 | /// 8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] 9 | public sealed class WorkItemAttribute : Attribute 10 | { 11 | /// The URI where the work item can be viewed. 12 | public WorkItemAttribute(string issueUri) 13 | { 14 | IssueUri = issueUri; 15 | } 16 | 17 | public string IssueUri { get; } 18 | } 19 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IObjectPatchingExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Source.MethodBody; 2 | using FluentLang.Compiler.Symbols.Visitor; 3 | using System.Collections.Immutable; 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 7 | { 8 | public interface IObjectPatchingExpression : IExpression 9 | { 10 | [return: MaybeNull] 11 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 12 | => visitor.Visit(this); 13 | IExpression Expression { get; } 14 | ImmutableArray Patches { get; } 15 | } 16 | } -------------------------------------------------------------------------------- /source/Compiler.Tests.Unit/Parsing/ParserErrorTests.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.TestUtils; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace FluentLang.Compiler.Tests.Unit.Parsing 7 | { 8 | public class ParserErrorTests : TestBase 9 | { 10 | public ParserErrorTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) 11 | { 12 | } 13 | 14 | [Fact] 15 | public void ReportInvalidToken() 16 | { 17 | CreateAssembly("#!~@`") 18 | .VerifyDiagnostics( 19 | new Diagnostic(new Location(new TextToken(@"#")), ErrorCode.SyntaxError)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /source/Compiler/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. 3 | // Project-level suppressions either have no target or are given 4 | // a specific target and scoped to a namespace, type, member, etc. 5 | 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | [assembly: SuppressMessage("Style", "IDE0045:Convert to conditional expression", Justification = "", Scope = "member", Target = "~M:FluentLang.Compiler.Emit.FluentlangToCSharpEmitter.Impl.EmitRequiredMethodKeyArguments(FluentLang.Compiler.Symbols.Interfaces.IMethod,System.IO.TextWriter)")] 9 | -------------------------------------------------------------------------------- /source/flc/DependencyLoading/IDependencyLoader.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using FluentLang.flc.ProjectSystem; 3 | using System.Collections.Generic; 4 | using System.Collections.Immutable; 5 | using System.Runtime.Loader; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace FluentLang.flc.DependencyLoading 10 | { 11 | public interface IDependencyLoader 12 | { 13 | ValueTask> LoadDependenciesAsync(ProjectInfo project, AssemblyLoadContext assemblyLoadContext, IEnumerable alreadyLoadedProjects, CancellationToken cancellationToken = default); 14 | } 15 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/IType.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using FluentLang.Shared; 3 | using System.Collections.Generic; 4 | 5 | namespace FluentLang.Compiler.Symbols.Interfaces 6 | { 7 | public interface IType : IVisitableSymbol 8 | { 9 | public sealed bool IsEquivalentTo(IType other) => IsEquivalentTo(other, null); 10 | 11 | internal bool IsEquivalentTo(IType other, Stack<(IType, IType)>? dependantEqualities); 12 | 13 | public bool IsSubtypeOf(IType other); 14 | 15 | internal IType Substitute(ImmutableArrayDictionary substitutions, Dictionary substituted); 16 | } 17 | } -------------------------------------------------------------------------------- /source/Runtime/Metadata/InterfaceAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluentLang.Runtime.Metadata 4 | { 5 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] 6 | public class InterfaceAttribute : Attribute 7 | { 8 | public InterfaceAttribute(string fullyQualifiedName, string anonymousInterfaceDeclaration, string[] typeParameters) 9 | { 10 | FullyQualifiedName = fullyQualifiedName; 11 | AnonymousInterfaceDeclaration = anonymousInterfaceDeclaration; 12 | TypeParameters = typeParameters; 13 | } 14 | 15 | public string FullyQualifiedName { get; } 16 | public string AnonymousInterfaceDeclaration { get; } 17 | public string[] TypeParameters { get; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /source/Compiler/Emit/FluentlangToCSharpEmitter.MethodKeyOrParamName.cs: -------------------------------------------------------------------------------- 1 | namespace FluentLang.Compiler.Emit 2 | { 3 | public partial class FluentlangToCSharpEmitter 4 | { 5 | private abstract class MethodKeyOrParamName 6 | { 7 | private MethodKeyOrParamName() { } 8 | 9 | public sealed class MethodKey : MethodKeyOrParamName 10 | { 11 | public MethodKey(string value) 12 | { 13 | Value = value; 14 | } 15 | 16 | public string Value { get; } 17 | } 18 | 19 | public sealed class ParamName : MethodKeyOrParamName 20 | { 21 | public ParamName(string value) 22 | { 23 | Value = value; 24 | } 25 | 26 | public string Value { get; } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /source/Shared/ImmutableArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using System.IO; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace FluentLang.Shared 6 | { 7 | public static class ImmutableArrayExtensions 8 | { 9 | public static T[] UnsafeAsArray(this ImmutableArray array) 10 | { 11 | return Unsafe.As, T[]>(ref array); 12 | } 13 | 14 | public static Stream ToStream(this ImmutableArray bytes) 15 | { 16 | return new MemoryStream(bytes.UnsafeAsArray(), writable: false); 17 | } 18 | 19 | public static ImmutableArray EmptyIfDefault(this ImmutableArray array) 20 | { 21 | return array.IsDefault ? ImmutableArray.Empty : array; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/MethodBody/IStaticInvocationExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using System.Collections.Immutable; 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | namespace FluentLang.Compiler.Symbols.Interfaces.MethodBody 6 | { 7 | public interface IStaticInvocationExpression : IInvocationExpression 8 | { 9 | [return: MaybeNull] 10 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 11 | => visitor.Visit(this); 12 | IMethod Method { get; } 13 | QualifiedName MethodName { get; } 14 | ImmutableArray TypeArguments { get; } 15 | } 16 | 17 | public interface IPipedStaticInvocationExpression : IStaticInvocationExpression 18 | { 19 | new string MethodName { get; } 20 | } 21 | } -------------------------------------------------------------------------------- /source/Compiler/Diagnostics/Diagnostic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Immutable; 4 | using System.Text; 5 | 6 | namespace FluentLang.Compiler.Diagnostics 7 | { 8 | public class Diagnostic 9 | { 10 | public Diagnostic(Location location, ErrorCode errorCode, ImmutableArray additionalContext = default) 11 | { 12 | Location = location; 13 | ErrorCode = errorCode; 14 | if (additionalContext.IsDefault) 15 | additionalContext = ImmutableArray.Empty; 16 | AdditionalContext = additionalContext; 17 | } 18 | 19 | public Location Location { get; } 20 | public ErrorCode ErrorCode { get; } 21 | public ImmutableArray AdditionalContext { get; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/ErrorSymbols/ErrorParameter.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using System.Collections.Immutable; 4 | 5 | namespace FluentLang.Compiler.Symbols.ErrorSymbols 6 | { 7 | public class ErrorParameter : IParameter, IErrorSymbol 8 | { 9 | public static ErrorParameter Instance = new ErrorParameter(); 10 | 11 | private ErrorParameter() { } 12 | 13 | public string Name => ""; 14 | 15 | public IType Type => ErrorType.Instance; 16 | 17 | public ImmutableArray AllDiagnostics => ImmutableArray.Empty; 18 | 19 | void ISymbol.EnsureAllLocalDiagnosticsCollected() 20 | { 21 | throw new System.NotImplementedException(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/MethodBody/DeclaredLocal.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using FluentLang.Compiler.Symbols.Interfaces.MethodBody; 3 | using System; 4 | 5 | namespace FluentLang.Compiler.Symbols.Source.MethodBody 6 | { 7 | internal class DeclaredLocal : IDeclaredLocal 8 | { 9 | public DeclaredLocal(IDeclarationStatement declaration) 10 | { 11 | Declaration = declaration; 12 | if (Declaration.IdentifierName is null) 13 | throw new ArgumentNullException(nameof(Declaration) + "." + nameof(Declaration.IdentifierName)); 14 | } 15 | 16 | public IDeclarationStatement Declaration { get; } 17 | 18 | public string Identifier => Declaration.IdentifierName!; 19 | 20 | public IType Type => Declaration.Type; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/MethodBody/NewObjectExpression.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Compiler.Symbols.Interfaces.MethodBody; 4 | using System.Collections.Immutable; 5 | 6 | namespace FluentLang.Compiler.Symbols.Source.MethodBody 7 | { 8 | internal sealed class NewObjectExpression : INewObjectExpression 9 | { 10 | private NewObjectExpression() { } 11 | public static NewObjectExpression Instance { get; } = new NewObjectExpression(); 12 | 13 | public IType Type => EmptyInterface.Instance; 14 | 15 | ImmutableArray ISymbol.AllDiagnostics => ImmutableArray.Empty; 16 | 17 | void ISymbol.EnsureAllLocalDiagnosticsCollected() 18 | { 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/flc/DependencyLoading/Dependency.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluentLang.flc.DependencyLoading 4 | { 5 | public class Dependency : IEquatable 6 | { 7 | public Dependency(string name, string version) 8 | { 9 | Name = name; 10 | Version = version; 11 | } 12 | 13 | public string Name { get; } 14 | public string Version { get; } 15 | 16 | public override bool Equals(object? obj) 17 | { 18 | return Equals(obj as Dependency); 19 | } 20 | 21 | public bool Equals(Dependency? other) 22 | { 23 | return other != null && 24 | Name == other.Name && 25 | Version == other.Version; 26 | } 27 | 28 | public override int GetHashCode() 29 | { 30 | return HashCode.Combine(Name, Version); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /source/flc/DependencyLoading/GlobalPackagesFolderProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | 7 | namespace FluentLang.flc.DependencyLoading 8 | { 9 | public static class GlobalPackagesFolderProvider 10 | { 11 | public static string GlobalPackagesFolder => 12 | Environment.GetEnvironmentVariable("NUGET_PACKAGES", EnvironmentVariableTarget.Process) 13 | ?? Environment.GetEnvironmentVariable("NUGET_PACKAGES", EnvironmentVariableTarget.User) 14 | ?? Environment.GetEnvironmentVariable("NUGET_PACKAGES", EnvironmentVariableTarget.Machine) 15 | ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget/packages"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/IParameter.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Substituted; 2 | using FluentLang.Compiler.Symbols.Visitor; 3 | using FluentLang.Shared; 4 | using System.Collections.Generic; 5 | using System.Diagnostics.CodeAnalysis; 6 | 7 | namespace FluentLang.Compiler.Symbols.Interfaces 8 | { 9 | public interface IParameter : IVisitableSymbol 10 | { 11 | [return: MaybeNull] 12 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 13 | => visitor.Visit(this); 14 | public string Name { get; } 15 | public IType Type { get; } 16 | 17 | internal IParameter Substitute(ImmutableArrayDictionary substitutions, Dictionary substituted) 18 | => new SubstitutedParameter(this, substitutions, substituted); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /source/Compiler/Compilation/CompilationResult.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using System.Collections.Immutable; 3 | 4 | namespace FluentLang.Compiler.Compilation 5 | { 6 | public class CompilationResult 7 | { 8 | public CompilationResult( 9 | CompilationResultStatus status, ImmutableArray assemblyDiagnostics, 10 | ImmutableArray roslynDiagnostics) 11 | { 12 | Status = status; 13 | AssemblyDiagnostics = assemblyDiagnostics; 14 | RoslynDiagnostics = roslynDiagnostics; 15 | } 16 | 17 | public CompilationResultStatus Status { get; } 18 | 19 | public ImmutableArray AssemblyDiagnostics { get; } 20 | 21 | public ImmutableArray RoslynDiagnostics { get; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /source/Compiler/Parsing/DiagnosticErrorListener.cs: -------------------------------------------------------------------------------- 1 | using Antlr4.Runtime; 2 | using FluentLang.Compiler.Diagnostics; 3 | using System.Collections.Immutable; 4 | using System.IO; 5 | 6 | namespace FluentLang.Compiler.Parsing 7 | { 8 | public class DiagnosticErrorListener : BaseErrorListener 9 | { 10 | private readonly DiagnosticBag _diagnostics; 11 | 12 | public DiagnosticErrorListener(DiagnosticBag diagnostics) 13 | { 14 | _diagnostics = diagnostics; 15 | } 16 | 17 | public override void SyntaxError(TextWriter output, IRecognizer recognizer, IToken offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e) 18 | { 19 | _diagnostics.Add(new Diagnostic(new Location(offendingSymbol), ErrorCode.SyntaxError, ImmutableArray.Create(msg))); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /source/Compiler/Parsing/ParserFactory.cs: -------------------------------------------------------------------------------- 1 | using Antlr4.Runtime; 2 | using FluentLang.Compiler.Diagnostics; 3 | using FluentLang.Compiler.Generated; 4 | using System.IO; 5 | 6 | namespace FluentLang.Compiler.Parsing 7 | { 8 | public static class ParserFactory 9 | { 10 | public static FluentLangParser Create(string source, DiagnosticBag diagnostics) 11 | { 12 | using var reader = new StringReader(source); 13 | 14 | var input = new AntlrInputStream(reader); 15 | var lexer = new FluentLangLexer(input); 16 | var tokenStream = new CommonTokenStream(lexer); 17 | var parser = new FluentLangParser(tokenStream); 18 | 19 | var errorListener = new DiagnosticErrorListener(diagnostics); 20 | parser.RemoveErrorListeners(); 21 | parser.AddErrorListener(errorListener); 22 | 23 | return parser; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /source/Runtime/MethodKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluentLang.Runtime 4 | { 5 | public struct MethodKey : IEquatable 6 | { 7 | private readonly string _key; 8 | 9 | public MethodKey(string key) 10 | { 11 | _key = key; 12 | } 13 | 14 | public bool Equals(MethodKey other) 15 | { 16 | return other._key?.Equals(_key) ?? 17 | throw new InvalidOperationException($"{nameof(_key)} is null. Default MethodKeys are invalid."); 18 | } 19 | 20 | public override bool Equals(object? obj) 21 | { 22 | if (obj is MethodKey methodKey) 23 | return Equals(methodKey); 24 | 25 | return false; 26 | } 27 | 28 | public override int GetHashCode() 29 | { 30 | return _key.GetHashCode(); 31 | } 32 | 33 | public override string ToString() 34 | { 35 | return _key; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/flc/ProjectSystem/SolutionInfo.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Immutable; 3 | 4 | namespace FluentLang.flc.ProjectSystem 5 | { 6 | public class SolutionInfo 7 | { 8 | [JsonConstructor] 9 | public SolutionInfo(ImmutableArray projects, ImmutableArray libDirectories, ImmutableArray nugetFeeds) 10 | { 11 | Projects = projects.IsDefaultOrEmpty ? ImmutableArray.Empty : projects; 12 | LibDirectories = libDirectories.IsDefault ? ImmutableArray.Empty : libDirectories; 13 | NugetFeeds = nugetFeeds.IsDefault ? ImmutableArray.Empty : nugetFeeds; 14 | } 15 | 16 | public ImmutableArray Projects { get; } 17 | 18 | public ImmutableArray LibDirectories { get; } 19 | 20 | public ImmutableArray NugetFeeds { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /source/Compiler.Tests.Unit/Compiler.Tests.Unit.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | FluentLang.Compiler.Tests.Unit 6 | enable 7 | xUnit1019 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /source/TestUtils/TestInterface.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols; 3 | using FluentLang.Compiler.Symbols.Interfaces; 4 | using System.Collections.Immutable; 5 | 6 | namespace FluentLang.TestUtils 7 | { 8 | public class TestInterface : IInterface 9 | { 10 | public QualifiedName? FullyQualifiedName { get; set; } 11 | 12 | public bool IsExported => false; 13 | 14 | public ImmutableArray TypeParameters => ImmutableArray.Empty; 15 | 16 | public ImmutableArray TypeArguments => ImmutableArray.Empty; 17 | 18 | public ImmutableArray Methods { get; set; } = ImmutableArray.Empty; 19 | 20 | public ImmutableArray AllDiagnostics { get; set; } = ImmutableArray.Empty; 21 | 22 | void ISymbol.EnsureAllLocalDiagnosticsCollected() { } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/ErrorSymbols/ErrorInterfaceMethod.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using System.Collections.Immutable; 4 | using System.Linq; 5 | 6 | namespace FluentLang.Compiler.Symbols.ErrorSymbols 7 | { 8 | public class ErrorInterfaceMethod : IInterfaceMethod, IErrorSymbol 9 | { 10 | public ErrorInterfaceMethod(string name, int numParameters) 11 | { 12 | Name = name; 13 | Parameters = Enumerable.Repeat(ErrorParameter.Instance, numParameters).ToImmutableArray(); 14 | } 15 | 16 | public string Name { get; } 17 | 18 | public IType ReturnType => ErrorType.Instance; 19 | 20 | public ImmutableArray Parameters { get; } 21 | 22 | public ImmutableArray AllDiagnostics => ImmutableArray.Empty; 23 | 24 | void ISymbol.EnsureAllLocalDiagnosticsCollected(){ } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /source/TestUtils/XunitLogger.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using System; 3 | using Xunit.Abstractions; 4 | 5 | namespace FluentLang.TestUtils 6 | { 7 | public class XunitLogger : ILogger, IDisposable 8 | { 9 | private readonly ITestOutputHelper _output; 10 | 11 | public XunitLogger(ITestOutputHelper output) 12 | { 13 | _output = output; 14 | } 15 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) where TState : notnull 16 | { 17 | _output.WriteLine($"{logLevel.ToString().ToUpper()}: {formatter(state, exception)}"); 18 | } 19 | 20 | public bool IsEnabled(LogLevel logLevel) 21 | { 22 | return true; 23 | } 24 | 25 | public IDisposable BeginScope(TState state) 26 | { 27 | return this; 28 | } 29 | 30 | public void Dispose() 31 | { 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /source/Runtime/Union.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FluentLang.Runtime 4 | { 5 | public class Union 6 | { 7 | public Union(object inner, ulong matchingOptions) 8 | { 9 | Inner = inner; 10 | MatchingOptions = matchingOptions; 11 | } 12 | 13 | public Union(Union union, Span matchingTargetOptionsPerOption) 14 | : this(union.Inner, union.GetUpcastToUnionMatchingOptions(matchingTargetOptionsPerOption)) 15 | { 16 | } 17 | 18 | public object Inner { get; } 19 | public ulong MatchingOptions { get; } 20 | 21 | private ulong GetUpcastToUnionMatchingOptions(Span matchingTargetOptionsPerOption) 22 | { 23 | ulong bits = 0; 24 | for (var i = 0; i < matchingTargetOptionsPerOption.Length; i++) 25 | { 26 | if ((MatchingOptions & ((ulong)1 << i)) != 0) 27 | { 28 | bits |= matchingTargetOptionsPerOption[i]; 29 | } 30 | } 31 | 32 | return bits; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /source/Shared/Release.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace FluentLang.Shared 5 | { 6 | public static class Release 7 | { 8 | public static void Assert([DoesNotReturnIf(false)] bool condition) 9 | { 10 | Assert(condition, string.Empty); 11 | } 12 | 13 | public static void Assert([DoesNotReturnIf(false)] bool condition, string? message) 14 | { 15 | if (!condition) 16 | Fail(message); 17 | } 18 | 19 | /// 20 | /// Throws an 21 | /// 22 | /// Returns an exception so that for flow control analysis you can write `throw Release.Fail()` 23 | /// However this will never actually occur. 24 | /// 25 | /// 26 | /// 27 | [DoesNotReturn] 28 | public static Exception Fail(string? message) 29 | { 30 | throw new InvalidOperationException(message); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /source/TestUtils/TextToken.cs: -------------------------------------------------------------------------------- 1 | using Antlr4.Runtime; 2 | 3 | namespace FluentLang.TestUtils 4 | { 5 | public class TextToken : IToken 6 | { 7 | public TextToken(string text) 8 | { 9 | Text = text; 10 | } 11 | 12 | public string Text { get; } 13 | 14 | public int Type => throw new System.NotImplementedException(); 15 | 16 | public int Line => throw new System.NotImplementedException(); 17 | 18 | public int Column => throw new System.NotImplementedException(); 19 | 20 | public int Channel => throw new System.NotImplementedException(); 21 | 22 | public int TokenIndex => throw new System.NotImplementedException(); 23 | 24 | public int StartIndex => throw new System.NotImplementedException(); 25 | 26 | public int StopIndex => throw new System.NotImplementedException(); 27 | 28 | public ITokenSource TokenSource => throw new System.NotImplementedException(); 29 | 30 | public ICharStream InputStream => throw new System.NotImplementedException(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /source/flc.Tests.Unit/flc.Tests.Unit.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | FluentLang.Compiler.Tests.Unit 6 | enable 7 | xUnit1019 8 | 9.0 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /source/Compiler.Tests.Unit/Symbols/SourceSymbols/MethodBodyTests/NewObjectExpressionTests.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces.MethodBody; 2 | using FluentLang.Compiler.Symbols.Source.MethodBody; 3 | using FluentLang.TestUtils; 4 | using System.Linq; 5 | using Xunit; 6 | using Xunit.Abstractions; 7 | 8 | namespace FluentLang.Compiler.Tests.Unit.Symbols.SourceSymbols.MethodBodyTests 9 | { 10 | public class NewObjectExpressionTests : TestBase 11 | { 12 | public NewObjectExpressionTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) 13 | { 14 | } 15 | 16 | [Fact] 17 | public void CanParseNewObjectExpression() 18 | { 19 | var assembly = CreateAssembly(@" 20 | M() : {} { 21 | return {}; 22 | }").VerifyDiagnostics().VerifyEmit(); 23 | var m = AssertGetMethod(assembly, "M"); 24 | var returnStatement = Assert.IsAssignableFrom(m.Statements.Single()); 25 | Assert.IsAssignableFrom(returnStatement.Expression); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /source/Compiler/Emit/LocalSystemDllsMetadataReferenceProvider.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Runtime; 2 | using Microsoft.CodeAnalysis; 3 | using System.Collections.Immutable; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace FluentLang.Compiler.Emit 8 | { 9 | public class LocalSystemDllsMetadataReferenceProvider : IMetadataReferenceProvider 10 | { 11 | private LocalSystemDllsMetadataReferenceProvider() 12 | { 13 | 14 | } 15 | 16 | public static LocalSystemDllsMetadataReferenceProvider Instance { get; } = new LocalSystemDllsMetadataReferenceProvider(); 17 | 18 | public ImmutableArray MetadataReferences { get; } = 19 | Directory.GetFiles(Path.GetDirectoryName(typeof(object).Assembly.Location), "System.*.dll") 20 | .Concat(Directory.GetFiles(Path.GetDirectoryName(typeof(object).Assembly.Location), "netstandard.dll")) 21 | .Append(typeof(FLObject).Assembly.Location) 22 | .Select(x => MetadataReference.CreateFromFile(x)) 23 | .ToImmutableArray(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/MethodBody/EmptyInterface.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using System.Collections.Immutable; 4 | 5 | namespace FluentLang.Compiler.Symbols.Source.MethodBody 6 | { 7 | internal sealed class EmptyInterface : IInterface 8 | { 9 | private EmptyInterface() { } 10 | 11 | public static EmptyInterface Instance { get; } = new EmptyInterface(); 12 | 13 | public QualifiedName? FullyQualifiedName => null; 14 | 15 | public bool IsExported => false; 16 | 17 | public ImmutableArray TypeParameters => ImmutableArray.Empty; 18 | 19 | public ImmutableArray TypeArguments => ImmutableArray.Empty; 20 | 21 | public ImmutableArray Methods => ImmutableArray.Empty; 22 | 23 | public ImmutableArray AllDiagnostics => ImmutableArray.Empty; 24 | 25 | void ISymbol.EnsureAllLocalDiagnosticsCollected() 26 | { 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /source/Compiler/Diagnostics/DiagnosticFormatter.cs: -------------------------------------------------------------------------------- 1 | using Antlr4.Runtime; 2 | using System.Linq; 3 | 4 | namespace FluentLang.Compiler.Diagnostics 5 | { 6 | public class DiagnosticFormatter : IDiagnosticFormatter 7 | { 8 | public string CreateDiagnosticMessage(Diagnostic diagnostic) 9 | { 10 | return diagnostic.ErrorCode switch 11 | { 12 | //TODO: explicitly handle more errors. 13 | ErrorCode.InvalidMetadataAssembly => 14 | diagnostic.AdditionalContext.FirstOrDefault()?.ToString() ?? "", 15 | var errorCode => 16 | $"code: {errorCode}, text: {diagnostic.Location.GetText().ToString()}, aditionalContext: {string.Join(", ", diagnostic.AdditionalContext)}", 17 | }; 18 | } 19 | 20 | public string CreateLocationMessage(Diagnostic diagnostic) 21 | { 22 | //TODO: store file number. 23 | var location = diagnostic.Location.TextRange; 24 | return $"Start: [Ln {location.Start.Line}, Col {location.Start.Column}] End: [Ln {location.End.Line}, Col {location.End.Column}]"; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source/WebIde/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54390", 7 | "sslPort": 44368 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "WebIde": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 23 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Substituted/SubstitutedParameter.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Shared; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | 8 | namespace FluentLang.Compiler.Symbols.Substituted 9 | { 10 | internal class SubstitutedParameter : IParameter 11 | { 12 | private readonly IParameter _original; 13 | private readonly Lazy _type; 14 | 15 | public SubstitutedParameter(IParameter original, ImmutableArrayDictionary substitutions, Dictionary substituted) 16 | { 17 | _original = original; 18 | _type = new Lazy(() => _original.Type.Substitute(substitutions, substituted)); 19 | } 20 | 21 | public string Name => _original.Name; 22 | 23 | public IType Type => _type.Value; 24 | 25 | public ImmutableArray AllDiagnostics => ImmutableArray.Empty; 26 | 27 | void ISymbol.EnsureAllLocalDiagnosticsCollected() { } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/SymbolBase.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using System; 4 | using System.Collections.Immutable; 5 | 6 | namespace FluentLang.Compiler.Symbols.Source 7 | { 8 | public abstract class SymbolBase : ISymbol 9 | { 10 | protected readonly DiagnosticBag _diagnostics; 11 | private readonly Lazy> _allDiagnostics; 12 | 13 | public SymbolBase(DiagnosticBag diagnostics) 14 | { 15 | _diagnostics = diagnostics.CreateChildBag(this); 16 | _allDiagnostics = new Lazy>(() => 17 | { 18 | _diagnostics.EnsureAllDiagnosticsCollectedForSymbol(); 19 | return _diagnostics.ToImmutableArray(); 20 | }); 21 | } 22 | 23 | public ImmutableArray AllDiagnostics => _allDiagnostics.Value; 24 | 25 | void ISymbol.EnsureAllLocalDiagnosticsCollected() 26 | { 27 | EnsureAllLocalDiagnosticsCollected(); 28 | } 29 | 30 | protected abstract void EnsureAllLocalDiagnosticsCollected(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /source/Compiler.Tests.Unit/Symbols/SourceSymbols/SourceUnionTests.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Compiler.Symbols.Source.MethodBody; 4 | using FluentLang.TestUtils; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using Xunit; 10 | using Xunit.Abstractions; 11 | 12 | namespace FluentLang.Compiler.Tests.Unit.Symbols.SourceSymbols 13 | { 14 | public class SourceUnionTests : TestBase 15 | { 16 | public SourceUnionTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) 17 | { 18 | } 19 | 20 | [Fact] 21 | public void CanParseUnion() 22 | { 23 | var assembly = CreateAssembly("M() : int | {} { return 42; }").VerifyDiagnostics().VerifyEmit(); 24 | var m = AssertGetMethod(assembly, "M"); 25 | var union = Assert.IsAssignableFrom(m.ReturnType); 26 | Assert.Equal(Primitive.Int, union.Options[0]); 27 | Assert.True(union.Options[1].IsEquivalentTo(EmptyInterface.Instance)); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /source/Compiler/Compiler.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | FluentLang.Compiler 6 | enable 7 | true 8 | CS3021,CS8717 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Substituted/SubstitutedUnion.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Shared; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.Linq; 8 | 9 | namespace FluentLang.Compiler.Symbols.Substituted 10 | { 11 | internal class SubstitutedUnion : IUnion 12 | { 13 | private readonly Lazy> _options; 14 | 15 | public SubstitutedUnion(IUnion original, ImmutableArrayDictionary substitutions, Dictionary substituted) 16 | { 17 | substituted.Add(original, this); 18 | substituted.Add(this, this); 19 | _options = new Lazy>( 20 | () => original.Options.Select(x => x.Substitute(substitutions, substituted)).ToImmutableArray()); 21 | } 22 | 23 | public ImmutableArray Options => _options.Value; 24 | 25 | public ImmutableArray AllDiagnostics => ImmutableArray.Empty; 26 | 27 | void ISymbol.EnsureAllLocalDiagnosticsCollected() { } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /source/flc.Tests.Integration/flc.Tests.Integration.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | FluentLang.Compiler.Tests.Integration 6 | enable 7 | xUnit1019 8 | preview 9 | 10 | 11 | 12 | 13 | PreserveNewest 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | all 22 | runtime; build; native; contentfiles; analyzers; buildtransitive 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /source/flc/ProjectSystem/Reference.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.ComponentModel; 4 | 5 | namespace FluentLang.flc.ProjectSystem 6 | { 7 | public sealed class Reference 8 | { 9 | [JsonConstructor] 10 | public Reference( 11 | ReferenceType type, 12 | string name, 13 | string? version = null) 14 | { 15 | if (type == ReferenceType.Project && version is { }) 16 | throw new ArgumentException("Project reference cannot specify a version", nameof(version)); 17 | 18 | if (type == ReferenceType.Assembly && version is null) 19 | throw new ArgumentException("Assembly reference must specify a version", nameof(version)); 20 | 21 | if (type != ReferenceType.Assembly && type != ReferenceType.Project) 22 | throw new InvalidEnumArgumentException(nameof(type), (int)type, typeof(ReferenceType)); 23 | 24 | Type = type; 25 | Name = name; 26 | Version = version; 27 | } 28 | 29 | public ReferenceType Type { get; } 30 | public string Name { get; } 31 | public string? Version { get; } 32 | 33 | public enum ReferenceType 34 | { 35 | Assembly, 36 | Project, 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /source/Runtime/Runtime.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | FluentLang.Runtime 6 | latest 7 | enable 8 | true 9 | CS3021,CS8717 10 | true 11 | snupkg 12 | true 13 | FluentLang.Runtime 14 | 1.0.0 15 | FluentLang 16 | FluentLang 17 | FluentLang 18 | .Net based Runtime for the FluentLang Language. 19 | 20 | MIT 21 | https://github.com/YairHalberstadt/fluentlang/ 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Yair Halberstadt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Metadata/Utils.cs: -------------------------------------------------------------------------------- 1 | using Antlr4.Runtime; 2 | using FluentLang.Compiler.Diagnostics; 3 | using FluentLang.Compiler.Generated; 4 | using FluentLang.Compiler.Parsing; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Diagnostics.CodeAnalysis; 8 | using System.IO; 9 | using System.Reflection; 10 | using System.Text; 11 | using DiagnosticErrorListener = FluentLang.Compiler.Parsing.DiagnosticErrorListener; 12 | 13 | namespace FluentLang.Compiler.Symbols.Metadata 14 | { 15 | public static class Utils 16 | { 17 | public static T? GetAttribute(this MethodInfo method) where T : Attribute 18 | { 19 | return Attribute.GetCustomAttribute(method, typeof(T)) as T; 20 | } 21 | 22 | public static T[] GetAttributes(this Assembly assembly) where T : Attribute 23 | { 24 | return (T[])Attribute.GetCustomAttributes(assembly, typeof(T)); 25 | } 26 | 27 | public static T Parse(string source, Func getT, DiagnosticBag diagnostics) where T : ParserRuleContext 28 | { 29 | var parser = ParserFactory.Create(source, diagnostics); 30 | 31 | var t = getT(parser); 32 | return t; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /source/WebIde/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /source/flc.Tests.Unit/DependencyInjectionTests.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.flc.DependencyInjection; 2 | using FluentLang.flc.DependencyLoading; 3 | using FluentLang.flc.ProjectSystem; 4 | using Microsoft.Extensions.Logging; 5 | using StrongInject; 6 | using System; 7 | using System.Threading.Tasks; 8 | using Xunit; 9 | 10 | namespace FluentLang.Compiler.Tests.Unit 11 | { 12 | public partial class DependencyInjectionTests 13 | { 14 | [Fact] 15 | public async Task CanResolveCompiler() 16 | { 17 | await using var container = new FlcContainer(LogLevel.Information); 18 | await container.RunAsync(compiler => Assert.NotNull(compiler)); 19 | } 20 | 21 | [RegisterModule(typeof(FlcModule))] 22 | public partial class ProjectLoaderContainer : IContainer> 23 | { 24 | [Instance] private readonly LogLevel _logLevel; 25 | 26 | public ProjectLoaderContainer(LogLevel logLevel) 27 | { 28 | _logLevel = logLevel; 29 | } 30 | } 31 | 32 | [Fact] 33 | public void CanResolveProjectLoader() 34 | { 35 | using var container = new ProjectLoaderContainer(LogLevel.Information); 36 | container.Run(func => Assert.NotNull(func(new SolutionInfo(default, default, default)))); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/AssemblyFactory.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Compilation; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Compiler.Symbols.Metadata; 4 | using FluentLang.Compiler.Symbols.Source; 5 | using System.Collections.Immutable; 6 | using System.Reflection; 7 | 8 | namespace FluentLang.Compiler.Symbols 9 | { 10 | public class AssemblyFactory 11 | { 12 | private readonly IAssemblyCompiler _assemblyCompiler; 13 | 14 | public AssemblyFactory(IAssemblyCompiler assemblyCompiler) 15 | { 16 | _assemblyCompiler = assemblyCompiler; 17 | } 18 | 19 | public IAssembly FromSource( 20 | QualifiedName name, 21 | (int major, int minor, string? suffix) version, 22 | ImmutableArray directlyReferencedAssemblies, 23 | ImmutableArray documents) => new SourceAssembly( 24 | name, 25 | new Version(version.major, version.minor, version.suffix ?? ""), 26 | directlyReferencedAssemblies, 27 | documents, 28 | _assemblyCompiler); 29 | 30 | public IAssembly FromMetadata( 31 | Assembly assembly, 32 | ImmutableArray assemblyBytes, 33 | ImmutableArray dependencies) => 34 | new MetadataAssembly(assembly, assemblyBytes, dependencies); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/ITypeParameter.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Visitor; 2 | using FluentLang.Shared; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics.CodeAnalysis; 6 | 7 | namespace FluentLang.Compiler.Symbols.Interfaces 8 | { 9 | public interface ITypeParameter : IType, IEquatable 10 | { 11 | [return: MaybeNull] 12 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 13 | => visitor.Visit(this); 14 | 15 | public string Name { get; } 16 | public IType? ConstrainedTo { get; } 17 | 18 | bool IType.IsEquivalentTo(IType other, Stack<(IType, IType)>? dependantEqualities) 19 | { 20 | return ReferenceEquals(this, other); 21 | } 22 | 23 | bool IType.IsSubtypeOf(IType other) 24 | { 25 | return IsEquivalentTo(other) || (ConstrainedTo?.IsSubtypeOf(other) ?? false); 26 | } 27 | 28 | IType IType.Substitute(ImmutableArrayDictionary substitutions, Dictionary substituted) 29 | { 30 | return substitutions.TryGetValue(this, out var substitution) 31 | ? substitution 32 | : this; 33 | } 34 | 35 | bool IEquatable.Equals(ITypeParameter other) => ReferenceEquals(this, other); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/SourceParameter.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using System; 4 | using System.Collections.Immutable; 5 | using static FluentLang.Compiler.Generated.FluentLangParser; 6 | 7 | namespace FluentLang.Compiler.Symbols.Source 8 | { 9 | internal class SourceParameter : SymbolBase, IParameter 10 | { 11 | private readonly ParameterContext _context; 12 | private readonly SourceSymbolContext _sourceSymbolContext; 13 | private readonly Lazy _type; 14 | 15 | public SourceParameter( 16 | ParameterContext context, 17 | SourceSymbolContext sourceSymbolContext, 18 | bool isExported, 19 | DiagnosticBag diagnostics) : base(diagnostics) 20 | { 21 | _context = context; 22 | _sourceSymbolContext = sourceSymbolContext; 23 | Name = _context.LOWERCASE_IDENTIFIER().Symbol.Text; 24 | _type = new Lazy(() => _context.type_declaration().type().BindType(_sourceSymbolContext, isExported, _diagnostics)); 25 | } 26 | public string Name { get; } 27 | 28 | public IType Type => _type.Value; 29 | 30 | protected override void EnsureAllLocalDiagnosticsCollected() 31 | { 32 | // Touch all lazy fields to force binding; 33 | 34 | _ = _type.Value; 35 | } 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /source/flc/flc.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0 6 | FluentLang.flc 7 | enable 8 | true 9 | CS3021,CS8717 10 | 9.0 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /source/WebIde/WebIde.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | 3.0 6 | FluentLang.WebIde 7 | latest 8 | enable 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/MethodBody/MethodBodySymbolContextExtensions.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Shared; 4 | using System.Collections.Immutable; 5 | using static FluentLang.Compiler.Generated.FluentLangParser; 6 | 7 | namespace FluentLang.Compiler.Symbols.Source.MethodBody 8 | { 9 | internal static class MethodBodySymbolContextExtensions 10 | { 11 | public static void WarnIfUseOfMethodWhichCapturesUnassignedLocals(this MethodBodySymbolContext methodBodySymbolContext, IMethod target, DiagnosticBag diagnostics, Method_referenceContext syntax) 12 | { 13 | var currentMethod = methodBodySymbolContext.SourceSymbolContext.Scope; 14 | Release.Assert(currentMethod != null); 15 | if (target.DeclaringMethod == currentMethod) 16 | { 17 | if (target.InScopeAfter is { } declarationStatement) 18 | { 19 | var currentStatement = methodBodySymbolContext.CurrentStatement; 20 | Release.Assert(currentStatement != null); 21 | if (declarationStatement.OrdinalPositionInMethod >= currentStatement.OrdinalPositionInMethod) 22 | { 23 | diagnostics.Add(new Diagnostic( 24 | new Location(syntax), 25 | ErrorCode.UseOfMethodWhichCapturesUnassignedLocals, 26 | ImmutableArray.Create(target))); 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Substituted/ConstructedInterface.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Compiler.Symbols.Source; 4 | using System.Collections.Generic; 5 | using System.Collections.Immutable; 6 | 7 | namespace FluentLang.Compiler.Symbols.Substituted 8 | { 9 | internal class ConstructedInterface : IInterface 10 | { 11 | private readonly SubstitutedInterface _substituted; 12 | 13 | public ConstructedInterface(IInterface original, ImmutableArray typeArguments) 14 | { 15 | _substituted = new SubstitutedInterface( 16 | original, 17 | SourceSymbolContextExtensions.CreateTypeMap(typeArguments, original.TypeParameters), 18 | new Dictionary()); 19 | 20 | TypeArguments = typeArguments; 21 | } 22 | 23 | public bool IsExported => _substituted.IsExported; 24 | 25 | public QualifiedName? FullyQualifiedName => _substituted.FullyQualifiedName; 26 | 27 | public ImmutableArray Methods => _substituted.Methods; 28 | 29 | public ImmutableArray TypeParameters => ImmutableArray.Empty; 30 | 31 | public ImmutableArray AllDiagnostics => ImmutableArray.Empty; 32 | 33 | public ImmutableArray TypeArguments { get; } 34 | 35 | void ISymbol.EnsureAllLocalDiagnosticsCollected() 36 | { 37 | 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /source/Compiler/Generated/FluentLangLexer.tokens: -------------------------------------------------------------------------------- 1 | SINGLE_LINE_COMMENT=1 2 | WHITESPACES=2 3 | PLUS=3 4 | MINUS=4 5 | STAR=5 6 | DIV=6 7 | PERCENT=7 8 | LT=8 9 | GT=9 10 | OP_EQ=10 11 | OP_NE=11 12 | OP_LE=12 13 | OP_GE=13 14 | OP_AND=14 15 | OP_OR=15 16 | LOGICAL_OR=16 17 | ASSIGNMENT=17 18 | OPEN_BRACE=18 19 | CLOSE_BRACE=19 20 | OPEN_PARENS=20 21 | CLOSE_PARENS=21 22 | DOT=22 23 | COMMA=23 24 | COLON=24 25 | SEMICOLON=25 26 | DISCARD=26 27 | RIGHT_ARROW=27 28 | DOT_DOT=28 29 | BOOL=29 30 | INT=30 31 | DOUBLE=31 32 | CHAR=32 33 | STRING=33 34 | LITERAL_TRUE=34 35 | LITERAL_FALSE=35 36 | INTEGER_LITERAL=36 37 | REAL_LITERAL=37 38 | CHARACTER_LITERAL=38 39 | REGULAR_STRING=39 40 | NAMESPACE=40 41 | INTERFACE=41 42 | RETURN=42 43 | IF=43 44 | ELSE=44 45 | MIXIN=45 46 | EXPORT=46 47 | OPEN=47 48 | LET=48 49 | MATCH=49 50 | UPPERCASE_IDENTIFIER=50 51 | LOWERCASE_IDENTIFIER=51 52 | ErrorChar=52 53 | '+'=3 54 | '-'=4 55 | '*'=5 56 | '/'=6 57 | '%'=7 58 | '<'=8 59 | '>'=9 60 | '=='=10 61 | '!='=11 62 | '<='=12 63 | '>='=13 64 | '&&'=14 65 | '||'=15 66 | '|'=16 67 | '='=17 68 | '{'=18 69 | '}'=19 70 | '('=20 71 | ')'=21 72 | '.'=22 73 | ','=23 74 | ':'=24 75 | ';'=25 76 | '_'=26 77 | '=>'=27 78 | '..'=28 79 | 'bool'=29 80 | 'int'=30 81 | 'double'=31 82 | 'char'=32 83 | 'string'=33 84 | 'true'=34 85 | 'false'=35 86 | 'namespace'=40 87 | 'interface'=41 88 | 'return'=42 89 | 'if'=43 90 | 'else'=44 91 | 'mixin'=45 92 | 'export'=46 93 | 'open'=47 94 | 'let'=48 95 | 'match'=49 96 | -------------------------------------------------------------------------------- /source/Compiler/Generated/FluentLangParser.tokens: -------------------------------------------------------------------------------- 1 | SINGLE_LINE_COMMENT=1 2 | WHITESPACES=2 3 | PLUS=3 4 | MINUS=4 5 | STAR=5 6 | DIV=6 7 | PERCENT=7 8 | LT=8 9 | GT=9 10 | OP_EQ=10 11 | OP_NE=11 12 | OP_LE=12 13 | OP_GE=13 14 | OP_AND=14 15 | OP_OR=15 16 | LOGICAL_OR=16 17 | ASSIGNMENT=17 18 | OPEN_BRACE=18 19 | CLOSE_BRACE=19 20 | OPEN_PARENS=20 21 | CLOSE_PARENS=21 22 | DOT=22 23 | COMMA=23 24 | COLON=24 25 | SEMICOLON=25 26 | DISCARD=26 27 | RIGHT_ARROW=27 28 | DOT_DOT=28 29 | BOOL=29 30 | INT=30 31 | DOUBLE=31 32 | CHAR=32 33 | STRING=33 34 | LITERAL_TRUE=34 35 | LITERAL_FALSE=35 36 | INTEGER_LITERAL=36 37 | REAL_LITERAL=37 38 | CHARACTER_LITERAL=38 39 | REGULAR_STRING=39 40 | NAMESPACE=40 41 | INTERFACE=41 42 | RETURN=42 43 | IF=43 44 | ELSE=44 45 | MIXIN=45 46 | EXPORT=46 47 | OPEN=47 48 | LET=48 49 | MATCH=49 50 | UPPERCASE_IDENTIFIER=50 51 | LOWERCASE_IDENTIFIER=51 52 | ErrorChar=52 53 | '+'=3 54 | '-'=4 55 | '*'=5 56 | '/'=6 57 | '%'=7 58 | '<'=8 59 | '>'=9 60 | '=='=10 61 | '!='=11 62 | '<='=12 63 | '>='=13 64 | '&&'=14 65 | '||'=15 66 | '|'=16 67 | '='=17 68 | '{'=18 69 | '}'=19 70 | '('=20 71 | ')'=21 72 | '.'=22 73 | ','=23 74 | ':'=24 75 | ';'=25 76 | '_'=26 77 | '=>'=27 78 | '..'=28 79 | 'bool'=29 80 | 'int'=30 81 | 'double'=31 82 | 'char'=32 83 | 'string'=33 84 | 'true'=34 85 | 'false'=35 86 | 'namespace'=40 87 | 'interface'=41 88 | 'return'=42 89 | 'if'=43 90 | 'else'=44 91 | 'mixin'=45 92 | 'export'=46 93 | 'open'=47 94 | 'let'=48 95 | 'match'=49 96 | -------------------------------------------------------------------------------- /source/flc/ProjectSystem/ProjectInfo.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Immutable; 4 | 5 | namespace FluentLang.flc.ProjectSystem 6 | { 7 | public class ProjectInfo 8 | { 9 | [JsonConstructor] 10 | public ProjectInfo( 11 | string name, 12 | Version version, 13 | ImmutableArray includedFilesAndFolders, 14 | ImmutableArray excludedFilesAndFolders = default, 15 | ImmutableArray references = default, 16 | bool isTest = false) 17 | { 18 | if (string.IsNullOrEmpty(name)) 19 | throw new ArgumentException("is null or empty", nameof(name)); 20 | Name = name; 21 | Version = version ?? throw new ArgumentNullException(nameof(version)); 22 | if (includedFilesAndFolders.IsDefaultOrEmpty) 23 | throw new ArgumentException("must include at least one file", nameof(includedFilesAndFolders)); 24 | IncludedFilesAndFolders = includedFilesAndFolders; 25 | IsTest = isTest; 26 | ExcludedFilesAndFolders = excludedFilesAndFolders.IsDefault ? ImmutableArray.Empty : excludedFilesAndFolders; 27 | References = references.IsDefault ? ImmutableArray.Empty: references; 28 | } 29 | 30 | public ImmutableArray IncludedFilesAndFolders { get; } 31 | public bool IsTest { get; } 32 | public ImmutableArray ExcludedFilesAndFolders { get; } 33 | public string Name { get; } 34 | public ImmutableArray References { get; } 35 | public Version Version { get; } 36 | } 37 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/MethodBody/ReturnStatement.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces.MethodBody; 3 | using System; 4 | using static FluentLang.Compiler.Generated.FluentLangParser; 5 | 6 | namespace FluentLang.Compiler.Symbols.Source.MethodBody 7 | { 8 | internal sealed class ReturnStatement : SymbolBase, IReturnStatement 9 | { 10 | private readonly Return_statementContext _context; 11 | private readonly MethodBodySymbolContext _methodBodySymbolContext; 12 | private readonly Lazy _expression; 13 | 14 | public ReturnStatement( 15 | Return_statementContext context, 16 | int ordinalPositionInMethod, 17 | MethodBodySymbolContext methodBodySymbolContext, 18 | DiagnosticBag diagnostics) : base(diagnostics) 19 | { 20 | _context = context; 21 | OrdinalPositionInMethod = ordinalPositionInMethod; 22 | _methodBodySymbolContext = methodBodySymbolContext.WithStatement(this); 23 | _expression = new Lazy(BindExpression); 24 | } 25 | 26 | private IExpression BindExpression() 27 | { 28 | return _context.expression().BindExpression(_methodBodySymbolContext, _diagnostics); 29 | } 30 | 31 | public IExpression Expression => _expression.Value; 32 | 33 | public int OrdinalPositionInMethod { get; } 34 | 35 | protected override void EnsureAllLocalDiagnosticsCollected() 36 | { 37 | // Touch all lazy fields to force binding; 38 | 39 | _ = _expression.Value; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/SourceSymbolContext.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using FluentLang.Shared; 3 | using System; 4 | using System.Collections.Immutable; 5 | 6 | namespace FluentLang.Compiler.Symbols.Source 7 | { 8 | internal class SourceSymbolContext 9 | { 10 | public SourceSymbolContext( 11 | IMethod? scope, 12 | IAssembly assembly, 13 | ImmutableArray imports, 14 | QualifiedName? nameSpace, 15 | Func> currentLevelTypeParameters) 16 | { 17 | Scope = scope; 18 | Assembly = assembly; 19 | Imports = imports.IsDefault ? throw Release.Fail("imports cannot be default") : imports; 20 | NameSpace = nameSpace; 21 | CurrentLevelTypeParameters = currentLevelTypeParameters; 22 | } 23 | 24 | public IMethod? Scope { get; } 25 | public Func> CurrentLevelTypeParameters { get; } 26 | public IAssembly Assembly { get; } 27 | public ImmutableArray Imports { get; } 28 | public QualifiedName? NameSpace { get; } 29 | public SourceSymbolContext WithScope(IMethod? scope) 30 | { 31 | return new SourceSymbolContext(scope, Assembly, Imports, NameSpace, () => ImmutableArray.Empty); 32 | } 33 | public SourceSymbolContext WithTypeParameters(Func> currentLevelTypeParameters) 34 | { 35 | return new SourceSymbolContext(Scope, Assembly, Imports, NameSpace, currentLevelTypeParameters); 36 | } 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/IInterfaceMethod.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Substituted; 2 | using FluentLang.Compiler.Symbols.Visitor; 3 | using FluentLang.Shared; 4 | using System.Collections.Generic; 5 | using System.Collections.Immutable; 6 | using System.Diagnostics.CodeAnalysis; 7 | using System.Linq; 8 | 9 | namespace FluentLang.Compiler.Symbols.Interfaces 10 | { 11 | public interface IInterfaceMethod : IVisitableSymbol 12 | { 13 | [return: MaybeNull] 14 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 15 | => visitor.Visit(this); 16 | 17 | public string Name { get; } 18 | public IType ReturnType { get; } 19 | public ImmutableArray Parameters { get; } 20 | public IInterfaceMethod OriginalDefinition => this; 21 | 22 | internal bool IsEquivalentTo(IInterfaceMethod otherMethod, Stack<(IType, IType)>? dependantEqualities) 23 | { 24 | if (Name != otherMethod.Name) 25 | return false; 26 | 27 | if (Parameters.Length != otherMethod.Parameters.Length) 28 | return false; 29 | 30 | if (!ReturnType.IsEquivalentTo(otherMethod.ReturnType, dependantEqualities)) 31 | return false; 32 | 33 | return Parameters.SequenceEqual(otherMethod.Parameters, (x, y) => x.Type.IsEquivalentTo(y.Type, dependantEqualities)); 34 | } 35 | 36 | internal IInterfaceMethod Substitute(ImmutableArrayDictionary substitutions, Dictionary substituted) 37 | => new SubstitutedInterfaceMethod(this, substitutions, substituted); 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Visitor/SymbolExtensions.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | namespace FluentLang.Compiler.Symbols.Visitor 7 | { 8 | public static class SymbolExtensions 9 | { 10 | public static IEnumerable DescendantNodes(this IVisitableSymbol symbol, Func? visitChildren = null, Func? includeSymbol = null) 11 | { 12 | var visitor = new CollectAllSymbolsVisitor( 13 | visitChildren ?? (_ => true), 14 | includeSymbol ?? (_ => true)); 15 | symbol.Visit(visitor); 16 | return visitor.Symbols; 17 | } 18 | 19 | private sealed class CollectAllSymbolsVisitor : BaseSymbolVisitor 20 | { 21 | public readonly List Symbols = new List(); 22 | 23 | private readonly Func _visitChildren; 24 | private readonly Func _includeSymbol; 25 | 26 | public CollectAllSymbolsVisitor(Func visitChildren, Func includeSymbol) 27 | { 28 | _visitChildren = visitChildren; 29 | _includeSymbol = includeSymbol; 30 | } 31 | 32 | [return: MaybeNull] 33 | protected override object DefaultVisit(IVisitableSymbol symbol) 34 | { 35 | if (_includeSymbol(symbol)) 36 | { 37 | Symbols.Add(symbol); 38 | } 39 | if (_visitChildren(symbol)) 40 | { 41 | return symbol.Visit(this); 42 | } 43 | return default; 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Interfaces/IUnion.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Substituted; 2 | using FluentLang.Compiler.Symbols.Visitor; 3 | using FluentLang.Shared; 4 | using System.Collections.Generic; 5 | using System.Collections.Immutable; 6 | using System.Diagnostics.CodeAnalysis; 7 | using System.Linq; 8 | 9 | namespace FluentLang.Compiler.Symbols.Interfaces 10 | { 11 | public interface IUnion : IType 12 | { 13 | [return: MaybeNull] 14 | T IVisitableSymbol.Visit(ISymbolVisitor visitor) 15 | => visitor.Visit(this); 16 | 17 | ImmutableArray Options { get; } 18 | 19 | bool IType.IsEquivalentTo(IType other, Stack<(IType, IType)>? dependantEqualities) 20 | { 21 | if (ReferenceEquals(this, other)) 22 | { 23 | return true; 24 | } 25 | 26 | if (other is IUnion union && Options.Length == union.Options.Length) 27 | { 28 | return 29 | Options 30 | .Zip(union.Options, (a, b) => a.IsEquivalentTo(b, dependantEqualities)) 31 | .All(x => x); 32 | } 33 | 34 | return false; 35 | } 36 | 37 | bool IType.IsSubtypeOf(IType other) 38 | { 39 | if (ReferenceEquals(this, other)) 40 | { 41 | return true; 42 | } 43 | 44 | return Options.All(x => x.IsSubtypeOf(other)); 45 | } 46 | 47 | IType IType.Substitute(ImmutableArrayDictionary substitutions, Dictionary substituted) 48 | => substituted.TryGetValue(this, out var substitution) ? substitution : new SubstitutedUnion(this, substitutions, substituted); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/SourceDocument.cs: -------------------------------------------------------------------------------- 1 | using Antlr4.Runtime; 2 | using FluentLang.Compiler.Diagnostics; 3 | using FluentLang.Compiler.Generated; 4 | using FluentLang.Compiler.Parsing; 5 | using FluentLang.Compiler.Symbols.Interfaces; 6 | using System; 7 | using System.Collections.Immutable; 8 | using System.IO; 9 | using static FluentLang.Compiler.Generated.FluentLangParser; 10 | using DiagnosticErrorListener = FluentLang.Compiler.Parsing.DiagnosticErrorListener; 11 | 12 | namespace FluentLang.Compiler.Symbols.Source 13 | { 14 | internal sealed class SourceDocument : IDocument 15 | { 16 | private readonly string _source; 17 | private readonly Lazy _syntaxTree; 18 | private ImmutableArray _diagnostics; 19 | 20 | public SourceDocument(string source) 21 | { 22 | _source = source; 23 | _syntaxTree = new Lazy(GetSyntaxTree); 24 | } 25 | 26 | public string FullName => "test.cs"; 27 | 28 | public Compilation_unitContext SyntaxTree => _syntaxTree.Value; 29 | 30 | public ImmutableArray Diagnostics 31 | { 32 | get 33 | { 34 | _ = _syntaxTree.Value; 35 | return _diagnostics; 36 | } 37 | } 38 | 39 | public Compilation_unitContext GetSyntaxTree() 40 | { 41 | var diagnostics = new DiagnosticBag(null!); 42 | var parser = ParserFactory.Create(_source, diagnostics); 43 | 44 | var compilationUnit = parser.compilation_unit(); 45 | _diagnostics = diagnostics.ToImmutableArray(); 46 | return compilationUnit; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/MethodBody/MethodBodySymbolContext.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Symbols.Interfaces; 2 | using FluentLang.Compiler.Symbols.Interfaces.MethodBody; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.Immutable; 6 | using System.Text; 7 | 8 | namespace FluentLang.Compiler.Symbols.Source.MethodBody 9 | { 10 | internal class MethodBodySymbolContext 11 | { 12 | public MethodBodySymbolContext(SourceSymbolContext sourceSymbolContext) 13 | { 14 | SourceSymbolContext = sourceSymbolContext; 15 | Locals = ImmutableList.Empty; 16 | } 17 | 18 | private MethodBodySymbolContext(SourceSymbolContext sourceSymbolContext, ImmutableList locals, IStatement? currentStatement) 19 | { 20 | SourceSymbolContext = sourceSymbolContext; 21 | Locals = locals; 22 | CurrentStatement = currentStatement; 23 | } 24 | 25 | public SourceSymbolContext SourceSymbolContext { get; } 26 | public ImmutableList Locals { get; } 27 | public IStatement? CurrentStatement { get; } 28 | 29 | public MethodBodySymbolContext WithLocal(ILocal local) 30 | => new MethodBodySymbolContext(SourceSymbolContext, Locals.Add(local), CurrentStatement); 31 | public MethodBodySymbolContext WithScope(IMethod method) 32 | => new MethodBodySymbolContext(SourceSymbolContext.WithScope(method), Locals.AddRange(method.ParameterLocals), CurrentStatement); 33 | public MethodBodySymbolContext WithStatement(IStatement statement) 34 | => new MethodBodySymbolContext(SourceSymbolContext, Locals, statement); 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /source/flc/Testing/TestRunner.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Shared; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | namespace FluentLang.flc.Testing 8 | { 9 | public class TestRunner 10 | { 11 | public static TestResult RunTests(Assembly compiledAssembly) 12 | { 13 | var methods = 14 | compiledAssembly 15 | .ExportedTypes 16 | .SelectMany(x => x.GetMethods(BindingFlags.Static | BindingFlags.Public)) 17 | .Where(x => 18 | x.GetParameters().Length == 0 19 | && (x.ReturnType == typeof(string) || x.ReturnType == typeof(bool))); 20 | 21 | var successes = new List(); 22 | var failures = new List<(string name, string message)>(); 23 | foreach (var method in methods) 24 | { 25 | object? result; 26 | try 27 | { 28 | result = method.Invoke(null, null); 29 | } 30 | catch (Exception e) 31 | { 32 | result = e.ToString(); 33 | } 34 | 35 | switch (result) 36 | { 37 | case true: 38 | case "": 39 | case null: 40 | successes.Add(method.Name); 41 | break; 42 | case false: 43 | failures.Add((method.Name, "failed")); 44 | break; 45 | case string message: 46 | failures.Add((method.Name, message)); 47 | break; 48 | default: 49 | Release.Fail("This location is thought to be unreachable"); 50 | break; 51 | } 52 | } 53 | 54 | return failures.Any() 55 | ? (TestResult)new TestResult.Failure(successes, failures) 56 | : new TestResult.Success(successes); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Substituted/SubstitutedInterfaceMethod.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Shared; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.Diagnostics; 8 | using System.Linq; 9 | 10 | namespace FluentLang.Compiler.Symbols.Substituted 11 | { 12 | [DebuggerDisplay("{Name}")] 13 | internal class SubstitutedInterfaceMethod : IInterfaceMethod 14 | { 15 | private readonly IInterfaceMethod _original; 16 | private readonly Lazy _returnType; 17 | private readonly Lazy> _parameters; 18 | 19 | public SubstitutedInterfaceMethod(IInterfaceMethod original, ImmutableArrayDictionary substitutions, Dictionary substituted) 20 | { 21 | _original = original; 22 | _returnType = new Lazy(_original.ReturnType.Substitute(substitutions, substituted)); 23 | _parameters = new Lazy>( 24 | () => _original.Parameters.Select(x => x.Substitute(substitutions, substituted)).ToImmutableArray()); 25 | } 26 | 27 | public string Name => _original.Name; 28 | 29 | public IType ReturnType => _returnType.Value; 30 | 31 | public ImmutableArray Parameters => _parameters.Value; 32 | 33 | public ImmutableArray AllDiagnostics => ImmutableArray.Empty; 34 | 35 | public IInterfaceMethod OriginalDefinition => _original.OriginalDefinition; 36 | 37 | void ISymbol.EnsureAllLocalDiagnosticsCollected() { } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /source/Runtime/FLObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Immutable; 3 | 4 | namespace FluentLang.Runtime 5 | { 6 | public class FLObject 7 | { 8 | public static FLObject Empty { get; } = new FLObject(); 9 | private FLObject() => _methods = ImmutableDictionary.Empty; 10 | 11 | private FLObject(ImmutableDictionary methods) 12 | { 13 | _methods = methods; 14 | } 15 | 16 | private readonly ImmutableDictionary _methods; 17 | 18 | public T GetMethod(MethodKey methodKey) where T : Delegate 19 | { 20 | if (!_methods.TryGetValue(methodKey, out var method)) 21 | { 22 | throw new InvalidOperationException( 23 | $@"Method with MethodKey {methodKey.ToString()} does not exist on this. 24 | Make sure this is running with the same versions of dependencies as it was compiled against."); 25 | } 26 | if (!(method is T t)) 27 | { 28 | throw new InvalidOperationException( 29 | $@"Method with MethodKey {methodKey.ToString()} is of type {method.GetType()} but was expected to be of type {typeof(T)}. 30 | Make sure this is running with the same versions of dependencies as it was compiled against."); 31 | } 32 | return t; 33 | } 34 | 35 | public FLObject With(MethodKey methodKey, Delegate method) 36 | { 37 | return new FLObject(_methods.SetItem(methodKey, method)); 38 | } 39 | } 40 | 41 | public static class FLObjectExtensions 42 | { 43 | public static FLObject ToTemp(this FLObject fLObject, out FLObject temp) 44 | { 45 | temp = fLObject; 46 | return fLObject; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /source/Compiler/Diagnostics/ErrorCode.cs: -------------------------------------------------------------------------------- 1 | namespace FluentLang.Compiler.Diagnostics 2 | { 3 | public enum ErrorCode 4 | { 5 | SyntaxError, 6 | DuplicateInterfaceDeclaration, 7 | DuplicateMethodDeclaration, 8 | TypeNotFound, 9 | CannotReferenceSelfAsAdditiveInterface, 10 | InvalidParseTree, 11 | MethodNotFound, 12 | AmbigiousInterfaceReference, 13 | AmbigiousMethodReference, 14 | MismatchedTypes, 15 | CanOnlyPatchInterface, 16 | CannotMixInNonInterface, 17 | CannotPatchInMethodWithoutParameters, 18 | ResultantTypeOfObjectPatchingExpressionIsNotSubtypeOfFirstParameterOfPatchedInMethod, 19 | InvalidArgument, 20 | InvalidIntegerLiteral, 21 | IntegerLiteralOutOfRange, 22 | InvalidCharLiteral, 23 | InvalidRealLiteral, 24 | NonBooleanCondition, 25 | NoBestType, 26 | InvalidLocalReference, 27 | MemberNotFound, 28 | LastStatementMustBeReturnStatement, 29 | OnlyLastStatementCanBeReturnStatement, 30 | ReturnTypeDoesNotMatch, 31 | MethodMustContainAtLeastOneStatement, 32 | HidesLocal, 33 | InvalidEscapeSequence, 34 | UseOfMethodWhichCapturesUnassignedLocals, 35 | ParametersShareNames, 36 | InvalidMetadataAssembly, 37 | CannotUseUnexportedInterfaceFromExportedMember, 38 | MultipleVersionsOfSameAssembly, 39 | TooManyOptionsInUnion, 40 | CannotMatchOnNonUnion, 41 | MatchNotExhaustive, 42 | CanOnlyCombineInterfaces, 43 | TypeParametersShareNames, 44 | CannotConstrainToPrimitive, 45 | WrongNumberOfTypeArguments, 46 | TypeArgumentDoesntMatchConstraints, 47 | RecursiveFunctionCallWithDifferentTypeArguments, 48 | PipedStaticInvocationExpressionCannotHaveQualifiedName, 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /source/Compiler.Tests.Unit/Symbols/Interfaces/VersionTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using Version = FluentLang.Compiler.Symbols.Interfaces.Version; 3 | 4 | namespace FluentLang.Compiler.Tests.Unit.Symbols.Interfaces 5 | { 6 | public class VersionTests 7 | { 8 | [Fact] 9 | public void CanParseVersion() 10 | { 11 | Assert.True(Version.TryParse("1.2.3", out var version)); 12 | Assert.Equal(new Version(1, 2, 3), version); 13 | } 14 | 15 | [Fact] 16 | public void CanParseVersionWithLongBuild() 17 | { 18 | Assert.True(Version.TryParse($"1.2.{long.MaxValue}", out var version)); 19 | Assert.Equal(new Version(1, 2, long.MaxValue), version); 20 | } 21 | 22 | [Fact] 23 | public void CanParsePrerealeaseVersion() 24 | { 25 | Assert.True(Version.TryParse("1.2.0-alpha.3", out var version)); 26 | Assert.Equal(new Version(1, 2, 3, "alpha"), version); 27 | } 28 | 29 | [Fact] 30 | public void CanParsePrerealeaseVersionCOntaningExtraDashesDotsAndNumbers() 31 | { 32 | Assert.True(Version.TryParse("1.2.0-alpha-1.17.3", out var version)); 33 | Assert.Equal(new Version(1, 2, 3, "alpha-1.17"), version); 34 | } 35 | 36 | [Theory] 37 | [InlineData("1")] 38 | [InlineData("1,2,3")] 39 | [InlineData("1a.2.3")] 40 | [InlineData("1..3")] 41 | [InlineData("1-alpha.1")] 42 | [InlineData("1,2,3-alpha.1")] 43 | [InlineData("1a.2.3-alpha.1")] 44 | [InlineData("1..3-alpha.1")] 45 | [InlineData("1.2.1-alpha.1")] 46 | [InlineData("1.2.0-alpha")] 47 | [InlineData("1.2.0-alpha1")] 48 | public void DoesNotParseInvalidVersions(string str) 49 | { 50 | Assert.False(Version.TryParse(str, out _)); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/ErrorSymbols/ErrorType.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Compiler.Symbols.Visitor; 4 | using FluentLang.Shared; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.Diagnostics.CodeAnalysis; 8 | 9 | namespace FluentLang.Compiler.Symbols.ErrorSymbols 10 | { 11 | internal class ErrorType : IType, IErrorSymbol 12 | { 13 | private ErrorType() { } 14 | 15 | public static ErrorType Instance { get; } = new ErrorType(); 16 | 17 | public ImmutableArray AllDiagnostics => ImmutableArray.Empty; 18 | 19 | bool IType.IsEquivalentTo(IType other, Stack<(IType, IType)>? dependantEqualities) 20 | { 21 | // We use ReferenceEquals since it ensures that AreEquavalent maintains an Equivalence Relation 22 | // If we want to treat ErrorTypes differently, we should explicitly check for IErrorSymbol 23 | return ReferenceEquals(this, other); 24 | } 25 | 26 | bool IType.IsSubtypeOf(IType other) 27 | { 28 | // We use ReferenceEquals since it ensures that IsSubtypeOf maintains a partial ordering 29 | // If we want to treat ErrorTypes differently, we should explicitly check for IErrorSymbol 30 | return ReferenceEquals(this, other); 31 | } 32 | 33 | void ISymbol.EnsureAllLocalDiagnosticsCollected() 34 | { 35 | } 36 | 37 | IType IType.Substitute(ImmutableArrayDictionary substitutions, Dictionary substituted) 38 | { 39 | return this; 40 | } 41 | 42 | [return: MaybeNull] 43 | public T Visit(ISymbolVisitor visitor) => default; 44 | } 45 | } -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/MethodBody/MixinPatch.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using FluentLang.Compiler.Symbols.Interfaces.MethodBody; 4 | using System; 5 | using System.Collections.Immutable; 6 | using static FluentLang.Compiler.Generated.FluentLangParser; 7 | 8 | namespace FluentLang.Compiler.Symbols.Source.MethodBody 9 | { 10 | internal sealed class MixinPatch : SymbolBase, IMixinPatch 11 | { 12 | private readonly ExpressionContext _context; 13 | private readonly MethodBodySymbolContext _methodBodySymbolContext; 14 | private readonly Lazy _expression; 15 | 16 | public MixinPatch( 17 | ExpressionContext context, 18 | MethodBodySymbolContext methodBodySymbolContext, 19 | DiagnosticBag diagnostics) : base(diagnostics) 20 | { 21 | _context = context; 22 | _methodBodySymbolContext = methodBodySymbolContext; 23 | _expression = new Lazy(BindExpression); 24 | } 25 | 26 | private IExpression BindExpression() 27 | { 28 | var expression = _context.BindExpression(_methodBodySymbolContext, _diagnostics); 29 | if (!(expression.Type is IInterface)) //TODO: do we want to make this check lazy? 30 | { 31 | _diagnostics.Add(new Diagnostic(new Location(_context), ErrorCode.CannotMixInNonInterface, ImmutableArray.Create(expression.Type))); 32 | } 33 | return expression; 34 | } 35 | 36 | public IExpression Expression => _expression.Value; 37 | 38 | protected override void EnsureAllLocalDiagnosticsCollected() 39 | { 40 | // Touch all lazy fields to force binding; 41 | 42 | _ = _expression.Value; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /source/Compiler.Tests.Unit/Symbols/SourceSymbols/MethodBodyTests/PipedStaticInvocationExpressionTests.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.TestUtils; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using Xunit; 7 | using Xunit.Abstractions; 8 | 9 | namespace FluentLang.Compiler.Tests.Unit.Symbols.SourceSymbols.MethodBodyTests 10 | { 11 | public class PipedStaticInvocationExpressionTests : TestBase 12 | { 13 | public PipedStaticInvocationExpressionTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) 14 | { 15 | } 16 | 17 | [Fact] 18 | public void CanBindPipedStaticInvocationExpression() 19 | { 20 | CreateAssembly(@" 21 | Main() : int { 22 | return 5..M(37); 23 | } 24 | M(a : int, b : int) : int { 25 | return a + b; 26 | }") 27 | .VerifyDiagnostics().VerifyEmit(expectedResult: 42); 28 | } 29 | 30 | [Fact] 31 | public void ErrorIfMethodNotFound() 32 | { 33 | CreateAssembly(@" 34 | Main() : int { 35 | return 5..M(37); 36 | }") 37 | .VerifyDiagnostics( 38 | new Diagnostic(new Location(new TextToken(@"return5..M(37);")), ErrorCode.ReturnTypeDoesNotMatch), 39 | new Diagnostic(new Location(new TextToken(@"M")), ErrorCode.MethodNotFound)); 40 | } 41 | 42 | [Fact] 43 | public void ErrorIfQualifiedNameUsed() 44 | { 45 | CreateAssembly(@" 46 | Main() : int { 47 | return 5..N.M(37); 48 | } 49 | namespace N { 50 | M(a : int, b : int) : int { 51 | return a + b; 52 | } 53 | }") 54 | .VerifyDiagnostics( 55 | new Diagnostic(new Location(new TextToken(@"N.M")), ErrorCode.PipedStaticInvocationExpressionCannotHaveQualifiedName)); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/ErrorSymbols/ErrorInterface.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using System.Collections.Generic; 4 | using System.Collections.Immutable; 5 | 6 | namespace FluentLang.Compiler.Symbols.ErrorSymbols 7 | { 8 | internal class ErrorInterface : IInterface, IErrorSymbol 9 | { 10 | private ErrorInterface() { } 11 | 12 | public static ErrorInterface Instance { get; } = new ErrorInterface(); 13 | 14 | public QualifiedName? FullyQualifiedName => new QualifiedName("", null); 15 | 16 | public bool IsExported => false; 17 | 18 | public ImmutableArray TypeParameters => ImmutableArray.Empty; 19 | 20 | public ImmutableArray TypeArguments => ImmutableArray.Empty; 21 | 22 | public ImmutableArray Methods => ImmutableArray.Empty; 23 | 24 | public ImmutableArray AllDiagnostics => ImmutableArray.Empty; 25 | 26 | bool IType.IsEquivalentTo(IType other, Stack<(IType, IType)>? dependantEqualities) 27 | { 28 | // We use ReferenceEquals since it ensures that AreEquavalent maintains an Equivalence Relation 29 | // If we want to treat ErrorTypes differently, we should explicitly check for IErrorSymbol 30 | return ReferenceEquals(this, other); 31 | } 32 | 33 | bool IType.IsSubtypeOf(IType other) 34 | { 35 | // We use ReferenceEquals since it ensures that IsSubtypeOf maintains a partial ordering 36 | // If we want to treat ErrorTypes differently, we should explicitly check for IErrorSymbol 37 | return ReferenceEquals(this, other); 38 | } 39 | 40 | void ISymbol.EnsureAllLocalDiagnosticsCollected() 41 | { 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /source/Compiler/Symbols/Source/SourceUnion.cs: -------------------------------------------------------------------------------- 1 | using FluentLang.Compiler.Diagnostics; 2 | using FluentLang.Compiler.Symbols.Interfaces; 3 | using System; 4 | using System.Collections.Immutable; 5 | using System.Linq; 6 | using static FluentLang.Compiler.Generated.FluentLangParser; 7 | 8 | namespace FluentLang.Compiler.Symbols.Source 9 | { 10 | internal sealed class SourceUnion : SymbolBase, IUnion 11 | { 12 | private readonly UnionContext _context; 13 | private readonly SourceSymbolContext _sourceSymbolContext; 14 | private readonly bool _isExported; 15 | private readonly Lazy> _options; 16 | 17 | public SourceUnion( 18 | UnionContext context, 19 | SourceSymbolContext sourceSymbolContext, 20 | bool isExported, 21 | DiagnosticBag diagnostics) : base(diagnostics) 22 | { 23 | _context = context; 24 | _sourceSymbolContext = sourceSymbolContext; 25 | _isExported = isExported; 26 | _options = new Lazy>(BindOptions); 27 | } 28 | 29 | public ImmutableArray Options => _options.Value; 30 | 31 | private ImmutableArray
Sorry, there's nothing at this address.