예제 #1
0
        private void VisitTreeAndBuildClassDefinitions(CapturedVariablesTreeNode currentNode)
        {
            var variablesFromThisScopeWhichWereCaptured = currentNode
                                                          .VariablesDefinedInScope
                                                          .Where(var => var.ReferencingLambdas.Count > 0)
                                                          .ToList();

            if (variablesFromThisScopeWhichWereCaptured.Count > 0)
            {
                if (currentNode is CapturedVariablesTreeNodeClassScope)
                {
                    if (!_capturedVarsClassDefs.ContainsKey(currentNode.ScopeIndex))
                    {
                        var classDef        = SyntaxTreeBuilder.BuildClassDefinition();
                        var typeDeclaration = new type_declaration(((CapturedVariablesTreeNodeClassScope)currentNode).ClassName, classDef);
                        _capturedVarsClassDefs.Add(currentNode.ScopeIndex,
                                                   new ScopeClassDefinition(currentNode.CorrespondingSyntaxTreeNode,
                                                                            typeDeclaration,
                                                                            currentNode,
                                                                            compiler_string_consts.self_word));
                    }
                }
                else
                {
                    if (!_capturedVarsClassDefs.ContainsKey(currentNode.ScopeIndex))
                    {
                        var classDef        = SyntaxTreeBuilder.BuildClassDefinition();
                        var typeDeclaration = new type_declaration(GeneratedClassName, classDef);
                        _capturedVarsClassDefs.Add(currentNode.ScopeIndex,
                                                   new ScopeClassDefinition(currentNode.CorrespondingSyntaxTreeNode,
                                                                            typeDeclaration,
                                                                            currentNode));
                    }


                    var vars = variablesFromThisScopeWhichWereCaptured
                               .Select(field => field.SymbolInfo.sym_info as IVAriableDefinitionNode)
                               .ToList();

                    var fieldNames = vars
                                     .Select(var => new ident(var.name))
                                     .ToList();

                    var fieldTypes = vars
                                     .Select(var => SyntaxTreeBuilder.BuildSemanticType(var.type))
                                     .ToList();

                    var classFields = SyntaxTreeBuilder.BuildClassFieldsSection(fieldNames, fieldTypes);

                    ((class_definition)_capturedVarsClassDefs[currentNode.ScopeIndex].ClassDeclaration.type_def).body
                    .Add(
                        classFields);

                    if (currentNode is CapturedVariablesTreeNodeProcedureScope)
                    {
                        var constructorSection = SyntaxTreeBuilder.BuildSimpleConstructorSection(fieldNames,
                                                                                                 fieldNames.Select(
                                                                                                     id =>
                                                                                                     new ident("_" +
                                                                                                               id.name))
                                                                                                 .ToList(),
                                                                                                 fieldTypes);
                        ((class_definition)_capturedVarsClassDefs[currentNode.ScopeIndex].ClassDeclaration.type_def)
                        .body.Add(constructorSection);
                    }
                }

                foreach (var capturedVar in variablesFromThisScopeWhichWereCaptured)
                {
                    VisitCapturedVar(currentNode, capturedVar);
                }
            }

            foreach (CapturedVariablesTreeNode childNode in currentNode.ChildNodes)
            {
                VisitTreeAndBuildClassDefinitions(childNode);
            }

            if (variablesFromThisScopeWhichWereCaptured.Count > 0)
            {
                var vars = variablesFromThisScopeWhichWereCaptured
                           .Select(x =>
                                   new
                {
                    IVarDefinitionNode = x.SymbolInfo.sym_info as IVAriableDefinitionNode,
                    VarDeclNode        = x.SyntaxTreeNodeWithVarDeclaration
                })
                           .Where(x => x.IVarDefinitionNode != null)
                           .ToList();

                foreach (var var in vars)
                {
                    foreach (CapturedVariablesTreeNode childNode in currentNode.ChildNodes)
                    {
                        _rewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariableInfo.Add(
                            new RewriteReferencesForNodesThatAreChildNodesToThoseThatContainCapturedVariableInfo
                        {
                            TreeNode        = childNode,
                            Varname         = var.IVarDefinitionNode.name,
                            NodeWithVarDecl = var.VarDeclNode
                        });
                    }
                }
            }
        }
