pascalabcnet/SyntaxVisitors/UniversalVisitors/ABCStatisticsVisitors.cs
Mikhalkovich Stanislav b4c5ad785e -2**4 теперь возвращает -16
2**3**2 теперь работает
2020-09-14 21:14:08 +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.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
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 && mc.dereferencing_value is ident id && (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.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.PrintCount, 4) * 5;
}
if (stat.DynamicArrays > 0)
{
PositivePercent += Math.Min(stat.PrintCount, 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)
{
}*/
}
}