public static procedure_definition BuildToStringFuncForAutoClass(List <ident> names) { var pal = new procedure_attributes_list(proc_attribute.attr_override); var fp = new formal_parameters(); var ff = new function_header("ToString", "string", fp, pal); var cleft = new char_const('('); var cright = new char_const(')'); var ccomma = new char_const(','); bin_expr ex = new bin_expr(cleft, cright, Operators.Plus); for (var i = 0; i < names.Count; i++) { var dn = new dot_node(names[i], new ident("ToString")); var asnode = new typecast_node(names[i], new named_type_reference("object"), op_typecast.as_op); var eqnode = new bin_expr(asnode, new nil_const(), Operators.Equal); var expr = new question_colon_expression(eqnode, new string_const("nil"), dn); ex.left = new bin_expr(ex.left, expr, Operators.Plus); if (i < names.Count - 1) { ex.left = new bin_expr(ex.left, ccomma, Operators.Plus); } } var ass = new assign("Result", ex); return(BuildShortProcFuncDefinitionNoSC(ff, ass)); }
expression_list construct_expression_list_for_slice_expr_multi(slice_expr sl) { if (sl.slices == null) { return(null); // упадёт - это ошибка компилятора } var el = new expression_list(); // будем наполнять кортежами - самое простое var sc = sl.source_context; foreach (var slice in sl.slices) { var tup = new dot_node(new dot_node(new ident("?System", sc), new ident("Tuple", sc), sc), new ident("Create", sc), sc); var eel = new expression_list(); // пытаемся разобраться с ^1 var sl1 = slice.Item1; eel.Add(sl1); IndexVisitor.New.ProcessNode(sl1); // индексный визитор сам не вызывается поскольку в многомерных срезах хранится List кортежей троек expression, который сам не обходится var sl2 = slice.Item2; eel.Add(sl2); IndexVisitor.New.ProcessNode(sl2); var sl3 = slice.Item3; // и step тоже надо обходить!!! eel.Add(sl3); IndexVisitor.New.ProcessNode(sl3); var mc = new method_call(tup, eel, sc); // sc - не очень хорошо - ошибка будет в общем месте el.Add(mc); // по идее все параметры готовы. Надо только проверить, что они целые } return(el); }
public override void visit(dot_node dn) { ProcessNode(dn.left); if (dn.right.GetType() != typeof(ident)) { ProcessNode(dn.right); } }
public override void visit(dot_node dn) { ProcessNode(dn.left); if (!(dn.right is ident)) { ProcessNode(dn.right); } }
public addressed_value Into(addressed_value x, addressed_value v) // При возникновении новой конструкции в грамматике variable добавить обработку сюда { if (v.GetType() == typeof(dot_question_node)) { var vv = v as dot_question_node; var res = new dot_question_node(Into(x, vv.left), vv.right, x.source_context); return(res); } else if (v.GetType() == typeof(dot_node)) { var vv = v as dot_node; var res = new dot_node(Into(x, vv.left), vv.right, x.source_context); return(res); } else if (v.GetType() == typeof(indexer)) { var vv = v as indexer; var res = new indexer(Into(x, vv.dereferencing_value), vv.indexes, x.source_context); return(res); } else if (v.GetType() == typeof(slice_expr)) { var vv = v as slice_expr; var res = new slice_expr(Into(x, vv.dereferencing_value), vv.from, vv.to, vv.step, x.source_context); return(res); } else if (v.GetType() == typeof(slice_expr_question)) { var vv = v as slice_expr_question; var res = new slice_expr_question(Into(x, vv.dereferencing_value), vv.from, vv.to, vv.step, x.source_context); return(res); } else if (v.GetType() == typeof(method_call)) { var vv = v as method_call; var res = new method_call(Into(x, vv.dereferencing_value), vv.parameters, x.source_context); return(res); } else if (v.GetType() == typeof(roof_dereference)) { var vv = v as roof_dereference; var res = new roof_dereference(Into(x, vv.dereferencing_value), x.source_context); return(res); } else if (v.GetType() == typeof(ident_with_templateparams)) { var vv = v as ident_with_templateparams; var res = new ident_with_templateparams(Into(x, vv.name), vv.template_params, x.source_context); return(res); } else { var res = new dot_node(x, v, x.source_context); return(res); } }
public override void visit(tuple_node tup) { var dn = new dot_node(new dot_node(new ident("?System"), new ident("Tuple")), new ident("Create", tup.source_context)); var mc = new method_call(dn, tup.el, tup.source_context); //var sug = new sugared_expression(tup, mc, tup.source_context); - нет никакой семантической проверки - всё - на уровне синтаксиса! ReplaceUsingParent(tup, mc); visit(mc); }
public override void visit(tuple_node tup) { var dn = new dot_node(new dot_node(new ident("?System"), new ident("Tuple")), new ident("Create", tup.source_context)); var mc = new method_call(dn, tup.el, tup.source_context); //var sug = new sugared_expression(tup, mc, tup.source_context); - нет никакой семантической проверки - всё - на уровне синтаксиса! //ReplaceUsingParent(tup, mc); - исправление #1199. Оказывается, ReplaceUsingParent и Replace не эквивалентны - у копии Parent на старого родителя Replace(tup, mc); visit(mc); }
private TupleDesugaringResult DesugarTuplePattern(tuple_pattern pattern, expression matchingExpression) { Debug.Assert(!pattern.IsRecursive, "All recursive patterns should be desugared into simple patterns at this point"); var desugaringResult = new TupleDesugaringResult(); var tupleItems = pattern.parameters; for (int i = 0; i < tupleItems.Count; ++i) { var tupleItemCall = new dot_node( matchingExpression as addressed_value, new ident("Item" + (i + 1).ToString()), matchingExpression.source_context); if (tupleItems[i] is tuple_pattern_var_parameter varParam) { desugaringResult.VarParametersDeclarations.Add( new var_statement( varParam.identifier, tupleItemCall, matchingExpression.source_context ) ); } if (tupleItems[i] is const_pattern_parameter constParam) { var eqParams = new expression_list( new List <expression>() { tupleItemCall, constParam.const_param } ); var equalCall = new method_call( new dot_node(new ident("object"), new ident("Equals")), eqParams, pattern.source_context ); desugaringResult.SuccessMatchingCheck = desugaringResult.SuccessMatchingCheck == null ? (expression)equalCall : bin_expr.LogicalAnd(desugaringResult.SuccessMatchingCheck, equalCall); desugaringResult.ElemTypeChecks.Add(GetTypeCompatibilityCheck(tupleItemCall, constParam.const_param)); } } desugaringResult.TupleLengthCheck = GetTypeCompatibilityCheck(matchingExpression, new int32_const(tupleItems.Count)); if (desugaringResult.SuccessMatchingCheck == null) { desugaringResult.SuccessMatchingCheck = new bool_const(true); } return(desugaringResult); }
public override void visit(dot_node dn) { if (dn.left is ident id) { TryToRename(id); } else { ProcessNode(dn.left); } ProcessNode(dn.right); }
public override void visit(ident id) { int?paramNameLevel = null; var paramName = id.name; // Ищем с какого уровня имя for (int level = formalParametersStack.Count - 1; level >= 0; --level) { if (formalParametersStack[level].ContainsKey(paramName)) { // Нашли! paramNameLevel = level; break; } } bool isField = false; // Локальные параметры обрабатываются в другом визиторе // Параметр функции if ((object)paramNameLevel != null) { var upper = UpperNode(); // Подозреваем обращение к параметру метода if ((object)upper == null || (object)upper != null && (upper as dot_node) == null) { // Это не self.paramName - поле класса и не что-то другое? // Нашли обращение к параметру? var self = new ident("self", id.source_context); // Заменяем paramName -> self.hoistedParamName: <>num__paramName var hoistedParamName = new ident(formalParametersStack[(int)paramNameLevel][paramName], id.source_context); var selfId = new dot_node(self, hoistedParamName); Replace(id, selfId); } // Иначе проверить что это поле класса! self.paramName или какой-то другой очень извращенный вариант вроде (someMethod: self).paramName } // Поле класса // Параметр внешней функции (если наша - вложенная) // Глобальная переменная }
public question_colon_expression ConvertToQCE(dot_question_node dqn) { addressed_value left = dqn.left; addressed_value right = dqn.right; var eq = new bin_expr(left, new nil_const(), Operators.Equal, left.source_context); addressed_value dn = null; var dnleft = right; // Левая часть dn addressed_value rdqn = null; addressed_value ldqn = null; // Если right - это dot_question_node, то протащить внутрь него left. В силу ассоциирования слева направо достаточно на первый уровень. if (right.GetType() == typeof(dot_question_node)) { var dqn_int = right as dot_question_node; ldqn = dqn_int.left; dnleft = ldqn; rdqn = dqn_int.right; // необходимо left протащить внутрь в ldqn } // Пока right - это dot_node, то необходимо протаскивать left чтобы присоединить его к первому не dot_node while (dnleft.GetType() == typeof(dot_node)) { dn = dnleft; dnleft = (dnleft as dot_node).left; } // В итоге в dnleft - самый внутренний left, который уже не является dot_node dnleft = new dot_node(left, dnleft, left.source_context); // Прикрепили right к самому внутреннему левому узлу в нотации a.b.c.d if (dn != null) { (dn as dot_node).left = dnleft; } else if (rdqn == null) { right = dnleft; } else { right = new dot_question_node(dnleft, (right as dot_question_node).right, dnleft.source_context); } var q = new question_colon_expression(eq, new nil_const(), right, dqn.source_context); right.Parent = q; return(q); }
public expression ConvertNamedTypeReferenceToDotNodeOrIdent(named_type_reference ntr) // либо ident либо dot_node { if (ntr.names.Count == 1) { return(ntr.names[0]); } else { var dn = new dot_node(ntr.names[0], ntr.names[1], ntr.names[0].source_context.Merge(ntr.names[1].source_context)); for (var i = 2; i < ntr.names.Count; i++) { dn = new dot_node(dn, ntr.names[i], dn.source_context.Merge(ntr.names[i].source_context)); } dn.source_context = ntr.source_context; return(dn); } }
/*public override void visit(procedure_call pc) * { * ProcessNode(pc.func_name); * var methCall = pc.func_name as method_call; * if ((object)methCall != null) * { * foreach (var param in methCall.parameters.expressions) * { * param.visit(this); * } * } * }*/ public override void visit(dot_node dn) { var rid = dn.right as ident; if ((object)rid != null && rid.name != YieldConsts.Self) { ProcessNode(dn.left); } // Most nested // DotNode (DLeft, DRight) -> DotNode(DotNode("self", "<>__self"), DRight) // LEFT self -> captured self (self.captured_self) /*var id = dn.left as ident; * if ((object)id != null && (id.className == "self" || CollectedClassFields.Contains(id.className))) * { * // Some magic for blocking back-traverse from BaseChangeVisitor redoin' work * //var rid = dn.right as ident; * //if ((object)rid != null && rid.className != Consts.Self) * { * var newDotNode = new dot_node(new dot_node(new ident("self"), new ident(Consts.Self)), dn.right); * // Change right? * //var capturedRight = new dot_node(new ident(Consts.Self), dn.right); * //var newDotNode = new dot_node(dn.left, capturedRight); * Replace(dn, newDotNode); * } * * * // Some magic for blocking back-traverse from BaseChangeVisitor redoin' work * //var rid = dn.right as ident; * //if ((object)rid != null && rid.className != Consts.Self) * // { * // var capturedSelf = new dot_node(new ident("self"), new ident(Consts.Self)); * // Replace(dn.left, capturedSelf); * // } * } * else * { * ProcessNode(dn.left); * }*/ //if (dn.right.GetType() != typeof(ident)) // ProcessNode(dn.right); }
public virtual void visit(dot_node _dot_node) { DefaultVisit(_dot_node); }
private void AddReferencesToIdentInLambda(type_declaration upperScopeWhereVarsAreCapturedClass, CapturedVariablesTreeNode scope, string varName, syntax_tree_node syntaxTreeNodeWithVarDeclaration, dot_node substDotNode, bool nestedLambda) { /*#if DEBUG * var pp = scope.ToString().IndexOf("TreeNode"); * var ss = scope.ToString().Remove(0, pp + 8).Replace("Scope"," "); * var cn = ""; * if (scope.ChildNodes.Count>0) * cn = "Childs: "+ scope.ChildNodes.Aggregate("",(s, x) => s + x.ScopeIndex.ToString() + " "); * System.IO.File.AppendAllText("d:\\w.txt", "AddR enter: " + ss + scope.ScopeIndex + " " + cn + "" +scope.CorrespondingSyntaxTreeNode + "\n"); #endif*/ for (var i = 0; i < scope.ChildNodes.Count; i++) { if (!(scope.ChildNodes[i] is CapturedVariablesTreeNodeLambdaScope)) { var substKey = new SubstitutionKey(varName, syntaxTreeNodeWithVarDeclaration, scope.ChildNodes[i].CorrespondingSyntaxTreeNode); if (_capturedVarsClassDefs.ContainsKey(scope.ChildNodes[i].ScopeIndex)) { var cl = _capturedVarsClassDefs[scope.ChildNodes[i].ScopeIndex]; if (cl.AssignNodeForUpperClassFieldInitialization == null) { var fieldType = SyntaxTreeBuilder.BuildSimpleType(upperScopeWhereVarsAreCapturedClass.type_name.name); var field = SyntaxTreeBuilder.BuildClassFieldsSection( new List <ident> { new ident(cl.GeneratedUpperClassFieldName) }, new List <type_definition> { fieldType }); var clClass = (class_definition)cl.ClassDeclaration.type_def; clClass.body.Add(field); cl.AssignNodeForUpperClassFieldInitialization = new assign( new dot_node(new ident(cl.GeneratedSubstitutingFieldName), new ident(cl.GeneratedUpperClassFieldName)), new ident(compiler_string_consts.self_word)); } } if (!_substitutions.ContainsKey(substKey)) { /*#if DEBUG * System.IO.File.AppendAllText("d:\\w.txt", "1 substitutions.Add: " + substKey + " " + substDotNode + "\n"); #endif*/ _substitutions.Add(substKey, substDotNode); } AddReferencesToIdentInLambda(upperScopeWhereVarsAreCapturedClass, scope.ChildNodes[i], varName, syntaxTreeNodeWithVarDeclaration, substDotNode, nestedLambda); } else { var scopeAsLambda = scope.ChildNodes[i] as CapturedVariablesTreeNodeLambdaScope; if (scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.HasValue) { dot_node substDotNode1; if (!nestedLambda) { var parts = new Stack <ident>(); var dn = substDotNode; parts.Push((ident)dn.right); while (!(dn.left is ident && dn.right is ident)) { dn = (dot_node)dn.left; parts.Push((ident)dn.right); } substDotNode1 = new dot_node(new ident(_capturedVarsClassDefs[scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].GeneratedUpperClassFieldName), parts.Pop()); while (parts.Count > 0) { substDotNode1 = new dot_node(substDotNode1, parts.Pop()); } } else { var parts = new Stack <ident>(); var dn = substDotNode; parts.Push((ident)dn.right); while (!(dn.left is ident && dn.right is ident)) { dn = (dot_node)dn.left; parts.Push((ident)dn.right); } parts.Push((ident)dn.left); substDotNode1 = new dot_node(new ident(_capturedVarsClassDefs[scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].GeneratedUpperClassFieldName), parts.Pop()); while (parts.Count > 0) { substDotNode1 = new dot_node(substDotNode1, parts.Pop()); } } var substKey = new SubstitutionKey(varName, syntaxTreeNodeWithVarDeclaration, scope.ChildNodes[0].CorrespondingSyntaxTreeNode); if (!_substitutions.ContainsKey(substKey)) { /*#if DEBUG * System.IO.File.AppendAllText("d:\\w.txt", "2 substitutions.Add: " + substKey + " " + substDotNode + "\n"); #endif*/ _substitutions.Add(substKey, substDotNode1); } AddReferencesToIdentInLambda(_capturedVarsClassDefs[scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].ClassDeclaration, scopeAsLambda.ChildNodes[0], varName, syntaxTreeNodeWithVarDeclaration, substDotNode1, true); } else { // SSM 25.06.19 fix #1988 - заменил ошибочное scope.ChildNodes[0] на scope.ChildNodes[i] AddReferencesToIdentInLambda(upperScopeWhereVarsAreCapturedClass, scope.ChildNodes[i], varName, syntaxTreeNodeWithVarDeclaration, substDotNode, nestedLambda); } } } /*#if DEBUG * System.IO.File.AppendAllText("d:\\w.txt", "AddR exit: " + scope.ScopeIndex+"\n"); #endif*/ }
public override void visit(dot_node _dot_node) { }
public override void visit(ident id) { // Check dot node var upper = UpperNode(1); //if (upper is dot_node) // return; var idName = id.name; var idSourceContext = id.source_context; // frninja 31/03/16 - фикс селфа для extensionmethod if (idName.ToLower() == "self" && !CollectedFormalParams.Contains(idName)) { var newSelf = new dot_node(new ident("self"), new ident(YieldConsts.Self)); Replace(id, newSelf); return; } // Detect where is id from if (CollectedLocals.Contains(idName)) { Replace(id, new ident(CapturedLocalsMap[idName], idSourceContext)); } else if (CollectedFormalParams.Contains(idName)) { Replace(id, new ident(CapturedFormalParamsMap[idName], idSourceContext)); } else if (IsInClassMethod) { // In class -> check fields //if (CollectedClassFields.Contains(idName)) { // Good // Name in class fields -> capture as class field //var capturedId = new dot_node(new dot_node(new ident("self"), new ident(YieldConsts.Self)), id); //Replace(id, capturedId); } //else { // Bad // At syntax we don't know if the className is class field or not coz of e.g. base .NET classes // HERE WE SHOULD REPLACE TO yield_unknown_reference -> so decision is passed to semantic // Check for globals will be processed at semantic, too if (!id.name.StartsWith("<")) // Check for already captured { Replace(id, new yield_unknown_ident(id, ClassName, this.IsStaticMethod)); } } } else { // Not in class -> check globals if (CollectedUnitGlobals.Contains(idName)) { // Global -> just do nothing } else { // What about static classes - search at semantic // HERE WE SHOULD REPLACE TO yield_unknown_reference -> so decision is passed to semantic } } }
public override void visit(dot_node _dot_node) { _dot_node.left.visit(this); _dot_node.right.visit(this); }
// frninja 21/05/16 public override void visit(foreach_stmt frch) { // Полный код Loweringа c yield_unknown_foreach_type = integer // var a: System.Collections.Generic.IEnumerable<integer>; // a := l; // var en := a.GetEnumerator(); // while en.MoveNext do // begin // var curr := en.Current; // var не нужно ставить если curr была описана раньше // Print(curr); // end; /// // var a: System.Collections.Generic.IEnumerable<yield_unknown_foreach_type> := l; var foreachCollIdent = this.NewForeachCollectionName(); var foreachCollType = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"), new template_param_list(new yield_unknown_foreach_type(frch))); var foreachCollVarDef = new var_statement(foreachCollIdent, foreachCollType); var ass = new assign(foreachCollIdent, frch.in_what); // var en := a.GetEnumerator(); var enumeratorIdent = this.NewEnumeratorName(); var enumeratorVarDef = new var_statement(enumeratorIdent, new method_call(new dot_node(foreachCollIdent, new ident("GetEnumerator")), new expression_list())); //var curr := en.Current; // Переменная цикла foreach. Есть три варианта: // 1. foreach x in l do -> curr := en.Current; // 2. foreach var x in l do -> var curr := en.Current; // 3. foreach var x: T in l do -> var curr: T := en.Current; var currentIdent = frch.identifier; statement st = null; var curExpr = new dot_node(enumeratorIdent, "Current"); // С типом if (frch.type_name == null) // 1. foreach x in l do -> curr := en.Current; { st = new assign(currentIdent, curExpr); } else if (frch.type_name is no_type_foreach) // 2. foreach var x in l do -> var curr := en.Current; { // Получаем служебное имя с $ и заменяем его в теле цикла currentIdent = this.NewVarNames(frch.identifier).VarName; var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent); frch.visit(replacerVis); st = new var_statement(currentIdent, curExpr); } else // 3. foreach var x: T in l do -> var curr: T := en.Current; { // Получаем служебное имя с $ и заменяем его в теле цикла currentIdent = this.NewVarNames(frch.identifier).VarName; var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent); frch.visit(replacerVis); st = new var_statement(currentIdent, frch.type_name, curExpr); } // Добавляем тело цикла в stl var stl = new statement_list(st); ProcessNode(frch.stmt); // для обработки вложенных конструкций stl.Add(frch.stmt); var whileNode = new while_node(new method_call(new dot_node(enumeratorIdent, "MoveNext"), new expression_list()), stl, WhileCycleType.While); var sq = SeqStatements(foreachCollVarDef, ass, enumeratorVarDef, whileNode); ReplaceStatement(frch, sq); visit(whileNode); // Lowering оставшегося whileNode }
public override void visit(ident id) { var idName = id.name.ToLower(); SymbolInfo si = _visitor.context.find_first(idName); //var q = si.GetHashCode(); if (si == null) { /*if (InLambdaContext) * { * _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id))); * return; * }*/ return; } if (si.sym_info.semantic_node_type == semantic_node_type.namespace_variable || si.sym_info.semantic_node_type == semantic_node_type.common_namespace_function_node || si.sym_info.semantic_node_type == semantic_node_type.namespace_constant_definition || si.sym_info.semantic_node_type == semantic_node_type.compiled_function_node || //si.sym_info.semantic_node_type == semantic_node_type.common_method_node || // SSM bug fix #1991 11.06.19 конкурирует с #891 si.sym_info.semantic_node_type == semantic_node_type.compiled_namespace_node || si.sym_info.semantic_node_type == semantic_node_type.compiled_variable_definition || si.sym_info.semantic_node_type == semantic_node_type.common_type_node || si.sym_info.semantic_node_type == semantic_node_type.compiled_type_node || si.sym_info.semantic_node_type == semantic_node_type.basic_interface_node || si.sym_info.semantic_node_type == semantic_node_type.common_unit_node || si.sym_info.semantic_node_type == semantic_node_type.common_namespace_node || si.sym_info.semantic_node_type == semantic_node_type.compiled_unit_node || si.sym_info.semantic_node_type == semantic_node_type.template_type || si.sym_info.semantic_node_type == semantic_node_type.ref_type_node || si.sym_info.semantic_node_type == semantic_node_type.generic_indicator || si.sym_info.semantic_node_type == semantic_node_type.class_constant_definition || si.sym_info.semantic_node_type == semantic_node_type.function_constant_definition || // SSM 03.11.18 bug fix #1449 si.sym_info.semantic_node_type == semantic_node_type.basic_function_node && (idName == "exit" || idName == "continue" || idName == "break")) { return; } var acceptableVarType = si.sym_info.semantic_node_type == semantic_node_type.local_variable || si.sym_info.semantic_node_type == semantic_node_type.local_block_variable || si.sym_info.semantic_node_type == semantic_node_type.common_parameter || si.sym_info.semantic_node_type == semantic_node_type.class_field || si.sym_info.semantic_node_type == semantic_node_type.basic_property_node ; //trjuk, chtoby ne perelopachivat ves kod. zamenjaem ident na self.ident // Использую этот трюк для нестатических полей предков - они не захватываются из-за плохого алгоритма захвата // aab 12.06.19 begin // Добавил такое же переименование для статичесских полей класса. Теперь захват работает if ((si.sym_info.semantic_node_type == semantic_node_type.class_field || si.sym_info.semantic_node_type == semantic_node_type.common_method_node || si.sym_info.semantic_node_type == semantic_node_type.common_event || si.sym_info.semantic_node_type == semantic_node_type.common_property_node || si.sym_info.semantic_node_type == semantic_node_type.basic_property_node) && InLambdaContext) { dot_node dn = null; // Поменял принцип добавления имени класса для статических полей и функций Func <common_type_node, addressed_value> getClassIdent = classNode => { if (classNode.name.Contains("<")) { var classIdent = new ident(classNode.name.Remove(classNode.name.IndexOf("<"))); var templateParams = new template_param_list(classNode.instance_params.Select(x => x.name) /*.Aggregate("", (acc, elem) => acc += elem)*/); return(new ident_with_templateparams(classIdent, templateParams)); } else { return(new ident(classNode.name)); } }; if (si.sym_info is class_field classField && classField.IsStatic) { dn = new dot_node(getClassIdent(classField.cont_type), new ident(id.name, id.source_context), id.source_context); } else if (si.sym_info is common_method_node commonMethodNode && commonMethodNode.IsStatic) { dn = new dot_node(getClassIdent(commonMethodNode.cont_type), new ident(id.name, id.source_context), id.source_context); }
public override void visit(dot_node _dot_node) { DefaultVisit(_dot_node); pre_do_visit(_dot_node); visit(dot_node.left); visit(dot_node.right); post_do_visit(_dot_node); }
public virtual void post_do_visit(dot_node _dot_node) { }
public virtual void visit(dot_node _dot_node) { }
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); } } }
public override void visit(dot_node _dot_node) { prepare_node(_dot_node.left, "left"); prepare_node(_dot_node.right, "right"); }
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); }
public override void visit(dot_node _dot_node) { ProcessNode(_dot_node.left); //правую часть не обходим }
public override void visit(ident id) { var idName = id.name.ToLower(); SymbolInfo si = _visitor.context.find_first(idName); if (si == null) { if (InLambdaContext) { _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id))); return; } return; } if (si.sym_info.semantic_node_type == semantic_node_type.namespace_variable || si.sym_info.semantic_node_type == semantic_node_type.common_namespace_function_node || si.sym_info.semantic_node_type == semantic_node_type.namespace_constant_definition || si.sym_info.semantic_node_type == semantic_node_type.compiled_function_node || si.sym_info.semantic_node_type == semantic_node_type.common_method_node || // SSM bug fix #167 si.sym_info.semantic_node_type == semantic_node_type.compiled_namespace_node || si.sym_info.semantic_node_type == semantic_node_type.compiled_variable_definition || si.sym_info.semantic_node_type == semantic_node_type.common_type_node || si.sym_info.semantic_node_type == semantic_node_type.compiled_type_node || si.sym_info.semantic_node_type == semantic_node_type.basic_interface_node || si.sym_info.semantic_node_type == semantic_node_type.common_unit_node || si.sym_info.semantic_node_type == semantic_node_type.common_namespace_node || si.sym_info.semantic_node_type == semantic_node_type.compiled_unit_node || si.sym_info.semantic_node_type == semantic_node_type.template_type || si.sym_info.semantic_node_type == semantic_node_type.generic_indicator || si.sym_info.semantic_node_type == semantic_node_type.class_constant_definition || si.sym_info.semantic_node_type == semantic_node_type.basic_function_node && (idName == "exit" || idName == "continue" || idName == "break")) { return; } var acceptableVarType = si.sym_info.semantic_node_type == semantic_node_type.local_variable || si.sym_info.semantic_node_type == semantic_node_type.local_block_variable || si.sym_info.semantic_node_type == semantic_node_type.common_parameter || si.sym_info.semantic_node_type == semantic_node_type.class_field ; //trjuk, chtoby ne perelopachivat ves kod. zamenjaem ident na self.ident // Использую этот трюк для нестатических полей предков - они не захватываются из-за плохого алгоритма захвата if ((si.sym_info.semantic_node_type == semantic_node_type.class_field && !(si.sym_info as class_field).IsStatic || si.sym_info.semantic_node_type == semantic_node_type.common_event || si.sym_info.semantic_node_type == semantic_node_type.common_property_node) && InLambdaContext) { dot_node dn = new dot_node(new ident("self", id.source_context), new ident(id.name, id.source_context), id.source_context); bool ok = true; try { id.Parent.ReplaceDescendantUnsafe(id, dn); } catch { ok = false; } if (ok) { ProcessNode(id.Parent); return; } } if (!(acceptableVarType) && InLambdaContext) { _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id))); return; } /*if (si.sym_info.semantic_node_type == semantic_node_type.class_field && InLambdaContext) * { * var semClassField = (class_field)si.sym_info; * if (semClassField.polymorphic_state != polymorphic_state.ps_common) * { * _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id))); * return; * } * }*/ if (si.scope == null) { return; } var scopeIndex = si.scope.ScopeNum; var selfWordInClass = false; CapturedVariablesTreeNode scope; if (_scopesCapturedVarsNodesDictionary.TryGetValue(scopeIndex, out scope)) { var prScope = scope as CapturedVariablesTreeNodeProcedureScope; if (prScope != null && acceptableVarType) { if (si.sym_info.semantic_node_type == semantic_node_type.local_variable) { if (!(idName == compiler_string_consts.self_word && si.scope is SymbolTable.ClassMethodScope && _classScope != null) && InLambdaContext) { _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id))); } } if (si.sym_info.semantic_node_type == semantic_node_type.common_parameter && prScope.FunctionNode.parameters.First(v => v.name.ToLower() == idName).parameter_type != parameter_type.value && InLambdaContext) { _visitor.AddError(new CannotCaptureNonValueParameters(_visitor.get_location(id))); } if (idName == compiler_string_consts.self_word && si.scope is SymbolTable.ClassMethodScope && _classScope != null) { var selfField = _classScope.VariablesDefinedInScope.Find(var => var.SymbolInfo == si); if (selfField == null) { _classScope.VariablesDefinedInScope.Add( new CapturedVariablesTreeNode.CapturedSymbolInfo(null, si)); } selfWordInClass = true; } else { var field = prScope.VariablesDefinedInScope.Find(var => var.SymbolInfo == si); if (field == null) { prScope.VariablesDefinedInScope.Add(new CapturedVariablesTreeNode.CapturedSymbolInfo(null, si)); } } } var clScope = scope as CapturedVariablesTreeNodeClassScope; if (clScope != null && acceptableVarType) { var field = clScope.VariablesDefinedInScope.Find(var => var.SymbolInfo == si); if (field == null) { clScope.VariablesDefinedInScope.Add(new CapturedVariablesTreeNode.CapturedSymbolInfo(null, si)); } if (si.access_level != access_level.al_public) { if (!clScope.NonPublicMembersNamesMapping.ContainsKey(idName)) { var name = LambdaHelper.GetNameForNonPublicMember(idName); var semClassField = (class_field)si.sym_info; var pn = new common_property_node(name, _visitor.context._ctn, null, field_access_level.fal_public, semClassField.polymorphic_state); pn.internal_property_type = _visitor.convert_strong(id).type; clScope.NonPublicMembersNamesMapping.Add(idName, new Tuple <string, class_field, semantic_node>(name, semClassField, pn)); } } } var idRef = (selfWordInClass ? _classScope : scope) .VariablesDefinedInScope .Find(var => var.SymbolInfo == si); if (idRef == null) //TODO: Осторожнее переделать { { return; } } if (_currentTreeNode.CorrespondingSyntaxTreeNode != null) { var varName = ((IVAriableDefinitionNode)idRef.SymbolInfo.sym_info).name; //TODO: случай параметров и полей класса!!!!!!!!!!!!!!!!!! var substKey = new SubstitutionKey(varName, idRef.SyntaxTreeNodeWithVarDeclaration, _currentTreeNode.CorrespondingSyntaxTreeNode); if (!_identsReferences.ContainsKey(substKey)) { _identsReferences.Add(substKey, new List <ident>()); } _identsReferences[substKey].Add(id); } if (InLambdaContext && scope is CapturedVariablesTreeNodeLambdaScope && scopeIndex < _currentLambdaScopeNodeStack.Peek().ScopeIndex) //TODO: Захват параметров лямбды в другой лямбде { _visitor.AddError(new ThisTypeOfVariablesCannotBeCaptured(_visitor.get_location(id))); return; } if (!InLambdaContext || scopeIndex >= _currentLambdaScopeNodeStack.Peek().ScopeIndex) { return; } var stackAsList = _currentLambdaScopeNodeStack.ToList(); stackAsList.RemoveAt(0); if (!_currentLambdaScopeNodeStack.Peek().CapturedVarsSymbolInfo.Contains(si)) { _currentLambdaScopeNodeStack.Peek().CapturedVarsSymbolInfo.Add(si); foreach (var capturedVariablesTreeNodeLambdaScope in stackAsList) { if (!capturedVariablesTreeNodeLambdaScope.CapturedVarsSymbolInfo.Contains(si)) { capturedVariablesTreeNodeLambdaScope.CapturedVarsSymbolInfo.Add(si); } } } if (!idRef.ReferencingLambdas.Contains(_currentLambdaScopeNodeStack.Peek())) { idRef.ReferencingLambdas.Add(_currentLambdaScopeNodeStack.Peek()); foreach (var capturedVariablesTreeNodeLambdaScope in stackAsList) { if (!idRef.ReferencingLambdas.Contains(capturedVariablesTreeNodeLambdaScope)) { idRef.ReferencingLambdas.Add(capturedVariablesTreeNodeLambdaScope); } } } } }
private void AddReferencesToIdentInLambda(type_declaration upperScopeWhereVarsAreCapturedClass, CapturedVariablesTreeNode scope, string varName, syntax_tree_node syntaxTreeNodeWithVarDeclaration, dot_node substDotNode, bool nestedLambda) { for (var i = 0; i < scope.ChildNodes.Count; i++) { if (!(scope.ChildNodes[i] is CapturedVariablesTreeNodeLambdaScope)) { var substKey = new SubstitutionKey(varName, syntaxTreeNodeWithVarDeclaration, scope.ChildNodes[i].CorrespondingSyntaxTreeNode); if (_capturedVarsClassDefs.ContainsKey(scope.ChildNodes[i].ScopeIndex)) { var cl = _capturedVarsClassDefs[scope.ChildNodes[i].ScopeIndex]; if (cl.AssignNodeForUpperClassFieldInitialization == null) { var fieldType = SyntaxTreeBuilder.BuildSimpleType(upperScopeWhereVarsAreCapturedClass.type_name.name); var field = SyntaxTreeBuilder.BuildClassFieldsSection( new List <ident> { new ident(cl.GeneratedUpperClassFieldName) }, new List <type_definition> { fieldType }); var clClass = (class_definition)cl.ClassDeclaration.type_def; clClass.body.Add(field); cl.AssignNodeForUpperClassFieldInitialization = new assign( new dot_node(new ident(cl.GeneratedSubstitutingFieldName), new ident(cl.GeneratedUpperClassFieldName)), new ident(compiler_string_consts.self_word)); } } if (!_substitutions.ContainsKey(substKey)) { _substitutions.Add(substKey, substDotNode); } AddReferencesToIdentInLambda(upperScopeWhereVarsAreCapturedClass, scope.ChildNodes[i], varName, syntaxTreeNodeWithVarDeclaration, substDotNode, nestedLambda); } else { var scopeAsLambda = scope.ChildNodes[i] as CapturedVariablesTreeNodeLambdaScope; if (scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.HasValue) { dot_node substDotNode1; if (!nestedLambda) { var parts = new Stack <ident>(); var dn = substDotNode; parts.Push((ident)dn.right); while (!(dn.left is ident && dn.right is ident)) { dn = (dot_node)dn.left; parts.Push((ident)dn.right); } substDotNode1 = new dot_node(new ident(_capturedVarsClassDefs[scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].GeneratedUpperClassFieldName), parts.Pop()); while (parts.Count > 0) { substDotNode1 = new dot_node(substDotNode1, parts.Pop()); } } else { var parts = new Stack <ident>(); var dn = substDotNode; parts.Push((ident)dn.right); while (!(dn.left is ident && dn.right is ident)) { dn = (dot_node)dn.left; parts.Push((ident)dn.right); } parts.Push((ident)dn.left); substDotNode1 = new dot_node(new ident(_capturedVarsClassDefs[scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].GeneratedUpperClassFieldName), parts.Pop()); while (parts.Count > 0) { substDotNode1 = new dot_node(substDotNode1, parts.Pop()); } } var substKey = new SubstitutionKey(varName, syntaxTreeNodeWithVarDeclaration, scope.ChildNodes[0].CorrespondingSyntaxTreeNode); if (!_substitutions.ContainsKey(substKey)) { _substitutions.Add(substKey, substDotNode1); } AddReferencesToIdentInLambda(_capturedVarsClassDefs[scopeAsLambda.ScopeIndexOfClassWhereLambdaWillBeAddedAsMethod.Value].ClassDeclaration, scopeAsLambda.ChildNodes[0], varName, syntaxTreeNodeWithVarDeclaration, substDotNode1, true); } else { AddReferencesToIdentInLambda(upperScopeWhereVarsAreCapturedClass, scope.ChildNodes[0], varName, syntaxTreeNodeWithVarDeclaration, substDotNode, nestedLambda); } } } }
public override void visit(dot_node _dot_node) { executer.visit(_dot_node); if (_dot_node.left != null) this.visit((dynamic)_dot_node.left); if (_dot_node.right != null) this.visit((dynamic)_dot_node.right); if (_dot_node.attributes != null) this.visit((dynamic)_dot_node.attributes); }