예제 #2
0
        private void VisitCapturedVar(CapturedVariablesTreeNode scope, CapturedVariablesTreeNode.CapturedSymbolInfo symbolInfo)
        {
            var varName           = ((IVAriableDefinitionNode)symbolInfo.SymbolInfo.sym_info).name.ToLower();
            var isSelfWordInClass = scope is CapturedVariablesTreeNodeClassScope && varName == compiler_string_consts.self_word;

            foreach (var referencingLambda in symbolInfo.ReferencingLambdas.OrderByDescending(rl => rl.ScopeIndex))
            {
                if (scope != referencingLambda.ParentNode)
                {
                    var upperScopesStack        = new Stack <CapturedVariablesTreeNode>();
                    var crawlUpScope            = referencingLambda.ParentNode;
                    var anotherLambdaIsOnTheWay = crawlUpScope is CapturedVariablesTreeNodeLambdaScope;

                    while (crawlUpScope != null && crawlUpScope != scope && !anotherLambdaIsOnTheWay)
                    {
                        upperScopesStack.Push(crawlUpScope);
                        crawlUpScope            = crawlUpScope.ParentNode;
                        anotherLambdaIsOnTheWay = crawlUpScope is CapturedVariablesTreeNodeLambdaScope;
                    }

                    if (anotherLambdaIsOnTheWay || crawlUpScope == null)
                    {
                        continue;
                    }

                    var upperScopeWhereVarsAreCaptured      = scope;
                    var upperScopeWhereVarsAreCapturedClass =
                        _capturedVarsClassDefs[upperScopeWhereVarsAreCaptured.ScopeIndex].ClassDeclaration;

                    var substKey = new SubstitutionKey(varName, symbolInfo.SyntaxTreeNodeWithVarDeclaration,
                                                       scope.CorrespondingSyntaxTreeNode);
                    if (!_substitutions.ContainsKey(substKey))
                    {
                        _substitutions.Add(substKey,
                                           new dot_node(
                                               new ident(
                                                   _capturedVarsClassDefs[upperScopeWhereVarsAreCaptured.ScopeIndex]
                                                   .GeneratedSubstitutingFieldName), new ident(varName)));
                    }

                    while (upperScopesStack.Count != 0)
                    {
                        var foundScopeWhereVarsWereCaptured = false;
                        while (upperScopesStack.Count != 0 && !foundScopeWhereVarsWereCaptured)
                        {
                            if (
                                upperScopesStack.Peek()
                                .VariablesDefinedInScope.Exists(var => var.ReferencingLambdas.Count > 0))
                            {
                                foundScopeWhereVarsWereCaptured = true;
                            }
                            else
                            {
                                var curScope = upperScopesStack.Pop();

                                if (upperScopeWhereVarsAreCaptured == scope &&
                                    upperScopeWhereVarsAreCaptured is CapturedVariablesTreeNodeClassScope)
                                {
                                    continue;
                                }

                                substKey = new SubstitutionKey(varName, symbolInfo.SyntaxTreeNodeWithVarDeclaration,
                                                               curScope.CorrespondingSyntaxTreeNode);

                                dot_node dotnode;

                                if (upperScopeWhereVarsAreCaptured != scope)
                                {
                                    dotnode =
                                        new dot_node(
                                            new ident(
                                                _capturedVarsClassDefs[upperScopeWhereVarsAreCaptured.ScopeIndex]
                                                .GeneratedSubstitutingFieldName),
                                            new ident(
                                                _capturedVarsClassDefs[upperScopeWhereVarsAreCaptured.ScopeIndex]
                                                .GeneratedUpperClassFieldName));

                                    var nodeForDotNodeCalc = upperScopeWhereVarsAreCaptured.ParentNode;
                                    while (nodeForDotNodeCalc != scope)
                                    {
                                        if (_capturedVarsClassDefs.ContainsKey(nodeForDotNodeCalc.ScopeIndex) &&
                                            _capturedVarsClassDefs[nodeForDotNodeCalc.ScopeIndex]
                                            .AssignNodeForUpperClassFieldInitialization != null)
                                        {
                                            dotnode = new dot_node(dotnode,
                                                                   new ident(
                                                                       _capturedVarsClassDefs[
                                                                           nodeForDotNodeCalc.ScopeIndex]
                                                                       .GeneratedUpperClassFieldName));
                                        }

                                        nodeForDotNodeCalc = nodeForDotNodeCalc.ParentNode;
                                    }
                                    if (!isSelfWordInClass)
                                    {
                                        dotnode = new dot_node(dotnode, new ident(varName));
                                    }
                                }
                                else
                                {
                                    dotnode = new dot_node(new ident(
                                                               _capturedVarsClassDefs[
                                                                   upperScopeWhereVarsAreCaptured.ScopeIndex]
                                                               .GeneratedSubstitutingFieldName),
                                                           new ident(varName));
                                }

                                if (!_substitutions.ContainsKey(substKey))
                                {
                                    _substitutions.Add(substKey, dotnode);
                                }
                            }
                        }

                        if (foundScopeWhereVarsWereCaptured)
                        {
                            var nextNodeWhereVarsAreCaptured = upperScopesStack.Pop();
                            if (!_capturedVarsClassDefs.ContainsKey(nextNodeWhereVarsAreCaptured.ScopeIndex))
                            {
                                var classDef        = SyntaxTreeBuilder.BuildClassDefinition();
                                var typeDeclaration = new type_declaration(GeneratedClassName, classDef);
                                _capturedVarsClassDefs.Add(nextNodeWhereVarsAreCaptured.ScopeIndex,
                                                           new ScopeClassDefinition(
                                                               nextNodeWhereVarsAreCaptured.CorrespondingSyntaxTreeNode,
                                                               typeDeclaration,
                                                               nextNodeWhereVarsAreCaptured));
                            }

                            var nextNodeWhereVarsAreCapturedClass =
                                (class_definition)
                                _capturedVarsClassDefs[nextNodeWhereVarsAreCaptured.ScopeIndex].ClassDeclaration
                                .type_def;

                            if (
                                _capturedVarsClassDefs[nextNodeWhereVarsAreCaptured.ScopeIndex]
                                .AssignNodeForUpperClassFieldInitialization == null)
                            {
                                var fieldType =
                                    SyntaxTreeBuilder.BuildSimpleType(upperScopeWhereVarsAreCapturedClass.type_name.name);
                                var field =
                                    SyntaxTreeBuilder.BuildClassFieldsSection(
                                        new List <ident>
                                {
                                    new ident(
                                        _capturedVarsClassDefs[nextNodeWhereVarsAreCaptured.ScopeIndex]
                                        .GeneratedUpperClassFieldName)
                                },
                                        new List <type_definition> {
                                    fieldType
                                });

                                nextNodeWhereVarsAreCapturedClass.body.Add(field);

                                _capturedVarsClassDefs[nextNodeWhereVarsAreCaptured.ScopeIndex]
                                .AssignNodeForUpperClassFieldInitialization =
                                    new assign(
                                        new dot_node(
                                            new ident(
                                                _capturedVarsClassDefs[nextNodeWhereVarsAreCaptured.ScopeIndex]
                                                .GeneratedSubstitutingFieldName),
                                            new ident(
                                                _capturedVarsClassDefs[nextNodeWhereVarsAreCaptured.ScopeIndex]
                                                .GeneratedUpperClassFieldName)),
                                        new ident(
                                            _capturedVarsClassDefs[upperScopeWhereVarsAreCaptured.ScopeIndex]
                                            .GeneratedSubstitutingFieldName));
                            }

                            substKey = new SubstitutionKey(varName, symbolInfo.SyntaxTreeNodeWithVarDeclaration,
                                                           nextNodeWhereVarsAreCaptured.CorrespondingSyntaxTreeNode);

                            var dot =
                                new dot_node(
                                    new ident(
                                        _capturedVarsClassDefs[nextNodeWhereVarsAreCaptured.ScopeIndex]
                                        .GeneratedSubstitutingFieldName),
                                    new ident(
                                        _capturedVarsClassDefs[nextNodeWhereVarsAreCaptured.ScopeIndex]
                                        .GeneratedUpperClassFieldName));

                            var nodeForDotNodeCalculation = nextNodeWhereVarsAreCaptured.ParentNode;
                            while (nodeForDotNodeCalculation != scope)
                            {
                                if (_capturedVarsClassDefs.ContainsKey(nodeForDotNodeCalculation.ScopeIndex) &&
                                    _capturedVarsClassDefs[nodeForDotNodeCalculation.ScopeIndex]
                                    .AssignNodeForUpperClassFieldInitialization != null)
                                {
                                    dot = new dot_node(dot,
                                                       new ident(
                                                           _capturedVarsClassDefs[nodeForDotNodeCalculation.ScopeIndex]
                                                           .GeneratedUpperClassFieldName));
                                }

                                nodeForDotNodeCalculation = nodeForDotNodeCalculation.ParentNode;
                            }

                            if (!isSelfWordInClass)
                            {
                                dot = new dot_node(dot, new ident(varName));
                            }

                            if (!_substitutions.ContainsKey(substKey))
                            {
                                _substitutions.Add(substKey, dot);
                            }

                            upperScopeWhereVarsAreCaptured      = nextNodeWhereVarsAreCaptured;
                            upperScopeWhereVarsAreCapturedClass =
                                _capturedVarsClassDefs[upperScopeWhereVarsAreCaptured.ScopeIndex].ClassDeclaration;
                        }
                    }

                    if (!(upperScopeWhereVarsAreCaptured == scope &&
                          upperScopeWhereVarsAreCaptured is CapturedVariablesTreeNodeClassScope))
                    {
                        if (upperScopeWhereVarsAreCaptured != scope)
                        {
                            var dotnode1 = new dot_node(
                                new ident(compiler_string_consts.self_word),
                                new ident(
                                    _capturedVarsClassDefs[upperScopeWhereVarsAreCaptured.ScopeIndex]
                                    .GeneratedUpperClassFieldName));

                            if (upperScopeWhereVarsAreCaptured != scope)
                            {
                                var nodeForDotNodeCalc = upperScopeWhereVarsAreCaptured.ParentNode;
                                while (nodeForDotNodeCalc != scope)
                                {
                                    if (_capturedVarsClassDefs.ContainsKey(nodeForDotNodeCalc.ScopeIndex) &&
                                        _capturedVarsClassDefs[nodeForDotNodeCalc.ScopeIndex]
                                        .AssignNodeForUpperClassFieldInitialization != null)
                                    {
                                        dotnode1 = new dot_node(dotnode1,
                                                                new ident(
                                                                    _capturedVarsClassDefs[nodeForDotNodeCalc.ScopeIndex]
                                                                    .GeneratedUpperClassFieldName));
                                    }

                                    nodeForDotNodeCalc = nodeForDotNodeCalc.ParentNode;
                                }
                            }

                            if (!isSelfWordInClass)
                            {
                                var classScope = scope as CapturedVariablesTreeNodeClassScope;
                                if (classScope != null)
                                {
                                    Tuple <string, class_field, semantic_node> publicProperty;
                                    if (classScope.NonPublicMembersNamesMapping.TryGetValue(varName, out publicProperty))
                                    {
                                        dotnode1 = new dot_node(dotnode1, new ident(publicProperty.Item1));
                                    }
                                    else
                                    {
                                        dotnode1 = new dot_node(dotnode1, new ident(varName));
                                    }
                                }
                                else
                                {
                                    dotnode1 = new dot_node(dotnode1, new ident(varName));
                                }
                            }
                            _lambdaIdReferences.Add(new LambdaReferencesSubstitutionInfo
                            {
                                LambdaScope = referencingLambda,
                                VarName     = varName,
                                SyntaxTreeNodeWithVarDeclaration = symbolInfo.SyntaxTreeNodeWithVarDeclaration,
                                DotNode = dotnode1
                            });
                        }
                        else
                        {
                            var dotnode1 = new dot_node(
                                new ident(compiler_string_consts.self_word),
                                new ident(varName));

                            _lambdaIdReferences.Add(new LambdaReferencesSubstitutionInfo
                            {
                                LambdaScope = referencingLambda,
                                VarName     = varName,
                                SyntaxTreeNodeWithVarDeclaration = symbolInfo.SyntaxTreeNodeWithVarDeclaration,
                                DotNode = dotnode1
                            });
                        }
                    }
                    if (!referencingLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.HasValue ||
                        upperScopeWhereVarsAreCaptured.ScopeIndex >
                        referencingLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod)
                    {
                        referencingLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod =
                            upperScopeWhereVarsAreCaptured.ScopeIndex;
                    }
                }
                else
                {
                    if (!_capturedVarsClassDefs.ContainsKey(scope.ScopeIndex))
                    {
                        var classDef        = SyntaxTreeBuilder.BuildClassDefinition();
                        var typeDeclaration = new type_declaration(GeneratedClassName, classDef);
                        _capturedVarsClassDefs.Add(scope.ScopeIndex,
                                                   new ScopeClassDefinition(
                                                       scope.CorrespondingSyntaxTreeNode,
                                                       typeDeclaration,
                                                       scope));
                    }

                    var substKey = new SubstitutionKey(varName, symbolInfo.SyntaxTreeNodeWithVarDeclaration,
                                                       scope.CorrespondingSyntaxTreeNode);
                    if (!_substitutions.ContainsKey(substKey))
                    {
                        if (!isSelfWordInClass)
                        {
                            string propertyName = null;

                            var classScope = scope as CapturedVariablesTreeNodeClassScope;
                            if (classScope != null)
                            {
                                Tuple <string, class_field, semantic_node> publicProperty;
                                if (classScope.NonPublicMembersNamesMapping.TryGetValue(varName, out publicProperty))
                                {
                                    propertyName = publicProperty.Item1;
                                }
                            }

                            _substitutions.Add(substKey,
                                               new dot_node(
                                                   new ident(
                                                       _capturedVarsClassDefs[scope.ScopeIndex]
                                                       .GeneratedSubstitutingFieldName), new ident(propertyName ?? varName)));
                        }
                    }

                    var dotnode1 = new dot_node(
                        new ident(compiler_string_consts.self_word),
                        new ident(varName));

                    _lambdaIdReferences.Add(new LambdaReferencesSubstitutionInfo
                    {
                        LambdaScope = referencingLambda,
                        VarName     = varName,
                        SyntaxTreeNodeWithVarDeclaration = symbolInfo.SyntaxTreeNodeWithVarDeclaration,
                        DotNode = dotnode1
                    });

                    if (!referencingLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.HasValue ||
                        scope.ScopeIndex > referencingLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod)
                    {
                        referencingLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod = scope.ScopeIndex;
                    }
                }

                if (!_lambdasToBeAddedAsMethods.Contains(referencingLambda))
                {
                    _lambdasToBeAddedAsMethods.Add(referencingLambda);
                }
            }
        }
        bool VisitTypeclassDeclaration(type_declaration typeclassDeclaration)
        {
            var typeclassDefinition = typeclassDeclaration.type_def as typeclass_definition;

            if (typeclassDefinition == null)
            {
                return(false);
            }

            var typeclassName = typeclassDeclaration.type_name as typeclass_restriction;

            // TODO: typeclassDefinition.additional_restrictions - translate to usual classes

            // Creating interface

            // Get members for typeclass interface
            var interfaceMembers = new List <class_members>();

            foreach (var cm in typeclassDefinition.body.class_def_blocks)
            {
                var cmNew = (class_members)cm.Clone();

                for (int i = 0; i < cmNew.members.Count; i++)
                {
                    var member = cmNew.members[i];
                    if (member is function_header || member is procedure_header)
                    {
                        cmNew.members[i] = member;
                    }
                    else if (member is procedure_definition procDef)
                    {
                        cmNew.members[i] = procDef.proc_header;
                    }
                    AddAttribute(cmNew.members[i], "__TypeclassMemberAttribute");
                    if (cmNew.members[i] is procedure_header ph)
                    {
                        ConvertOperatorNameIdent(ph);
                    }
                }

                interfaceMembers.Add(cmNew);
            }
            var interfaceInheritance = (named_type_reference_list)typeclassDefinition.additional_restrictions?.Clone();

            if (interfaceInheritance != null)
            {
                interfaceInheritance.source_context = null;
                for (int i = 0; i < interfaceInheritance.types.Count; i++)
                {
                    if (interfaceInheritance.types[i] is typeclass_reference tr)
                    {
                        interfaceInheritance.types[i] = TypeclassReferenceToInterfaceName(tr.names[0].name, tr.restriction_args);
                    }
                    else
                    {
                        throw new NotImplementedException("Syntactic Error");
                    }
                }
            }
            var typeclassInterfaceDef =
                SyntaxTreeBuilder.BuildClassDefinition(
                    interfaceInheritance,
                    null, interfaceMembers.ToArray());

            typeclassInterfaceDef.keyword = class_keyword.Interface;
            var typeclassInterfaceName = new template_type_name("I" + typeclassName.name, RestrictionsToIdentList(typeclassName.restriction_args));
            var typeclassInterfaceDecl = new type_declaration(typeclassInterfaceName, typeclassInterfaceDef);

            typeclassInterfaceDecl.attributes = typeclassDeclaration.attributes;
            AddAttribute(
                typeclassInterfaceDecl, "__TypeclassAttribute",
                new expression_list(new string_const(TypeclassRestrictionToString(typeclassName))));


            // Creating class

            var typeclassDefTranslated =
                SyntaxTreeBuilder.BuildClassDefinition(
                    new named_type_reference_list(new template_type_reference(typeclassInterfaceName.name, typeclassName.restriction_args)),
                    null, typeclassDefinition.body.class_def_blocks.ToArray());

            typeclassDefTranslated.attribute = class_attribute.Abstract;
            for (int i = 0; i < typeclassDefTranslated.body.class_def_blocks.Count; i++)
            {
                var cm = typeclassDefTranslated.body.class_def_blocks[i].members;

                for (int j = 0; j < cm.Count; j++)
                {
                    procedure_header header = null;
                    if (cm[j] is procedure_header ph)
                    {
                        header = ph;
                        header.proc_attributes.Add(new procedure_attribute("abstract", proc_attribute.attr_abstract));
                    }
                    else if (cm[j] is procedure_definition pd)
                    {
                        header = pd.proc_header;
                        header.proc_attributes.Add(new procedure_attribute("virtual", proc_attribute.attr_virtual));
                    }

                    ConvertOperatorNameIdent(header);
                }
            }

            /*
             * {
             *  // Add constructor
             *  var cm = typeclassDefTranslated.body.class_def_blocks[0];
             *  var def = new procedure_definition(
             *      new constructor(),
             *      new statement_list(new empty_statement()));
             *  def.proc_body.Parent = def;
             *  def.proc_header.proc_attributes = new procedure_attributes_list();
             *
             *  cm.Add(def);
             * }
             */
            // Add template parameters for typeclass class(derived typeclasses)
            ident_list templates = RestrictionsToIdentList(typeclassName.restriction_args);

            if (typeclassDefinition.additional_restrictions != null)
            {
                for (int i = 0; i < typeclassDefinition.additional_restrictions.types.Count; i++)
                {
                    string name;
                    string templateName;
                    if (typeclassDefinition.additional_restrictions.types[i] is typeclass_reference tr)
                    {
                        name         = tr.names[0].name;
                        templateName = TypeclassRestrctionToTemplateName(name, tr.restriction_args).name;
                    }
                    else
                    {
                        throw new NotImplementedException("SyntaxError");
                    }

                    // Add template parameter
                    templates.Add(templateName);

                    // Add where restriction
                    if (typeclassDefTranslated.where_section == null)
                    {
                        typeclassDefTranslated.where_section = new where_definition_list();
                    }
                    typeclassDefTranslated.where_section.Add(GetWhereRestriction(
                                                                 interfaceInheritance.types[i],
                                                                 templateName));

                    // Add methods from derived typeclasses
                    var body = (instancesAndRestrictedFunctions.typeclasses[name].type_def as typeclass_definition).body;
                    foreach (var cdb in body.class_def_blocks)
                    {
                        var cdbNew = new class_members(cdb.access_mod == null ? access_modifer.none : cdb.access_mod.access_level);
                        foreach (var member in cdb.members)
                        {
                            procedure_header memberHeaderNew;

                            if (member is procedure_header || member is function_header)
                            {
                                memberHeaderNew = (procedure_header)member.Clone();
                                memberHeaderNew.source_context = null;
                            }
                            else if (member is procedure_definition procDefinition)
                            {
                                memberHeaderNew                = (procedure_header)procDefinition.proc_header.Clone();
                                memberHeaderNew.Parent         = null;
                                memberHeaderNew.source_context = null;
                            }
                            else
                            {
                                continue;
                            }

                            var variableName = templateName + "Instance";
                            var parameters   = memberHeaderNew.parameters.params_list.Aggregate(new expression_list(), (x, y) => new expression_list(x.expressions.Concat(y.idents.idents).ToList()));

                            expression methodCall = null;
                            if (memberHeaderNew.name.meth_name is operator_name_ident oni)
                            {
                                ConvertOperatorNameIdent(memberHeaderNew);
                                Debug.Assert(parameters.expressions.Count == 2, "Parameters count for operation should be equal to 2");
                                //methodCall = new bin_expr(parameters.expressions[0], parameters.expressions[1], oni.operator_type);
                            }
                            var callName = new dot_node(variableName, memberHeaderNew.name.meth_name.name);
                            methodCall = new method_call(callName, parameters);
                            statement exec = null;
                            if (memberHeaderNew is function_header)
                            {
                                exec = new assign("Result", methodCall);
                            }
                            else if (memberHeaderNew is procedure_header)
                            {
                                exec = new procedure_call(methodCall as method_call);
                            }
                            var procDef = new procedure_definition(
                                memberHeaderNew,
                                new statement_list(
                                    GetInstanceSingletonVarStatement(templateName),
                                    exec));
                            cdbNew.Add(procDef);
                        }
                        typeclassDefTranslated.body.class_def_blocks.Add(cdbNew);
                    }
                }
            }

            var typeclassNameTanslated = new template_type_name(typeclassName.name, templates, typeclassName.source_context);

            var typeclassDeclTranslated = new type_declaration(typeclassNameTanslated, typeclassDefTranslated, typeclassDeclaration.source_context);

            typeclassDeclTranslated.attributes = typeclassDeclaration.attributes;
            AddAttribute(
                typeclassDeclTranslated, "__TypeclassAttribute",
                new expression_list(new string_const(TypeclassRestrictionToString(typeclassName))));

            Replace(typeclassDeclaration, typeclassDeclTranslated);
            UpperNodeAs <type_declarations>().InsertBefore(typeclassDeclTranslated, typeclassInterfaceDecl);
            visit(typeclassInterfaceDecl);
            visit(typeclassDeclTranslated);

            return(true);
        }
        bool VisitInstanceDeclaration(type_declaration instanceDeclaration)
        {
            var instanceDefinition = instanceDeclaration.type_def as instance_definition;

            if (instanceDefinition == null)
            {
                return(false);
            }
            var instanceName = instanceDeclaration.type_name as typeclass_restriction;

            // If it is instance of derived typelass than it should have template parameters
            var templateArgs = new ident_list();
            where_definition_list whereSection = null;
            var originalTypeclass = instancesAndRestrictedFunctions.typeclasses[instanceName.name].type_def as typeclass_definition;
            var typeclassParents  = originalTypeclass.additional_restrictions;

            if (typeclassParents != null && typeclassParents.Count > 0)
            {
                whereSection = new where_definition_list();

                for (int i = 0; i < typeclassParents.Count; i++)
                {
                    ident template_name;
                    if (typeclassParents[i] is typeclass_reference tr)
                    {
                        string name = tr.names[0].name;
                        template_name = TypeclassRestrctionToTemplateName(name, tr.restriction_args);

                        whereSection.Add(GetWhereRestriction(
                                             TypeclassReferenceToInterfaceName(name, instanceName.restriction_args),
                                             template_name));
                    }
                    else
                    {
                        throw new NotImplementedException("Should be syntactic error");
                    }
                    templateArgs.Add(template_name);
                }
            }

            List <type_definition> templateLists = instanceName.restriction_args.params_list.Concat(templateArgs.idents.Select(x => new named_type_reference(x.name)).OfType <type_definition>()).ToList();
            var parents = new named_type_reference_list(new List <named_type_reference> {
                new template_type_reference(instanceName.name, new template_param_list(templateLists)),
                new template_type_reference("I" + instanceName.name, instanceName.restriction_args)
            });
            var instanceDefTranslated =
                SyntaxTreeBuilder.BuildClassDefinition(
                    parents,
                    null, instanceDefinition.body.class_def_blocks.ToArray());

            instanceDefTranslated.template_args  = templateArgs;
            instanceDefTranslated.where_section  = whereSection;
            instanceDefTranslated.source_context = instanceDefinition.source_context;

            for (int i = 0; i < instanceDefTranslated.body.class_def_blocks.Count; i++)
            {
                var cm = instanceDefTranslated.body.class_def_blocks[i].members;

                for (int j = 0; j < cm.Count; j++)
                {
                    procedure_header header = null;
                    if (cm[j] is procedure_header ph)
                    {
                        cm[j] = ph;
                    }
                    else if (cm[j] is procedure_definition pd)
                    {
                        header = pd.proc_header;
                    }
                    header.proc_attributes.Add(new procedure_attribute("override", proc_attribute.attr_override));
                    ConvertOperatorNameIdent(header);
                }
            }

            /*
             * {
             *  // Add constructor
             *  var cm = instanceDefTranslated.body.class_def_blocks[0];
             *  var def = new procedure_definition(
             *      new constructor(),
             *      new statement_list(new empty_statement()));
             *  def.proc_body.Parent = def;
             *  def.proc_header.proc_attributes = new procedure_attributes_list();
             *
             *  cm.Add(def);
             * }
             */
            var typeName = new ident(CreateInstanceName(instanceName.restriction_args as typeclass_param_list, instanceName.name), instanceName.source_context);

            var instanceDeclTranslated = new type_declaration(typeName, instanceDefTranslated, instanceDeclaration.source_context);

            instanceDeclTranslated.attributes = instanceDeclaration.attributes;
            AddAttribute(
                instanceDeclTranslated, "__TypeclassInstanceAttribute",
                new expression_list(new string_const(TypeclassRestrictionToString(instanceName))));
            AddAttribute(instanceDeclTranslated, "__TypeclassAttribute",
                         new expression_list(new string_const(TypeclassRestrictionToString(
                                                                  (originalTypeclass.Parent as type_declaration).type_name as typeclass_restriction))));

            Replace(instanceDeclaration, instanceDeclTranslated);
            visit(instanceDeclTranslated);

            return(true);
        }
