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 }); } } } }
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); }
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); }