LightSymInfo rework (#2994)
* LightSymInfo rework * add rebuildDebug and build units * enable VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer * remove CollectFullLightSymInfo call * fix fix remove CollectFullLightSymInfo call
This commit is contained in:
parent
8193bc730f
commit
a8b1e9035b
|
|
@ -21,12 +21,11 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
// FillParentNodeVisitor расположен в SyntaxTree/tree как базовый визитор, отвечающий за построение дерева
|
||||
//FillParentNodeVisitor.New.ProcessNode(root); // почему-то перепрошивает не всё. А следующий вызов - всё
|
||||
root.FillParentsInAllChilds();
|
||||
|
||||
|
||||
#if DEBUG
|
||||
// var stat = new ABCStatisticsVisitor();
|
||||
// stat.ProcessNode(root);
|
||||
// var stat = new ABCStatisticsVisitor();
|
||||
// stat.ProcessNode(root);
|
||||
#endif
|
||||
|
||||
// new range - до всего! До выноса выражения с лямбдой из foreach. 11.07 добавил поиск yields и присваивание pd.HasYield
|
||||
NewRangeDesugarAndFindHasYieldVisitor.New.ProcessNode(root);
|
||||
|
||||
|
|
@ -38,7 +37,7 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
|
||||
// Выносим выражения с лямбдами из заголовка foreach + считаем максимум 10 вложенных лямбд
|
||||
StandOutExprWithLambdaInForeachSequenceAndNestedLambdasVisitor.New.ProcessNode(root);
|
||||
VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer.New.ProcessNode(root); // SSM bug fix #1147
|
||||
new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer(root as compilation_unit).ProcessNode(root);
|
||||
FindOnExceptVarsAndApplyRenameVisitor.New.ProcessNode(root);
|
||||
|
||||
// loop
|
||||
|
|
@ -54,13 +53,13 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
IndexVisitor.New.ProcessNode(root);
|
||||
|
||||
// slice_expr и slice_expr_question
|
||||
SliceDesugarVisitor.New.ProcessNode(root);
|
||||
SliceDesugarVisitor.New.ProcessNode(root);
|
||||
// поставил раньше AssignTuplesDesugarVisitor из за var (a,b) := a[1:3];
|
||||
|
||||
// теперь коллизия с (a[1:6], a[6:11]):= (a[6:11], a[1:6]);
|
||||
// assign_tuple и assign_var_tuple
|
||||
AssignTuplesDesugarVisitor.New.ProcessNode(root); // теперь это - на семантике
|
||||
|
||||
|
||||
|
||||
// question_point_desugar_visitor
|
||||
QuestionPointDesugarVisitor.New.ProcessNode(root);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTree
|
||||
{
|
||||
public class BindCollectLightSymInfo : CollectLightSymInfoVisitor
|
||||
{
|
||||
protected override AbstractScopeCreator scopeCreator => _scopeCreator;
|
||||
|
||||
private CachingScopeCreator _scopeCreator = new CachingScopeCreator();
|
||||
|
||||
public BindCollectLightSymInfo(compilation_unit root) : base(root)
|
||||
{
|
||||
Current = Root;
|
||||
visit(root);
|
||||
}
|
||||
|
||||
public SymInfoSyntax bind(ident node)
|
||||
{
|
||||
///Console.WriteLine("searching " + node.ToString());
|
||||
syntax_tree_node cur_node = node;
|
||||
while (cur_node != null)
|
||||
{
|
||||
// Console.WriteLine("cur_node: " + cur_node.ToString());
|
||||
|
||||
if (AbstractScopeCreator.IsScopeCreator(cur_node))
|
||||
{
|
||||
|
||||
//Console.WriteLine("checking scope" + cur_node.ToString())
|
||||
var cur_scope = scopeCreator.GetScope(cur_node);
|
||||
//Console.WriteLine(cur_scope.ToString() + ": " + cur_scope.Symbols.Count);
|
||||
var prev_scope = Current;
|
||||
|
||||
if (prev_scope != null)
|
||||
prev_scope.Parent = cur_scope;
|
||||
|
||||
Current = cur_scope;
|
||||
if (cur_scope.Parent == null && !(Current is GlobalScopeSyntax))
|
||||
{
|
||||
//Console.WriteLine("visiting " + cur_node.ToString());
|
||||
cur_node.visit(this);
|
||||
}
|
||||
var res = Current.bind(node);
|
||||
if (res != null) return res;
|
||||
}
|
||||
cur_node = cur_node.Parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Enter(syntax_tree_node st)
|
||||
{
|
||||
if (AbstractScopeCreator.IsScopeCreator(st))
|
||||
{
|
||||
if (st is procedure_definition pd)
|
||||
{
|
||||
var attr = pd.proc_header.class_keyword ? SymbolAttributes.class_attr : 0;
|
||||
var name = pd.proc_header?.name?.meth_name;
|
||||
if (name != null)
|
||||
if (pd.proc_header is function_header)
|
||||
Current.AddSymbol(name, SymKind.funcname, null, attr);
|
||||
else
|
||||
Current.AddSymbol(name, SymKind.procname, null, attr);
|
||||
}
|
||||
|
||||
visitNode = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void PreExitScope(syntax_tree_node st){}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTree
|
||||
{
|
||||
public class CollectFullLightSymInfoVisitor : CollectLightSymInfoVisitor
|
||||
{
|
||||
protected override AbstractScopeCreator scopeCreator => _scopeCreator;
|
||||
|
||||
private CachingScopeCreator _scopeCreator = new CachingScopeCreator();
|
||||
|
||||
public CollectFullLightSymInfoVisitor(compilation_unit root) : base(root)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Enter(syntax_tree_node st)
|
||||
{
|
||||
var scope = scopeCreator.GetScope(st);
|
||||
if (scope != null)
|
||||
{
|
||||
scope.Parent = Current;
|
||||
Current = scope;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Exit(syntax_tree_node st)
|
||||
{
|
||||
if (AbstractScopeCreator.IsScopeCreator(st))
|
||||
{
|
||||
PreExitScope(st);
|
||||
if (Current != null)
|
||||
Current = Current.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
public override void visit(procedure_definition node)
|
||||
{
|
||||
var name = node.proc_header?.name?.meth_name;
|
||||
var attr = node.proc_header.class_keyword ? SymbolAttributes.class_attr : 0;
|
||||
if (name != null)
|
||||
if (node.proc_header is function_header)
|
||||
Current.Parent.AddSymbol(name, SymKind.funcname, null, attr);
|
||||
else
|
||||
Current.Parent.AddSymbol(name, SymKind.procname, null, attr);
|
||||
|
||||
base.visit(node);
|
||||
}
|
||||
|
||||
public override void PreExitScope(syntax_tree_node st)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTree
|
||||
{
|
||||
public abstract class CollectLightSymInfoVisitor : BaseEnterExitVisitor
|
||||
{
|
||||
|
||||
|
||||
public GlobalScopeSyntax Root;
|
||||
public ScopeSyntax Current;
|
||||
protected Dictionary<string, NamedScopeSyntax> classes = new Dictionary<string, NamedScopeSyntax>();
|
||||
|
||||
|
||||
protected bool inPrivate = false;
|
||||
|
||||
public CollectLightSymInfoVisitor(compilation_unit root)
|
||||
{
|
||||
Root = scopeCreator.GetScope(root) as GlobalScopeSyntax;
|
||||
}
|
||||
|
||||
|
||||
|
||||
abstract protected AbstractScopeCreator scopeCreator
|
||||
{ get; }
|
||||
|
||||
|
||||
public ScopeSyntax GetScope(syntax_tree_node node) => scopeCreator.GetScope(node);
|
||||
|
||||
public abstract void PreExitScope(syntax_tree_node st);
|
||||
|
||||
public override void visit(var_def_statement vd)
|
||||
{
|
||||
var attr = vd.var_attr == definition_attribute.Static ? SymbolAttributes.class_attr : 0;
|
||||
if (vd == null || vd.vars == null || vd.vars.list == null)
|
||||
return;
|
||||
AddSymbols(vd.vars.list, SymKind.var, vd.vars_type, attr);
|
||||
base.visit(vd);
|
||||
}
|
||||
public override void visit(formal_parameters fp)
|
||||
{
|
||||
foreach (var pg in fp.params_list)
|
||||
{
|
||||
if (pg.param_kind == parametr_kind.var_parametr)
|
||||
AddSymbols(pg.idents.idents, SymKind.param, null, SymbolAttributes.varparam_attr);
|
||||
else
|
||||
AddSymbols(pg.idents.idents, SymKind.param);
|
||||
}
|
||||
base.visit(fp);
|
||||
}
|
||||
|
||||
public override void visit (simple_const_definition node)
|
||||
{
|
||||
AddSymbol(node.const_name, SymKind.const_var);
|
||||
}
|
||||
|
||||
public override void visit(type_declaration td)
|
||||
{
|
||||
if (td.type_def is class_definition cd)
|
||||
{
|
||||
var tname = td.type_name;
|
||||
if (cd.keyword == class_keyword.Class || cd.keyword == class_keyword.TemplateClass)
|
||||
AddSymbol(tname, SymKind.classname);
|
||||
else if (cd.keyword == class_keyword.Record || cd.keyword == class_keyword.TemplateRecord)
|
||||
AddSymbol(tname, SymKind.recordname);
|
||||
else if (cd.keyword == class_keyword.Interface || cd.keyword == class_keyword.TemplateInterface)
|
||||
AddSymbol(tname, SymKind.interfacename);
|
||||
|
||||
if (!classes.ContainsKey(td.type_name.name))
|
||||
{
|
||||
classes.Add(td.type_name.name, scopeCreator.GetScope(td.type_def) as NamedScopeSyntax);
|
||||
//Console.WriteLine("Added" + td.type_name.name + " " + (scopeCreator.GetScope(td.type_def) as ClassScopeSyntax));
|
||||
}
|
||||
}
|
||||
else if (td.type_def is named_type_reference)
|
||||
{
|
||||
AddSymbol(td.type_name, SymKind.type_alias);
|
||||
}
|
||||
base.visit(td);
|
||||
}
|
||||
|
||||
public override void visit(class_members cm)
|
||||
{
|
||||
if (cm.access_mod.access_level == access_modifer.private_modifer)
|
||||
{
|
||||
inPrivate = true;
|
||||
}
|
||||
base.visit(cm);
|
||||
inPrivate = false;
|
||||
}
|
||||
|
||||
public override void visit(for_node f)
|
||||
{
|
||||
if (f.create_loop_variable || f.type_name != null)
|
||||
AddSymbol(f.loop_variable, SymKind.var, f.type_name);
|
||||
base.visit(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void visit(procedure_definition node)
|
||||
{
|
||||
var name = node.proc_header?.name?.meth_name;
|
||||
var attr = node.proc_header.class_keyword ? SymbolAttributes.class_attr : 0;
|
||||
|
||||
if (name != null)
|
||||
if (node.proc_header?.name?.class_name != null)
|
||||
{
|
||||
var class_name = node.proc_header.name.class_name.name;
|
||||
if (classes.ContainsKey(class_name))
|
||||
{
|
||||
(Current as ProcScopeSyntax).classParent = classes[class_name];
|
||||
(Current as ProcScopeSyntax).classParent.AddSymbol(name, SymKind.funcname, null, attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
base.visit(node);
|
||||
}
|
||||
|
||||
public override void visit(class_definition cd)
|
||||
{
|
||||
var classScope = Current as NamedScopeSyntax;
|
||||
if (cd.class_parents != null )
|
||||
foreach (var parent in cd.class_parents.types)
|
||||
if (parent.names.Count == 1)
|
||||
if (classes.ContainsKey(parent.FirstIdent.name))
|
||||
classScope.classParent = classes[parent.FirstIdent.name];
|
||||
base.visit(cd);
|
||||
}
|
||||
|
||||
public override void visit(procedure_header node)
|
||||
{
|
||||
if ( node.template_args != null)
|
||||
{
|
||||
foreach (var template_name in node.template_args.idents)
|
||||
{
|
||||
AddSymbol(template_name, SymKind.template_param);
|
||||
}
|
||||
}
|
||||
base.visit(node);
|
||||
}
|
||||
|
||||
public override void visit(template_type_name node)
|
||||
{
|
||||
foreach (var name in node.template_args.idents)
|
||||
{
|
||||
AddSymbol(name, SymKind.template_param);
|
||||
}
|
||||
base.visit(node);
|
||||
}
|
||||
|
||||
public override void visit(property_ident node)
|
||||
{
|
||||
AddSymbol(node, SymKind.property);
|
||||
}
|
||||
|
||||
|
||||
public virtual void AddSymbol(ident name, SymKind kind, type_definition td = null, SymbolAttributes attr = 0)
|
||||
{
|
||||
if (inPrivate)
|
||||
attr &= SymbolAttributes.private_attr;
|
||||
Current.AddSymbol(name, kind, td, attr);
|
||||
}
|
||||
public void AddSymbols(List<ident> names, SymKind kind, type_definition td = null, SymbolAttributes attr = 0)
|
||||
{
|
||||
foreach (var n in names)
|
||||
{
|
||||
AddSymbol(n, kind, td, attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public string Spaces(int n) => new string(' ', n);
|
||||
public void OutputString(string s) => System.IO.File.AppendAllText(fname, s);
|
||||
public void OutputlnString(string s = "") => System.IO.File.AppendAllText(fname, s + '\n');
|
||||
public void Output(string fname)
|
||||
{
|
||||
#if DEBUG
|
||||
this.fname = fname;
|
||||
if (System.IO.File.Exists(fname))
|
||||
System.IO.File.Delete(fname);
|
||||
OutputElement(0, Root);
|
||||
#endif
|
||||
}
|
||||
string fname;
|
||||
public void OutputElement(int d, ScopeSyntax s)
|
||||
{
|
||||
OutputString(Spaces(d));
|
||||
if (s == null)
|
||||
throw new Exception("ggggggggg");
|
||||
if (s is ParamsScopeSyntax)
|
||||
{
|
||||
OutputString(s.ToString() + ": ");
|
||||
if (s.Symbols.Count > 0)
|
||||
OutputlnString(string.Join(", ", s.Symbols.Select(x => x.ToString())));
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputlnString(s.ToString());
|
||||
if (s.Symbols.Count > 0)
|
||||
OutputlnString(Spaces(d + 2) + string.Join(", ", s.Symbols.Select(x => x.ToString())));
|
||||
}
|
||||
foreach (var sc in s.Children)
|
||||
OutputElement(d + 2, sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
131
SyntaxVisitors/LightSymInfoVisitors/LightScopeCreator.cs
Normal file
131
SyntaxVisitors/LightSymInfoVisitors/LightScopeCreator.cs
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTree
|
||||
{
|
||||
|
||||
public abstract class AbstractScopeCreator
|
||||
{
|
||||
public static bool IsScopeCreator(syntax_tree_node st)
|
||||
{
|
||||
|
||||
if (st is compilation_unit || st is procedure_definition || st is statement_list ||
|
||||
st is for_node || st is foreach_stmt || st is class_definition || st is record_type ||
|
||||
st is function_lambda_definition || st is case_node) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual ScopeSyntax GetScope(syntax_tree_node st)
|
||||
{
|
||||
ScopeSyntax res = null;
|
||||
if (st is compilation_unit p) res = CreateScope(p);
|
||||
else if (st is procedure_definition pd) res = CreateScope(pd);
|
||||
else if (st is statement_list sl) res = CreateScope(sl);
|
||||
else if (st is for_node f) res = CreateScope(f);
|
||||
else if (st is foreach_stmt fe) res = CreateScope(fe);
|
||||
else if (st is class_definition cd) res = CreateScope(cd);
|
||||
else if (st is record_type rt) res = CreateScope(rt);
|
||||
else if (st is function_lambda_definition fld) res = CreateScope(fld);
|
||||
else if (st is case_node cas) res = CreateScope(cas);
|
||||
if (res != null) res.node = st;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
protected abstract ScopeSyntax CreateScope(compilation_unit node);
|
||||
protected abstract ScopeSyntax CreateScope(procedure_definition node);
|
||||
protected abstract ScopeSyntax CreateScope(statement_list node);
|
||||
protected abstract ScopeSyntax CreateScope(for_node node);
|
||||
protected abstract ScopeSyntax CreateScope(foreach_stmt node);
|
||||
protected abstract ScopeSyntax CreateScope(class_definition node);
|
||||
protected abstract ScopeSyntax CreateScope(record_type node);
|
||||
protected abstract ScopeSyntax CreateScope(function_lambda_definition node);
|
||||
protected abstract ScopeSyntax CreateScope(case_node node);
|
||||
}
|
||||
|
||||
class CachingScopeCreator : AbstractScopeCreator
|
||||
{
|
||||
Dictionary<syntax_tree_node, ScopeSyntax> map = new Dictionary<syntax_tree_node, ScopeSyntax>();
|
||||
|
||||
public override ScopeSyntax GetScope(syntax_tree_node st)
|
||||
{
|
||||
if (st == null) return null;
|
||||
if (!map.ContainsKey(st))
|
||||
{
|
||||
var scope = base.GetScope(st);
|
||||
if (scope != null) map.Add(st, scope);
|
||||
else return null;
|
||||
}
|
||||
return map[st];
|
||||
}
|
||||
|
||||
protected override ScopeSyntax CreateScope(compilation_unit node) {
|
||||
|
||||
if (node is unit_module um)
|
||||
return new UnitScopeSyntax();
|
||||
if (node is program_module pm)
|
||||
return new ProgramScopeSyntax();
|
||||
|
||||
throw new ArgumentException("Unkmown global scope type!!!");
|
||||
}
|
||||
|
||||
|
||||
protected override ScopeSyntax CreateScope(procedure_definition node)
|
||||
{
|
||||
|
||||
var name = node.proc_header?.name?.meth_name;
|
||||
if (name == null)
|
||||
name = "create";
|
||||
var res = new ProcScopeSyntax(name);
|
||||
if (node.proc_header is function_header fh)
|
||||
{
|
||||
res.AddSymbol(new ident("Result", node.source_context), SymKind.var, fh.return_type);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
protected override ScopeSyntax CreateScope(statement_list node) => new StatListScopeSyntax();
|
||||
|
||||
protected override ScopeSyntax CreateScope(for_node node) => new ForScopeSyntax();
|
||||
|
||||
protected override ScopeSyntax CreateScope(foreach_stmt node) => new ForeachScopeSyntax();
|
||||
|
||||
protected override ScopeSyntax CreateScope(class_definition cd)
|
||||
{
|
||||
var td = cd.Parent as type_declaration;
|
||||
var tname = td == null ? "NONAME" : td.type_name;
|
||||
ScopeSyntax res = null;
|
||||
|
||||
if (cd.keyword == class_keyword.Class)
|
||||
{
|
||||
res = new ClassScopeSyntax(tname);
|
||||
}
|
||||
else if (cd.keyword == class_keyword.Record)
|
||||
{
|
||||
res = new RecordScopeSyntax(tname);
|
||||
}
|
||||
else if (cd.keyword == class_keyword.Interface)
|
||||
{
|
||||
res = new InterfaceScopeSyntax(tname);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
protected override ScopeSyntax CreateScope(record_type node)
|
||||
{
|
||||
var td = node.Parent as type_declaration;
|
||||
var tname = td == null ? "NONAME" : td.type_name;
|
||||
return new RecordScopeSyntax(tname);
|
||||
}
|
||||
|
||||
protected override ScopeSyntax CreateScope(function_lambda_definition node) => new LambdaScopeSyntax();
|
||||
|
||||
protected override ScopeSyntax CreateScope(case_node node) => new CaseScopeSyntax();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
|
@ -17,10 +18,11 @@ using System.Text;
|
|||
|
||||
namespace PascalABCCompiler.SyntaxTree
|
||||
{
|
||||
public enum SymKind { var, field, param, procname, funcname, classname, recordname, interfacename };
|
||||
public enum SymKind { var, field, param, procname, funcname, classname,
|
||||
recordname, interfacename, template_param, type_alias, const_var, property };
|
||||
|
||||
[Flags]
|
||||
public enum Attributes { class_attr = 1, varparam_attr = 2};
|
||||
public enum SymbolAttributes { class_attr = 1, varparam_attr = 2, private_attr = 4};
|
||||
|
||||
public class SymInfoSyntax
|
||||
{
|
||||
|
|
@ -37,45 +39,130 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
public ident Id { get; set; }
|
||||
public type_definition Td { get; set; }
|
||||
public SymKind SK { get; set; }
|
||||
public Attributes Attr { get; set; }
|
||||
public SymInfoSyntax(ident Id, SymKind SK, type_definition Td = null, Attributes Attr = 0)
|
||||
public SymbolAttributes Attr { get; set; }
|
||||
public SymInfoSyntax(ident Id, SymKind SK, type_definition Td = null, SymbolAttributes Attr = 0)
|
||||
{
|
||||
this.Id = Id;
|
||||
this.Td = Td;
|
||||
this.SK = SK;
|
||||
this.Attr = Attr;
|
||||
}
|
||||
public void AddAttribute(Attributes attr)
|
||||
public void AddAttribute(SymbolAttributes attr)
|
||||
{
|
||||
Attr &= attr;
|
||||
Attr |= attr;
|
||||
}
|
||||
}
|
||||
|
||||
public class ScopeSyntax
|
||||
public abstract class ScopeSyntax
|
||||
{
|
||||
public syntax_tree_node node;
|
||||
|
||||
public ScopeSyntax Parent { get; set; }
|
||||
public List<ScopeSyntax> Children = new List<ScopeSyntax>();
|
||||
public List<SymInfoSyntax> Symbols = new List<SymInfoSyntax>();
|
||||
public HashSet<SymInfoSyntax> Symbols = new HashSet<SymInfoSyntax>();
|
||||
public override string ToString() => GetType().Name.Replace("Syntax", "");
|
||||
|
||||
protected virtual SymInfoSyntax searchSymbol(ident id)
|
||||
{
|
||||
foreach (var s in Symbols)
|
||||
{
|
||||
|
||||
if (s.Id.name == id.name && (id.source_context == null ||
|
||||
s.Id.source_context == null ||
|
||||
s.Id.source_context.Less(id.source_context)))
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void AddSymbol(ident name, SymKind kind, type_definition td = null, SymbolAttributes attr = 0)
|
||||
{
|
||||
Symbols.Add(new SymInfoSyntax(name, kind, td, attr));
|
||||
}
|
||||
public virtual SymInfoSyntax bind(ident id)
|
||||
{
|
||||
return searchSymbol(id);
|
||||
}
|
||||
|
||||
}
|
||||
public class ScopeWithDefsSyntax : ScopeSyntax { } //
|
||||
public class GlobalScopeSyntax : ScopeWithDefsSyntax { } // program_module unit_module
|
||||
public abstract class GlobalScopeSyntax : ScopeWithDefsSyntax { } // program_module unit_module
|
||||
|
||||
public class NamedScopeSyntax : ScopeWithDefsSyntax
|
||||
public class ProgramScopeSyntax : GlobalScopeSyntax { }
|
||||
|
||||
public class UnitScopeSyntax : GlobalScopeSyntax { }
|
||||
|
||||
public abstract class NamedScopeSyntax : ScopeWithDefsSyntax
|
||||
{
|
||||
public NamedScopeSyntax classParent;
|
||||
public ident Name { get; set; }
|
||||
public NamedScopeSyntax(ident Name) => this.Name = Name;
|
||||
public override string ToString() => base.ToString() + "(" + Name + ")";
|
||||
|
||||
protected SymInfoSyntax searchInParentClass(ident id)
|
||||
{
|
||||
if (classParent == null) return null;
|
||||
foreach (var symbol in classParent.Symbols)
|
||||
{
|
||||
if (symbol.Id.name == id.name && !symbol.Attr.HasFlag(SymbolAttributes.private_attr))
|
||||
{
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SymInfoSyntax bind(ident id)
|
||||
{
|
||||
SymInfoSyntax res = searchSymbol(id);
|
||||
if (res != null) return res;
|
||||
var cur = this;
|
||||
while (cur != null)
|
||||
{
|
||||
res = cur.searchInParentClass(id);
|
||||
if (res != null) return res;
|
||||
cur = cur.classParent;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcScopeSyntax : NamedScopeSyntax // procedure_definition
|
||||
{
|
||||
{
|
||||
|
||||
public ProcScopeSyntax(ident Name) : base(Name) { }
|
||||
|
||||
public override SymInfoSyntax bind(ident id)
|
||||
{
|
||||
|
||||
var res = classParent?.bind(id);
|
||||
if (res != null) return res;
|
||||
return base.bind(id);
|
||||
}
|
||||
}
|
||||
public class ParamsScopeSyntax : ScopeSyntax { } // formal_parameters
|
||||
public class ClassScopeSyntax : NamedScopeSyntax
|
||||
public class ClassScopeSyntax
|
||||
: NamedScopeSyntax
|
||||
{
|
||||
public ClassScopeSyntax(ident Name) : base(Name) { }
|
||||
|
||||
protected SymInfoSyntax searchSymbol(ident id)
|
||||
{
|
||||
//Console.WriteLine("searching " + id.ToString() + " in " + Name);
|
||||
foreach (var s in Symbols)
|
||||
{
|
||||
// Console.WriteLine("Checking " + s.Id);
|
||||
if (s.Id.name == id.name)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
} //
|
||||
public class RecordScopeSyntax : NamedScopeSyntax
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,225 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
/*
|
||||
ProgramScopeSyntax
|
||||
BlockScopeSyntax
|
||||
ProcScopeSyntax (name)
|
||||
ParamsScopeSyntax
|
||||
BlockScopeSyntax
|
||||
StatListScopeSyntax (0)
|
||||
StatListScopeSyntax (1)
|
||||
StatListScopeSyntax (0)
|
||||
StatListScopeSyntax (1)
|
||||
*/
|
||||
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTree
|
||||
{
|
||||
// Визитор накопления легковесной синтаксической таблицы символов.
|
||||
// Не дописан. Имеет большой потенциал применения
|
||||
public partial class CollectLightSymInfoVisitor : BaseEnterExitVisitor
|
||||
{
|
||||
public ScopeSyntax Root;
|
||||
/// <summary>
|
||||
/// Текущее пространство имен
|
||||
/// </summary>
|
||||
public ScopeSyntax Current;
|
||||
|
||||
public static CollectLightSymInfoVisitor New => new CollectLightSymInfoVisitor();
|
||||
public override void Enter(syntax_tree_node st)
|
||||
{
|
||||
ScopeSyntax t = null;
|
||||
/*switch (st)
|
||||
{
|
||||
case program_module p:
|
||||
case unit_module u:
|
||||
t = new GlobalScopeSyntax();
|
||||
Root = t;
|
||||
break;
|
||||
case procedure_definition p:
|
||||
var name = p.proc_header?.name?.meth_name;
|
||||
if (name == null)
|
||||
name = "create";
|
||||
var attr = p.proc_header.class_keyword ? Attributes.class_attr : 0;
|
||||
if (name != null)
|
||||
if (p.proc_header is function_header)
|
||||
AddSymbol(name, SymKind.funcname,null, attr);
|
||||
else AddSymbol(name, SymKind.procname, null, attr);
|
||||
t = new ProcScopeSyntax(name);
|
||||
break;
|
||||
//case formal_parameters p:// Это неправильный Scope - он закрывался при выходе из секции формальных параметров, что неправильно
|
||||
// t = new ParamsScopeSyntax();
|
||||
// break;
|
||||
case statement_list p:
|
||||
t = new StatListScopeSyntax();
|
||||
break;
|
||||
case for_node p:
|
||||
t = new ForScopeSyntax();
|
||||
break;
|
||||
case foreach_stmt p:
|
||||
t = new ForeachScopeSyntax();
|
||||
break;
|
||||
//case repeat_node p: // не надо т.к. это StatListScope
|
||||
// t = new RepeatScopeSyntax();
|
||||
// break;
|
||||
case case_node p:
|
||||
t = new CaseScopeSyntax();
|
||||
break;
|
||||
case class_definition p:
|
||||
var td = p.Parent as type_declaration;
|
||||
var tname = td==null ? "NONAME" : td.type_name;
|
||||
if (p.keyword == class_keyword.Class)
|
||||
{
|
||||
AddSymbol(tname, SymKind.classname);
|
||||
t = new ClassScopeSyntax(tname);
|
||||
}
|
||||
else if (p.keyword == class_keyword.Record)
|
||||
{
|
||||
AddSymbol(tname, SymKind.recordname);
|
||||
t = new RecordScopeSyntax(tname);
|
||||
}
|
||||
else if (p.keyword == class_keyword.Interface)
|
||||
{
|
||||
AddSymbol(tname, SymKind.interfacename);
|
||||
t = new InterfaceScopeSyntax(tname);
|
||||
}
|
||||
break;
|
||||
case function_lambda_definition p:
|
||||
t = new LambdaScopeSyntax();
|
||||
break;
|
||||
}*/
|
||||
if (st is program_module p1 || st is unit_module u)
|
||||
{
|
||||
t = new GlobalScopeSyntax();
|
||||
Root = t;
|
||||
}
|
||||
else if (st is procedure_definition p2)
|
||||
{
|
||||
var name = p2.proc_header?.name?.meth_name;
|
||||
if (name == null)
|
||||
name = "create";
|
||||
var attr = p2.proc_header.class_keyword ? Attributes.class_attr : 0;
|
||||
if (name != null)
|
||||
if (p2.proc_header is function_header)
|
||||
AddSymbol(name, SymKind.funcname, null, attr);
|
||||
else AddSymbol(name, SymKind.procname, null, attr);
|
||||
t = new ProcScopeSyntax(name);
|
||||
}
|
||||
else if (st is statement_list p3)
|
||||
{
|
||||
t = new StatListScopeSyntax();
|
||||
}
|
||||
else if (st is for_node p4)
|
||||
{
|
||||
t = new ForScopeSyntax();
|
||||
}
|
||||
else if (st is foreach_stmt p5)
|
||||
{
|
||||
t = new ForeachScopeSyntax();
|
||||
}
|
||||
else if (st is case_node p6)
|
||||
{
|
||||
t = new CaseScopeSyntax();
|
||||
}
|
||||
else if (st is class_definition p7)
|
||||
{
|
||||
var td = p7.Parent as type_declaration;
|
||||
var tname = td == null ? "NONAME" : td.type_name;
|
||||
if (p7.keyword == class_keyword.Class)
|
||||
{
|
||||
AddSymbol(tname, SymKind.classname);
|
||||
t = new ClassScopeSyntax(tname);
|
||||
}
|
||||
else if (p7.keyword == class_keyword.Record)
|
||||
{
|
||||
AddSymbol(tname, SymKind.recordname);
|
||||
t = new RecordScopeSyntax(tname);
|
||||
}
|
||||
else if (p7.keyword == class_keyword.Interface)
|
||||
{
|
||||
AddSymbol(tname, SymKind.interfacename);
|
||||
t = new InterfaceScopeSyntax(tname);
|
||||
}
|
||||
}
|
||||
else if (st is function_lambda_definition p8)
|
||||
{
|
||||
t = new LambdaScopeSyntax();
|
||||
}
|
||||
|
||||
if (t != null)
|
||||
{
|
||||
t.Parent = Current;
|
||||
if (Current != null)
|
||||
Current.Children.Add(t);
|
||||
Current = t;
|
||||
if (st is procedure_definition p)
|
||||
{
|
||||
if (p.proc_header is function_header fh)
|
||||
{
|
||||
AddSymbol(new ident("Result"), SymKind.var, fh.return_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public virtual void PreExitScope(syntax_tree_node st)
|
||||
{
|
||||
|
||||
}
|
||||
public override void Exit(syntax_tree_node st)
|
||||
{
|
||||
/*switch (st)
|
||||
{
|
||||
case program_module p:
|
||||
case procedure_definition pd:
|
||||
//case formal_parameters fp:
|
||||
case statement_list stl:
|
||||
case for_node f:
|
||||
case foreach_stmt fe:
|
||||
case class_definition cd:
|
||||
case record_type rt:
|
||||
case function_lambda_definition fld:
|
||||
//case repeat_node rep:
|
||||
case case_node cas:
|
||||
PreExitScope(st);
|
||||
if (Current != null)
|
||||
Current = Current.Parent;
|
||||
break;
|
||||
}*/
|
||||
if (st is program_module p || st is procedure_definition pd || st is statement_list stl ||
|
||||
st is for_node f || st is foreach_stmt fe || st is class_definition cd || st is record_type rt ||
|
||||
st is function_lambda_definition fld || st is case_node cas)
|
||||
{
|
||||
PreExitScope(st);
|
||||
if (Current != null)
|
||||
Current = Current.Parent;
|
||||
}
|
||||
}
|
||||
public override void visit(var_def_statement vd)
|
||||
{
|
||||
var attr = vd.var_attr == definition_attribute.Static ? Attributes.class_attr : 0;
|
||||
if (vd == null || vd.vars == null || vd.vars.list == null)
|
||||
return;
|
||||
AddSymbols(vd.vars.list, SymKind.var, vd.vars_type, attr);
|
||||
base.visit(vd);
|
||||
}
|
||||
public override void visit(formal_parameters fp)
|
||||
{
|
||||
foreach (var pg in fp.params_list)
|
||||
{
|
||||
AddSymbols(pg.idents.idents, SymKind.param, pg.vars_type);
|
||||
}
|
||||
base.visit(fp);
|
||||
}
|
||||
|
||||
public override void visit(for_node f)
|
||||
{
|
||||
if (f.create_loop_variable || f.type_name != null)
|
||||
AddSymbol(f.loop_variable, SymKind.var, f.type_name);
|
||||
base.visit(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
/*
|
||||
GlobalScopeSyntax
|
||||
BlockScopeSyntax
|
||||
ProcScopeSyntax (name)
|
||||
ParamsScopeSyntax
|
||||
BlockScopeSyntax
|
||||
StatListScopeSyntax (0)
|
||||
StatListScopeSyntax (1)
|
||||
StatListScopeSyntax (0)
|
||||
StatListScopeSyntax (1)
|
||||
*/
|
||||
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTree
|
||||
{
|
||||
public partial class CollectLightSymInfoVisitor
|
||||
{
|
||||
public virtual void AddSymbol(ident name, SymKind kind, type_definition td = null, Attributes attr = 0)
|
||||
{
|
||||
Current.Symbols.Add(new SymInfoSyntax(name, kind, td, attr));
|
||||
}
|
||||
public void AddSymbols(List<ident> names, SymKind kind, type_definition td = null, Attributes attr = 0)
|
||||
{
|
||||
foreach (var n in names)
|
||||
{
|
||||
AddSymbol(n, kind, td, attr);
|
||||
}
|
||||
}
|
||||
public string Spaces(int n) => new string(' ', n);
|
||||
public void OutputString(string s) => System.IO.File.AppendAllText(fname, s);
|
||||
public void OutputlnString(string s = "") => System.IO.File.AppendAllText(fname, s + '\n');
|
||||
public void Output(string fname)
|
||||
{
|
||||
#if DEBUG
|
||||
this.fname = fname;
|
||||
if (System.IO.File.Exists(fname))
|
||||
System.IO.File.Delete(fname);
|
||||
OutputElement(0, Root);
|
||||
#endif
|
||||
}
|
||||
string fname;
|
||||
public void OutputElement(int d, ScopeSyntax s)
|
||||
{
|
||||
OutputString(Spaces(d));
|
||||
if (s == null)
|
||||
throw new Exception("ggggggggg");
|
||||
if (s is ParamsScopeSyntax)
|
||||
{
|
||||
OutputString(s.ToString()+": ");
|
||||
if (s.Symbols.Count > 0)
|
||||
OutputlnString(string.Join(", ", s.Symbols.Select(x => x.ToString())));
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputlnString(s.ToString());
|
||||
if (s.Symbols.Count > 0)
|
||||
OutputlnString(Spaces(d + 2) + string.Join(", ", s.Symbols.Select(x => x.ToString())));
|
||||
}
|
||||
foreach (var sc in s.Children)
|
||||
OutputElement(d + 2, sc);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -45,6 +45,11 @@
|
|||
<Compile Include="AllVarsInProcYieldsProba.cs" />
|
||||
<Compile Include="BaseVisitors\CollectNamespaces.cs" />
|
||||
<Compile Include="BaseVisitors\HasStatementVisitor.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\BindCollectLightSymInfo.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\CollectFullLightSymInfoVisitor.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\CollectLightSymInfoVisitor.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\LightScopeCreator.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\LightScopeHelperClasses.cs" />
|
||||
<Compile Include="SugarVisitors\CacheFunctionVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\UnpackLambdaParametersVisitor.cs" />
|
||||
<Compile Include="TeacherControl\TeacherControl.cs" />
|
||||
|
|
@ -52,9 +57,6 @@
|
|||
<Compile Include="BaseVisitors\SmallHelperVisitors.cs" />
|
||||
<Compile Include="ChangeWhileVisitor.cs" />
|
||||
<Compile Include="CheckingVisitors\UnnamedRecordsCheckErrorsVisitor.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\LightScopeHelperClasses.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\SymInfoCollect1.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\SymInfoCollect1Helper.cs" />
|
||||
<Compile Include="PatternsVisitors\ExtendedIsDesugaringVisitor.cs" />
|
||||
<Compile Include="PatternsVisitors\PatternsDesugaringVisitor.cs" />
|
||||
<Compile Include="PatternsVisitors\ReplaceNamesInIsVarVisitor.cs" />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
|
||||
// Первое предназначение - вынести последовательность из заголовка в foreach до foreach как отдельное присваивание
|
||||
// Второе предназначение - переименовать все переменные, совпадающие по имени с типом T обобщенного класса, в котором находится метод, содержащий лямбду
|
||||
public class VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer: CollectLightSymInfoVisitor
|
||||
public class VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer: CollectFullLightSymInfoVisitor
|
||||
{
|
||||
/// <summary>
|
||||
/// Надо приводить к нижнему регистру
|
||||
|
|
@ -27,11 +27,13 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
// Описание переменной в словарь добавляется только если она описана в методе, но вне лямбды, поскольку в лямбде конфликтов имен нет
|
||||
// При выходе из пространства имен мы проверяем, есть ли в словаре такое значение, и если да, очищаем его, присваивая null
|
||||
// Переименовывать будем все имена name если ключ name есть в словаре и d[name] != null
|
||||
public static new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer New
|
||||
|
||||
public VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer(compilation_unit pm) : base(pm)
|
||||
{
|
||||
get => new VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer();
|
||||
|
||||
}
|
||||
public override void AddSymbol(ident name, SymKind kind, type_definition td = null, Attributes attr = 0)
|
||||
|
||||
public override void AddSymbol(ident name, SymKind kind, type_definition td = null, SymbolAttributes attr = 0)
|
||||
{
|
||||
if (name == null || name.name == null)
|
||||
{
|
||||
|
|
@ -163,7 +165,7 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
// это точно надо захватывать
|
||||
}
|
||||
|
||||
public override void visit(var_def_statement vds)
|
||||
public override void visit(var_def_statement vds)
|
||||
{
|
||||
// имена обойти отдельно, инициализатор - отдельно
|
||||
foreach (var id in vds.vars.idents)
|
||||
|
|
|
|||
33
_RebuildDebugAndBuildUnits.bat
Normal file
33
_RebuildDebugAndBuildUnits.bat
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
call Studio.bat /t:rebuild "/property:Configuration=Debug" "/p:Platform=Any CPU" PascalABCNET.sln
|
||||
|
||||
@IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
cd ReleaseGenerators
|
||||
..\bin\pabcnetc RebuildStandartModules.pas /rebuild
|
||||
@IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
cd PABCRtl
|
||||
..\..\bin\pabcnetc PABCRtl.pas /rebuild
|
||||
@IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
..\sn.exe -Vr PABCRtl.dll
|
||||
..\sn.exe -R PABCRtl.dll KeyPair.snk
|
||||
..\sn.exe -Vu PABCRtl.dll
|
||||
copy PABCRtl.dll ..\..\bin\Lib
|
||||
|
||||
cd ..
|
||||
ExecHide.exe gacutil.exe /u PABCRtl
|
||||
ExecHide.exe gacutil.exe /i ..\bin\Lib\PABCRtl.dll
|
||||
|
||||
..\bin\pabcnetc RebuildStandartModules.pas /rebuild
|
||||
@IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
|
||||
cd ..\bin
|
||||
REM MPGORunner.exe
|
||||
cd ..
|
||||
GOTO EXIT
|
||||
|
||||
:ERROR
|
||||
PAUSE
|
||||
|
||||
:EXIT
|
||||
Loading…
Reference in a new issue