예제 #5
0
        type_declarations GenClassesForYield(procedure_definition pd, IEnumerable <var_def_statement> fields)
        {
            var fh = (pd.proc_header as function_header);

            if (fh == null)
            {
                throw new SyntaxError("Only functions can contain yields", "", pd.proc_header.source_context, pd.proc_header);
            }
            var seqt = fh.return_type as sequence_type;

            if (seqt == null)
            {
                throw new SyntaxError("Functions with yields must return sequences", "", fh.return_type.source_context, fh.return_type);
            }

            // Теперь на месте функции генерируем класс

            // Захваченные переменные
            var cm = class_members.Public;

            foreach (var m in fields)
            {
                cm.Add(m);
            }

            // Параметры функции
            List <ident> lid  = new List <ident>();
            var          pars = fh.parameters;

            if (pars != null)
            {
                foreach (var ps in pars.params_list)
                {
                    if (ps.param_kind != parametr_kind.none)
                    {
                        throw new SyntaxError("Parameters of functions with yields must not have 'var', 'const' or 'params' modifier", "", pars.source_context, pars);
                    }
                    if (ps.inital_value != null)
                    {
                        throw new SyntaxError("Parameters of functions with yields must not have initial values", "", pars.source_context, pars);
                    }
                    var_def_statement vds = new var_def_statement(ps.idents, ps.vars_type);
                    cm.Add(vds); // все параметры функции делаем полями класса
                    lid.AddRange(vds.vars.idents);
                }
            }

            var stels = seqt.elements_type;

            // Системные поля и методы для реализации интерфейса IEnumerable
            cm.Add(new var_def_statement(Consts.State, "integer"),
                   new var_def_statement(Consts.Current, stels),
                   procedure_definition.EmptyDefaultConstructor,
                   new procedure_definition("Reset"),
                   new procedure_definition("MoveNext", "boolean", pd.proc_body),
                   new procedure_definition("get_Current", "object", new assign("Result", Consts.Current)),
                   new procedure_definition("GetEnumerator", "System.Collections.IEnumerator", new assign("Result", "Self"))
                   );

            var className       = newClassName();
            var classNameHelper = className + "Helper";

            var interfaces = new named_type_reference_list("System.Collections.IEnumerator", "System.Collections.IEnumerable");
            var td         = new type_declaration(classNameHelper, SyntaxTreeBuilder.BuildClassDefinition(interfaces, cm));

            // Изменение тела процедуры

            var stl = new statement_list(new var_statement("res", new new_expr(className)));

            stl.AddMany(lid.Select(id => new assign(new dot_node("res", id), id)));
            stl.Add(new assign("Result", "res"));
            pd.proc_body = new block(stl);

            // Второй класс

            var tpl = new template_param_list(stels);

            var IEnumeratorT = new template_type_reference("System.Collections.Generic.IEnumerator", tpl);

            var cm1 = class_members.Public.Add(
                procedure_definition.EmptyDefaultConstructor,
                new procedure_definition(new function_header("get_Current", stels), new assign("Result", Consts.Current)),
                new procedure_definition(new function_header("GetEnumerator", IEnumeratorT), new assign("Result", "Self")),
                new procedure_definition("Dispose")
                );

            var interfaces1  = new named_type_reference_list(classNameHelper);
            var IEnumerableT = new template_type_reference("System.Collections.Generic.IEnumerable", tpl);

            interfaces1.Add(IEnumerableT).Add(IEnumeratorT);

            var td1 = new type_declaration(className, SyntaxTreeBuilder.BuildClassDefinition(interfaces1, cm1));

            var cct = new type_declarations(td);

            cct.Add(td1);

            return(cct);
        }