pascalabcnet/SyntaxVisitors/UniversalVisitors/ABCStatisticsVisitors.cs
AlexanderZemlyak 342375501b
New languages engine (#3120)
* Implement first version of languages interfaces and classes

ParsersController заменен на LanguageProvider.

* Update ParserTools.csproj

* Update RemoteCompiler.cs

* Update TestRunner

* Rename LanguageIntegrator project to Languages

* Update TestRunner

* Rename Parsers folder

* Rename PascalABCParser.dll to PascalABCLanguage.dll

* Reorganise LanguageIntegrator and rename DocTagsParser

* Update Release Generators

* Update language loading messages

* Update linux version

* Move BaseParser fields to ILanguage interface

* Revert "Update Release Generators"

This reverts commit 26a991c71b81e643d9fbd9a815ddca222768dda9.

* Revert "Rename PascalABCParser.dll to PascalABCLanguage.dll"

* Clean the mess in parser folders

* Organize namespaces properly

* Revert "Rename LanguageIntegrator project to Languages"

* Add new enclosing folders for standard languages

* Organize namespaces of LanguageIntegrator properly

* Rename StandardLanguages to Languages

* Comment the rest of Visual basic source code

* Update OutputPath in pascal parser project

* Move BaseParser methods to IParser

* Restore Pascal parser project initial structure

* Add PascalLanguage project

* Move SyntaxTreeConverters project to Languages\Pascal folder

* Rename SemanticRules in parser project

* Rename Errors1 to Errors in parser project

* Delete LambdaConverter dll from installer

* Update language integrator to load *Language.dll files

* Move lambda converter project to pascal lanuage dir

* Revert "Delete LambdaConverter dll from installer"

This reverts commit dd56f559ebe4f8c4c5c33752d44e6953001b96a5.

* Switch off VBNETParser building

* Delete syntax tree converters controller

* Delete lambda converter dll from repository

* Reorganize syntax tree to semantic tree conversion stage

* Add BaseLanguage class to make language initialization more neat

* Delete syntax tree post processors entity from ILanguage and refactor ABCStatistics calls

* Add new IDocParser interface for documentation comments parser

* Clean up folders

* Add helper data structures to reduce parameters amount in CompileInterface and CompileImplementation

* Add documentation to language classes

* Move Union struct in global namespace and project (ParserTools)

* Add more comments and a safe select language method

* Rename SemanticRules class

* Fix directives format null bug

* Add System.Linq ref to LanguageIntegrator

* Delete SyntaxToSemanticTreeConverter interface

* Add BaseSyntaxTreeConverter

* Call safe select language method in intellisence

* Delete source files providers from parsers

* Rename GetSyntaxTree method

* Change Prebuild tree to be virtual - not abstract

* Refresh documentation a bit

* Add temporary language check for ABCHealth button

* Add parser reference to parser tools

* Move current compilation unit assigning higher to avoid bug with unit check

* Delete null DirectiveInfo's and refactor directives' code

* Add a few more comments
2024-05-25 12:26:32 +03:00

319 lines
11 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Linq;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class ABCStatisticsVisitor : WalkingVisitorNew
{
public int InBlockVarDefs { get; set; }
public int OutBlockVarDefs { get; set; }
public int ForsWithoutVar { get; set; }
public int ForsWithVar { get; set; }
public bool ProgramKeyword { get; set; }
public int OldStrings { get; set; }
public int StaticArrays { get; set; }
public int DynamicArrays { get; set; }
public int ReadProc { get; set; }
public int WriteProcWithSpace { get; set; }
public int TuplesCount { get; set; }
public int InitVarInDef { get; set; }
public int UnpackingAssign { get; set; }
public int LoopsCount { get; set; }
public int ForeachCount { get; set; }
public int LambdasCount { get; set; }
public int ExtAssignCount { get; set; }
public int BigIntegerTypeCount { get; set; }
public int ReadFuncCount { get; set; }
public int PrintCount { get; set; }
public ABCStatisticsVisitor()
{
}
public override void visit(ident id)
{
var name = id.name.ToLower();
if (name.StartsWith("readinteger") || name.StartsWith("readreal") || name.StartsWith("readstring") ||
name.StartsWith("readlninteger") || name.StartsWith("readlnreal") || name.StartsWith("readlnstring"))
ReadFuncCount++;
if (name.StartsWith("print"))
PrintCount++;
}
public override void visit(named_type_reference ntr)
{
var name = ntr.names[0].name.ToLower();
if (name == "biginteger")
BigIntegerTypeCount++;
base.visit(ntr);
}
public override void visit(assign an)
{
if (an.operator_type == Operators.AssignmentAddition || an.operator_type == Operators.AssignmentMultiplication || an.operator_type == Operators.AssignmentDivision)
ExtAssignCount++;
base.visit(an);
}
public override void visit(function_lambda_definition fld)
{
LambdasCount++;
base.visit(fld);
}
public override void visit(loop_stmt ln)
{
LoopsCount++;
base.visit(ln);
}
public override void visit(foreach_stmt fn)
{
ForeachCount++;
base.visit(fn);
}
public override void visit(tuple_node tn)
{
TuplesCount++;
base.visit(tn);
}
public override void visit(assign_var_tuple at)
{
UnpackingAssign++;
base.visit(at);
}
public override void visit(assign_tuple at)
{
UnpackingAssign++;
base.visit(at);
}
public override void visit(for_node fn)
{
if (fn.create_loop_variable == false)
ForsWithoutVar++;
if (fn.create_loop_variable == true)
ForsWithVar++;
base.visit(fn);
}
public override void visit(var_def_statement vds)
{
if (vds.Parent is var_statement)
{
InBlockVarDefs += vds.vars.Count;
}
else if (!(vds.Parent is class_members))
{
OutBlockVarDefs += vds.vars.Count;
}
if (vds.vars_type != null && vds.vars_type is string_num_definition)
{
OldStrings += 1;
}
if (vds.vars_type != null && vds.vars_type is array_type at && at.indexers != null && at.indexers.Count > 0 && at.indexers.indexers[0] != null)
{
StaticArrays += 1;
}
if (vds.vars_type != null && vds.vars_type is array_type at1 && at1.indexers == null)
{
DynamicArrays += 1;
}
if (vds.inital_value != null)
InitVarInDef++;
/*if (vds.inital_value != null)
{
if (vds.inital_value is ident id &&
(id.name.ToLower().StartsWith("readinteger") || id.name.ToLower().StartsWith("readreal") || id.name.ToLower().StartsWith("readstring") ||
id.name.ToLower().StartsWith("readlninteger") || id.name.ToLower().StartsWith("readlnreal") || id.name.ToLower().StartsWith("readlnstring")))
ReadFuncCount++;
}*/
base.visit(vds);
}
public override void visit(program_name pn)
{
if (pn != null)
ProgramKeyword = true;
}
public override void visit(method_call mc)
{
/*if (mc.dereferencing_value is ident id && (id.name.ToLower() == "read" || id.name.ToLower() == "readln"))
{
syntax_tree_node n = mc;
do
{
n = n.Parent;
} while (n != null && !(n is class_members));
if (n != null)
;
//ReadProc = false;
else
ReadProc += 1;
}*/
/*if (mc.dereferencing_value is ident id2)
{
var name = id2.name.ToLower();
var h = new HashSet<string> { "readinteger", "readlninteger", "readreal", "readlnreal", "readstring", "readlnstring", "readchar", "readlnchar" };
if (h.Contains(name))
ReadFuncCount++;
}*/
/*if (mc.dereferencing_value is ident id1 && (id1.name.ToLower() == "write" || id1.name.ToLower() == "writeln") &&
mc.parameters != null && mc.parameters.expressions.Any(ex => ex is char_const cc && cc.cconst == ' '))
{
WriteProcWithSpace += 1;
}*/
base.visit(mc);
}
public override void visit(procedure_call pc)
{
if (pc.func_name is method_call mc)
if (mc.dereferencing_value is ident id)
if (id.name != null && (id.name.ToLower() == "read" || id.name.ToLower() == "readln"))
{
syntax_tree_node n = pc;
do
{
n = n.Parent;
} while (n != null && !(n is class_members));
if (n != null)
//ReadProc = false
;
else
ReadProc += 1;
}
if (pc.func_name is method_call mc1 && mc1.dereferencing_value is ident id1 &&
(id1.name != null && (id1.name.ToLower() == "write" || id1.name.ToLower() == "writeln"))
&& mc1.parameters != null && mc1.parameters.expressions.Any(ex => ex is char_const cc && cc.cconst == ' '))
{
WriteProcWithSpace += 1;
}
base.visit(pc);
}
public int CalcHealth(out int NegativePercent, out int PositivePercent)
{
var stat = this;
var Percent = 100;
NegativePercent = 0;
PositivePercent = 0;
var diffBlockVarDefs = stat.OutBlockVarDefs; // - stat.InBlockVarDefs;
if (diffBlockVarDefs > 0)
{
NegativePercent += 10; // за первую
NegativePercent += (diffBlockVarDefs - 1) * 2; // за оставшиеся
if (NegativePercent > 25)
NegativePercent = 25;
}
// For i
if (stat.ForsWithoutVar > 0)
{
NegativePercent += Math.Min(15 + (stat.ForsWithoutVar - 1) * 3, 25);
}
if (stat.ReadProc > 0)
{
NegativePercent += Math.Min(15 + (stat.ReadProc - 1) * 2, 20);
}
if (stat.ProgramKeyword)
{
NegativePercent += 10;
}
if (stat.StaticArrays > 0)
{
NegativePercent += Math.Min(10 + (stat.StaticArrays - 1) * 2, 15);
}
if (stat.WriteProcWithSpace > 0)
{
NegativePercent += Math.Min(2 + (stat.WriteProcWithSpace - 1) * 1, 5);
}
if (stat.OldStrings > 0)
{
NegativePercent += stat.OldStrings;
}
if (NegativePercent < 0)
{
NegativePercent = 0;
}
Percent -= NegativePercent;
// Проценты за положительное
if (stat.InBlockVarDefs > 0)
{
PositivePercent += 10; // за первую
PositivePercent += (stat.InBlockVarDefs - 1) * 2; // за оставшиеся
// этот алгоритм уравновешивает описания внутри и вне. За одинаковое количество дается 0 баллов
}
if (stat.ForsWithVar != 0)
{
PositivePercent += Math.Min(stat.ForsWithVar, 4) * 3;
}
if (stat.InitVarInDef > 0)
{
PositivePercent += Math.Min(stat.InitVarInDef, 4) * 4;
}
if (stat.ReadFuncCount > 0)
{
PositivePercent += Math.Min(stat.ReadFuncCount, 4) * 3;
}
if (stat.ExtAssignCount > 0)
{
PositivePercent += Math.Min(stat.ExtAssignCount, 4) * 3;
}
if (stat.PrintCount > 0)
{
PositivePercent += Math.Min(stat.PrintCount, 4) * 4;
}
if (stat.TuplesCount > 0)
{
PositivePercent += Math.Min(stat.TuplesCount, 4) * 5;
}
if (stat.DynamicArrays > 0)
{
PositivePercent += Math.Min(stat.DynamicArrays, 4) * 5;
}
if (stat.UnpackingAssign > 0)
{
PositivePercent += Math.Min(stat.UnpackingAssign, 4) * 5;
}
if (stat.LoopsCount > 0)
{
PositivePercent += Math.Min(stat.LoopsCount, 4) * 4;
}
if (stat.ForeachCount > 0)
{
PositivePercent += Math.Min(stat.ForeachCount, 4) * 4;
}
if (stat.LambdasCount > 0)
{
PositivePercent += Math.Min(stat.LambdasCount, 4) * 8;
}
Percent += PositivePercent;
if (Percent > 200)
Percent = 200;
if (Percent < 0)
Percent = 0;
return Percent;
}
/*public override void visit(dot_node dn)
{
ProcessNode(dn.left);
if (dn.right.GetType() != typeof(ident))
ProcessNode(dn.right);
}*/
/*public override void visit(function_lambda_definition fd)
{
}*/
}
}