예제 #1
0
        public Calculator(IVariableScope variables = null, IFunctionScope functions = null)
        {
            this.variables = variables;
            this.functions = functions;

            this.simplifier = new SimplifyBinary(variables, functions);
        }
        public Calculator(IVariableScope variables = null, IFunctionScope functions = null)
        {
            this.variables = variables;
            this.functions = functions;

            this.simplifier = new SimplifyBinary(variables, functions);
        }
예제 #3
0
        /// <summary>
        /// Creates all (or filtered set) constructors from a type (that should be the base type)
        /// to this type which simply relay the call to the base class.
        /// </summary>
        /// <param name="this">This type scope.</param>
        /// <param name="baseType">The base type.</param>
        /// <param name="accessBuilder">
        /// Optional filter (returning null skips the constructor) and
        /// access protection builder. The default access protection is "public ".
        /// </param>
        /// <returns>This function scopes created.</returns>
        public static List <IFunctionScope> CreatePassThroughConstructors(this ITypeScope @this, Type baseType, Func <ConstructorInfo, string?>?accessBuilder = null)
        {
            if (@this == null)
            {
                throw new ArgumentNullException(nameof(@this));
            }
            if (baseType == null)
            {
                throw new ArgumentNullException(nameof(baseType));
            }
            List <IFunctionScope> result = new List <IFunctionScope>();

            foreach (var c in baseType.GetConstructors(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                     .Where(c => c.IsPublic || c.IsFamily || c.IsFamilyOrAssembly))
            {
                string?access = "public ";
                if (accessBuilder != null && (access = accessBuilder(c)) == null)
                {
                    continue;
                }

                IFunctionScope built = @this.CreateFunction(scope =>
                {
                    if (access.Length > 0)
                    {
                        scope.Append(access);
                        if (!Char.IsWhiteSpace(access, access.Length - 1))
                        {
                            scope.Space();
                        }
                    }
                    var parameters = c.GetParameters();
                    scope.Append(Helper.RemoveGenericParameters(@this.Name))
                    .AppendParameters(parameters);

                    if (parameters.Length > 0)
                    {
                        scope.Append(" : base( ");
                        bool atLeastOne = false;
                        foreach (var p in parameters)
                        {
                            if (atLeastOne)
                            {
                                scope.Append(", ");
                            }
                            else
                            {
                                atLeastOne = true;
                            }
                            scope.Append(p.Name);
                        }
                        scope.Append(" )");
                    }
                });
                result.Add(built);
            }
            return(result);
        }
            //

            static void AppendArrayDecl(IFunctionScope f, string typeName, int count)
            {
                if (count > 0)
                {
                    f.Append("new ").Append(typeName).Append("[").Append(count).Append("];").NewLine();
                }
                else
                {
                    f.Append("Array.Empty<").Append(typeName).Append(">();").NewLine();
                }
            }
            public CSCodeGenerationResult Implement(IActivityMonitor monitor, MethodInfo m, ICSCodeGenerationContext c, ITypeScope b)
            {
                IFunctionScope mB = b.CreateOverride(m);

                mB.Parent.Should().BeSameAs(b, "The function is ready to be implemented.");

                if (IsLambda)
                {
                    mB.Append("=> ").Append(ActualCode).Append(';').NewLine();
                }
                else
                {
                    mB.Append(ActualCode);
                }

                return(CSCodeGenerationResult.Success);
            }
        /// <summary>
        /// If an identifier is used in a function of an IncludeFile and references another
        /// Object (e.g. function or record type) from within the file the identifier must
        /// be prepended with the CodeFileAlias of that IncludeFile.
        /// This method checks whether we are currently in the scope of a function from an
        /// IncludeFile and if so it prepends the CodeFileAlias of the IncludeFile.
        /// </summary>
        /// <param name="memory"></param>
        /// <param name="identifier">The name of the object (without alias)</param>
        /// <returns></returns>
        public static string GetIdentifierBasedOnFunctionScope(ISyneryMemory memory, string identifier)
        {
            if (memory.CurrentScope != null)
            {
                // check whether the function call comes from a function scope that sits inside of an include file
                IFunctionScope surroundingFunctionScope = memory.CurrentScope.ResolveFunctionScope();

                if (surroundingFunctionScope != null &&
                    String.IsNullOrEmpty(surroundingFunctionScope.FunctionData.CodeFileAlias) == false)
                {
                    // prepend the CodeFileAlias of the current function scope to get the correct FullName of the requested function
                    return(GetFullName(identifier, surroundingFunctionScope.FunctionData.CodeFileAlias));
                }
            }

            return(identifier);
        }
        public CSCodeGenerationResult Implement(IActivityMonitor monitor,
                                                MethodInfo m,
                                                ICSCodeGenerationContext codeGenContext,
                                                ITypeScope typeBuilder)
        {
            IFunctionScope mB = typeBuilder.CreateOverride(m);

            Debug.Assert(mB.Parent == typeBuilder, "The function is ready to be implemented.");
            if (_attr.IsLambda)
            {
                mB.Append("=> ").Append(_attr.ActualCode).Append(';').NewLine();
            }
            else
            {
                mB.Append(_attr.ActualCode).NewLine();
            }
            return(CSCodeGenerationResult.Success);
        }
예제 #8
0
        public void playing_with_parts()
        {
            INamespaceScope     g                      = CodeWorkspace.Create().Global;
            INamespaceScopePart gSub                   = g.CreatePart();
            INamespaceScopePart gSub2                  = gSub.CreatePart();
            ITypeScope          gSub2Type1             = gSub2.CreateType("class GSub2Type1");
            ITypeScope          gSub2Type2             = gSub2.CreateType("class GSub2Type2");
            ITypeScopePart      gSub2Type1Part1        = gSub2Type1.CreatePart();
            ITypeScopePart      gSub2Type1Part2        = gSub2Type1.CreatePart();
            IFunctionScope      gSub2Type1Part2F1      = gSub2Type1Part2.CreateFunction("void Action()");
            IFunctionScopePart  gSub2Type1Part2F1Part1 = gSub2Type1Part2F1.CreatePart();

            g.Append("g:");
            gSub.Append("gSub:");
            gSub2.Append("gSub2:");
            gSub2Type1.Append("gSub2Type1:");
            gSub2Type2.Append("gSub2Type2:");
            gSub2Type1Part1.Append("gSub2Type1Part1:");
            gSub2Type1Part2.Append("gSub2Type1Part2:");
            gSub2Type1Part2F1.Append("gSub2Type1Part2F1:");
            gSub2Type1Part2F1Part1.Append("gSub2Type1Part2F1Part1:");

            var s = g.ToString().Trim();

            s.Should().Be(@"
gSub2:
gSub:
g:
class GSub2Type1
{
gSub2Type1Part1:
gSub2Type1Part2:
gSub2Type1:
void Action()
{
gSub2Type1Part2F1Part1:
gSub2Type1Part2F1:
}
}
class GSub2Type2
{
gSub2Type2:
}".Trim().ReplaceLineEndings());
        }
        public static Expression Apply(IEnumerable<Type> transformations, Expression expr, IVariableScope variables, IFunctionScope functions)
        {
            Expression result = expr;

            foreach (Type type in transformations)
            {
                result = (new EliminateSubtractions(result)).Result;
                result = (new BinaryToLinear(result)).Result;

                RuleOrientedTransformation transformation = (RuleOrientedTransformation)Activator.CreateInstance(type);

                result = transformation.Transform(result, e => Apply(e, variables, functions));

                result = (new LinearToBinary(result)).Result;
                result = (new SimplifyBinary(result, variables, functions)).Result;
            }

            return result;
        }
예제 #10
0
        public void full_run_test()
        {
            var f = TestHelper.TestProjectFolder.AppendPart("TestCodeProject");

            TestHelper.CleanupFolder(f);
            ICodeProject project = CodeWorkspace.CreateProject("MyProject");

            project.TargetFrameworks.Add("netcoreapp3.1");
            project.OutputType = "Exe";

            project.Code.Global.EnsureUsing("System");
            ITypeScope     program = project.Code.Global.CreateType("public static class Program");
            IFunctionScope main    = program.GeneratedByComment()
                                     .CreateFunction("public static int Main()");

            main.Append("Console.WriteLine(").AppendSourceString("Hop!").Append(" );").NewLine();
            main.Append("return 0;");

            var projectFolder = WriteProjectFolder(f, project);

            Run(projectFolder, "dotnet", "run", out string output);
            output.Should().Contain("Hop!");
        }
예제 #11
0
 public Expression Evaluate(IVariableScope variables, IFunctionScope functions)
 {
     return(Evaluate(this, variables, functions));
 }
 public Expression Differentiate(string var, IVariableScope variables, IFunctionScope functions, IDifferentiationScope derivatives)
 {
     return Differentiate(this, var, variables, functions, derivatives);
 }
예제 #13
0
 public static FunctionScopeAssertions Should(this IFunctionScope functionScope)
 => new FunctionScopeAssertions(functionScope);
예제 #14
0
 public Calculator(Expression expr, IVariableScope variables = null, IFunctionScope functions = null) : this(variables, functions)
 {
     this.result = Calculate(expr);
 }
        /// <summary>
        /// Generates the <paramref name="scope"/> that is the PocoDirectory_CK class and
        /// all the factories (<see cref="IPocoFactory"/> implementations) and the Poco class (<see cref="IPoco"/> implementations).
        /// </summary>
        /// <param name="monitor">The monitor to use.</param>
        /// <param name="classType">The <see cref="PocoDirectory"/> type.</param>
        /// <param name="c">Code generation context.</param>
        /// <param name="scope">The PocoDirectory_CK type scope.</param>
        /// <returns>Always <see cref="CSCodeGenerationResult.Success"/>.</returns>
        public override CSCodeGenerationResult Implement(IActivityMonitor monitor, Type classType, ICSCodeGenerationContext c, ITypeScope scope)
        {
            Debug.Assert(scope.FullName == "CK.Core.PocoDirectory_CK", "We can use the PocoDirectory_CK type name to reference the PocoDirectory implementation.");

            IPocoSupportResult r = c.Assembly.GetPocoSupportResult();

            Debug.Assert(r == c.CurrentRun.ServiceContainer.GetService(typeof(IPocoSupportResult)), "The PocoSupportResult is also available at the GeneratedBinPath.");

            // PocoDirectory_CK class.
            scope.GeneratedByComment().NewLine()
            .FindOrCreateFunction("internal PocoDirectory_CK()")
            .Append("Instance = this;").NewLine();

            scope.Append("internal static PocoDirectory_CK Instance;").NewLine()
            // The _factories field
            .Append("static readonly Dictionary<string,IPocoFactory> _factoriesN = new Dictionary<string,IPocoFactory>( ").Append(r.NamedRoots.Count).Append(" );").NewLine()
            .Append("static readonly Dictionary<Type,IPocoFactory> _factoriesT = new Dictionary<Type,IPocoFactory>( ").Append(r.AllInterfaces.Count).Append(" );").NewLine()
            .Append("public override IPocoFactory Find( string name ) => _factoriesN.GetValueOrDefault( name );").NewLine()
            .Append("public override IPocoFactory Find( Type t ) => _factoriesT.GetValueOrDefault( t );").NewLine()
            .Append("internal static void Register( IPocoFactory f )").OpenBlock()
            .Append("_factoriesN.Add( f.Name, f );").NewLine()
            .Append("foreach( var n in f.PreviousNames ) _factoriesN.Add( n, f );").NewLine()
            .Append("foreach( var i in f.Interfaces ) _factoriesT.Add( i, f );").NewLine()
            .CloseBlock();

            if (r.AllInterfaces.Count == 0)
            {
                return(CSCodeGenerationResult.Success);
            }

            foreach (var root in r.Roots)
            {
                // PocoFactory class.
                var tFB = c.Assembly.FindOrCreateAutoImplementedClass(monitor, root.PocoFactoryClass);
                tFB.Definition.Modifiers |= Modifiers.Sealed;
                string factoryClassName = tFB.Definition.Name.Name;

                // Poco class.
                var tB = c.Assembly.FindOrCreateAutoImplementedClass(monitor, root.PocoClass);
                tB.Definition.Modifiers |= Modifiers.Sealed;

                // The Poco's static _factory field is internal and its type is the exact class: extended code
                // can refer to the _factory to access the factory extended code without cast.
                //
                // This static internal field is an awful shortcut but it makes things simpler and more efficient
                // than looking up the factory in the DI (and downcasting it) each time we need it.
                // This simplification has been done for Cris Command implementation: a ICommand exposes
                // its ICommandModel: we used to inject the ICommandModel (that is the extended PocoFactory) in the ICommand
                // PocoClass ctor from the factory methods. It worked but it was complex... and, eventually, there
                // can (today) but most importantly there SHOULD, be only one StObjMap/Concrete generated code in an
                // assembly. Maybe one day, the StObj instances themselves can be made static (since they are some kind of
                // "absolute singletons").
                //
                // Note to myself: this "static shortcut" is valid because we are on a "final generation", not on a
                // local, per-module, intermediate, code generation like .Net 5 Code Generators.
                // How this kind of shortcuts could be implemented with .Net 5 Code Generators? It seems that it could but
                // there will be as many "intermediate statics" as there are "levels of assemblies"? Or, there will be only
                // one static (the first one) and the instance will be replaced by the subsequent assemblies? In all cases,
                // diamond problem will have to be ultimately resolved at the final leaf... Just like we do!
                //
                tB.Append("internal static ").Append(tFB.Name).Append(" _factory;")
                .NewLine();
                tB.Append("IPocoFactory IPocoGeneratedClass.Factory => _factory;").NewLine();

                // Always create the constructor so that other code generators
                // can always find it.
                // We support the interfaces here: if other participants have already created this type, it is
                // up to us, here, to handle the "exact" type definition.
                tB.Definition.BaseTypes.Add(new ExtendedTypeName("IPocoGeneratedClass"));
                tB.Definition.BaseTypes.AddRange(root.Interfaces.Select(i => new ExtendedTypeName(i.PocoInterface.ToCSharpName())));

                IFunctionScope ctorB = tB.CreateFunction($"public {root.PocoClass.Name}()");

                foreach (var p in root.PropertyList)
                {
                    Type propType    = p.PropertyType;
                    bool isUnionType = p.PropertyUnionTypes.Any();

                    var    typeName  = propType.ToCSharpName();
                    string fieldName = "_v" + p.Index;
                    tB.Append(typeName).Space().Append(fieldName);
                    if (p.DefaultValueSource == null)
                    {
                        tB.Append(";");
                    }
                    else
                    {
                        tB.Append(" = ").Append(p.DefaultValueSource).Append(";");
                    }
                    tB.NewLine();

                    tB.Append("public ").Append(typeName).Space().Append(p.PropertyName);
                    Debug.Assert(!p.IsReadOnly || p.DefaultValueSource == null, "Readonly with [DefaultValue] has already raised an error.");

                    if (p.IsReadOnly)
                    {
                        // Generates in constructor.
                        r.GenerateAutoInstantiatedNewAssignation(ctorB, fieldName, p.PropertyType);
                    }

                    tB.OpenBlock()
                    .Append("get => ").Append(fieldName).Append(";").NewLine();

                    if (!p.IsReadOnly)
                    {
                        tB.Append("set")
                        .OpenBlock();

                        bool isTechnicallyNullable = p.PropertyNullableTypeTree.Kind.IsTechnicallyNullable();
                        bool isNullable            = p.PropertyNullableTypeTree.Kind.IsNullable();

                        if (isTechnicallyNullable && !isNullable)
                        {
                            tB.Append("if( value == null ) throw new ArgumentNullException();").NewLine();
                        }

                        if (isUnionType)
                        {
                            if (isNullable)
                            {
                                tB.Append("if( value != null )")
                                .OpenBlock();
                            }
                            tB.Append("Type tV = value.GetType();").NewLine()
                            .Append("if( !_c").Append(fieldName)
                            .Append(".Any( t => t.IsAssignableFrom( tV ) ))")
                            .OpenBlock()
                            .Append("throw new ArgumentException( $\"Unexpected Type '{tV}' in UnionType. Allowed types are: ")
                            .Append(p.PropertyUnionTypes.Select(tU => tU.ToString()).Concatenate())
                            .Append(".\");")
                            .CloseBlock();
                            if (isNullable)
                            {
                                tB.CloseBlock();
                            }
                        }
                        tB.Append(fieldName).Append(" = value;")
                        .CloseBlock();
                    }
                    tB.CloseBlock();

                    if (isUnionType)
                    {
                        tB.Append("static readonly Type[] _c").Append(fieldName).Append("=").AppendArray(p.PropertyUnionTypes.Select(u => u.Type)).Append(";").NewLine();
                    }
                }

                // PocoFactory class.

                tFB.Append("PocoDirectory IPocoFactory.PocoDirectory => PocoDirectory_CK.Instance;").NewLine();

                tFB.Append("public Type PocoClassType => typeof(").Append(root.PocoClass.Name).Append(");")
                .NewLine();

                tFB.Append("public IPoco Create() => new ").Append(root.PocoClass.Name).Append("();")
                .NewLine();

                tFB.Append("public string Name => ").AppendSourceString(root.Name).Append(";")
                .NewLine();

                tFB.Append("public IReadOnlyList<string> PreviousNames => ").AppendArray(root.PreviousNames).Append(";")
                .NewLine();

                tFB.Append("public IReadOnlyList<Type> Interfaces => ").AppendArray(root.Interfaces.Select(i => i.PocoInterface)).Append(";")
                .NewLine();

                tFB.CreateFunction("public " + factoryClassName + "()")
                .Append("PocoDirectory_CK.Register( this );").NewLine()
                .Append(tB.Name).Append("._factory = this;");

                foreach (var i in root.Interfaces)
                {
                    tFB.Definition.BaseTypes.Add(new ExtendedTypeName(i.PocoFactoryInterface.ToCSharpName()));
                    tFB.AppendCSharpName(i.PocoInterface, true, true, true)
                    .Space()
                    .AppendCSharpName(i.PocoFactoryInterface, true, true, true)
                    .Append(".Create() => new ").AppendCSharpName(i.Root.PocoClass, true, true, true).Append("();")
                    .NewLine();
                }
            }
            return(CSCodeGenerationResult.Success);
        }
예제 #16
0
 public static Expression Apply(Expression expr, IVariableScope variables, IFunctionScope functions)
 {
     return(Apply(transformations, expr, variables, functions));
 }
예제 #17
0
 public static Expression Evaluate(Expression expr, IVariableScope variables, IFunctionScope functions)
 {
     return(Evaluate(transformations, expr, variables, functions));
 }
 public ServiceSupportCodeGenerator(ITypeScope rootType, IFunctionScope rootCtor)
 {
     _rootType = rootType;
     _infoType = rootType.Namespace.CreateType("public static class SFInfo");
     _rootCtor = rootCtor;
 }
        public static Expression Evaluate(IEnumerable<Type> transformations, Expression expr, IVariableScope variables, IFunctionScope functions)
        {
            Expression result = (new EliminateSubtractions(expr)).Result;
            result = (new SimplifyBinary(result, variables, functions)).Result;

            Expression presult = null;

            int count = 0;

            while (!result.Equals(presult) && count < 10)
            {
                presult = result;
                result = Apply(transformations, result, variables, functions);

                count++;
            }

            return (new ReturnSubtractions(result)).Result;
        }
 public SimplifyBinary(Expression expr, IVariableScope variables = null, IFunctionScope functions = null)
     : this(variables, functions)
 {
     this.result = Simplify(expr);
 }
 public SimplifyBinary(IVariableScope variables = null, IFunctionScope functions = null)
 {
     this.variables = variables;
     this.functions = functions;
 }
 public static Expression Apply(Expression expr, IVariableScope variables, IFunctionScope functions)
 {
     return Apply(transformations, expr, variables, functions);
 }
 public Expression Evaluate(IVariableScope variables, IFunctionScope functions)
 {
     return Evaluate(this, variables, functions);
 }
예제 #24
0
 public Expression Apply(IEnumerable <Type> transformations, IVariableScope variables, IFunctionScope functions)
 {
     return(Apply(transformations, this, variables, functions));
 }
예제 #25
0
        public static Expression Differentiate(Expression expr, string var, IVariableScope variables, IFunctionScope functions, IDifferentiationScope derivatives)
        {
            Expression derivative = (new Differentiation(expr, var, derivatives)).Result;

            return(Evaluate(derivative, variables, functions));
        }
 JsonCodeGenHandler ConfigureAndAddTypeInfoForListSetAndMap(JsonTypeInfo info, IFunctionScope fWrite, IFunctionScope fRead, NullableTypeTree tInterface)
 {
     Debug.Assert(!info.Type.Type.IsInterface && tInterface.Type.IsInterface);
     info.Configure(
         (ICodeWriter write, string variableName) =>
     {
         write.Append("PocoDirectory_CK.").Append(fWrite.Definition.MethodName.Name).Append("( w, ").Append(variableName).Append(", options );");
     },
         (ICodeWriter read, string variableName, bool assignOnly, bool isNullableVariable) =>
     {
         if (!assignOnly)
         {
             if (isNullableVariable)
             {
                 read.Append("if( ").Append(variableName).Append(" == null )")
                 .OpenBlock()
                 .Append(variableName).Append(" = new ").Append(info.GenCSharpName).Append("();")
                 .CloseBlock();
             }
             else
             {
                 read.Append(variableName).Append(".Clear();").NewLine();
             }
         }
         else
         {
             read.Append(variableName).Append(" = new ").Append(info.GenCSharpName).Append("();").NewLine();
         }
         // We cast the variable into its type to handle the case where the variable is an 'object' (or
         // any other base type) since these are regular collections (arrays are not handled here).
         read.Append("PocoDirectory_CK.")
         .Append(fRead.Definition.MethodName.Name)
         .Append("( ref r, (")
         .Append(info.GenCSharpName)
         .Append(")")
         .Append(variableName)
         .Append(", options );");
     });
     // The interface maps to the collection type and is its MostAbstractMapping.
     AllowTypeAlias(tInterface.ToNormalNull(), info, isMostAbstract: true);
     AllowTypeInfo(info);
     return(info.NullHandler);
 }
예제 #27
0
        public static Expression Evaluate(IEnumerable <Type> transformations, Expression expr, IVariableScope variables, IFunctionScope functions)
        {
            Expression result = (new EliminateSubtractions(expr)).Result;

            result = (new SimplifyBinary(result, variables, functions)).Result;

            Expression presult = null;

            int count = 0;

            while (!result.Equals(presult) && count < 10)
            {
                presult = result;
                result  = Apply(transformations, result, variables, functions);

                count++;
            }

            return((new ReturnSubtractions(result)).Result);
        }
 public Calculator(Expression expr, IVariableScope variables = null, IFunctionScope functions = null)
     : this(variables, functions)
 {
     this.result = Calculate(expr);
 }
예제 #29
0
        public static Expression Apply(IEnumerable <Type> transformations, Expression expr, IVariableScope variables, IFunctionScope functions)
        {
            Expression result = expr;

            foreach (Type type in transformations)
            {
                result = (new EliminateSubtractions(result)).Result;
                result = (new BinaryToLinear(result)).Result;

                RuleOrientedTransformation transformation = (RuleOrientedTransformation)Activator.CreateInstance(type);

                result = transformation.Transform(result, e => Apply(e, variables, functions));

                result = (new LinearToBinary(result)).Result;
                result = (new SimplifyBinary(result, variables, functions)).Result;
            }

            return(result);
        }
        public static Expression Differentiate(Expression expr, string var, IVariableScope variables, IFunctionScope functions, IDifferentiationScope derivatives)
        {
            Expression derivative = (new Differentiation(expr, var, derivatives)).Result;

            return Evaluate(derivative, variables, functions);
        }
예제 #31
0
 public SimplifyBinary(Expression expr, IVariableScope variables = null, IFunctionScope functions = null) : this(variables, functions)
 {
     this.result = Simplify(expr);
 }
예제 #32
0
 public Part(IFunctionScope owner)
     : base(owner)
 {
 }
예제 #33
0
 public SimplifyBinary(IVariableScope variables = null, IFunctionScope functions = null)
 {
     this.variables = variables;
     this.functions = functions;
 }
예제 #34
0
 public Expression Differentiate(string var, IVariableScope variables, IFunctionScope functions, IDifferentiationScope derivatives)
 {
     return(Differentiate(this, var, variables, functions, derivatives));
 }
예제 #35
0
 void OnFunctionCreated(IFunctionScope obj) => FunctionCount++;
 public Expression Apply(IEnumerable<Type> transformations, IVariableScope variables, IFunctionScope functions)
 {
     return Apply(transformations, this, variables, functions);
 }