Skip to content

Commit

Permalink
Improve Rule classes to be able add a rich context.history in Rules (#…
Browse files Browse the repository at this point in the history
…457)

* feat: update Rule stuff to add a rich context.history

* fix: update all rules to adapt with new classes
  • Loading branch information
NiumXp authored Nov 22, 2023
1 parent 754f220 commit 8b11426
Show file tree
Hide file tree
Showing 62 changed files with 427 additions and 481 deletions.
59 changes: 29 additions & 30 deletions norminette/registry.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import collections
from functools import cmp_to_key
from operator import attrgetter

import norminette.rules as rules
from norminette.rules import Rules, Primary
from norminette.exceptions import CParsingError

rules = Rules()


def sort_errs(a, b):
if a.col == b.col and a.line == b.line:
Expand All @@ -14,37 +18,25 @@ class Registry:
global has_err

def __init__(self):
self.rules = rules.rules
self.primary_rules = rules.primary_rules
self.dependencies = {}
for k, r in self.rules.items():
r.register(self)
for k, v in self.dependencies.items():
self.dependencies[k] = sorted(self.dependencies[k], reverse=True)
self.dependencies = collections.defaultdict(list)
for rule in rules.checks:
rule.register(self)
for name, dependencies in self.dependencies.items():
self.dependencies[name] = sorted(dependencies, reverse=True, key=attrgetter("__name__"))

def run_rules(self, context, rule):
if rule.name.startswith("Is"):
ret, read = rule.run(context)
else:
# print (rule.name)
ret = False
read = 0
rule.run(context)
# print(context.history, context.tokens[:5], rule)
# if rule.name.startswith("Is"):
# print (rule.name, ret)
if ret is True:
rule = rule(context)
result = rule.run(context)
ret, read = result if isinstance(rule, Primary) else (False, 0)
if ret:
context.scope.instructions += 1
if rule.name.startswith("Is"):
# print ("Line", context.tokens[0].pos[0], rule.name)
if isinstance(rule, Primary):
context.tkn_scope = read
context.history.append(rule.name)
for r in self.dependencies.get(rule.name, []):
self.run_rules(context, self.rules[r])
if "all" in self.dependencies:
for r in self.dependencies["all"]:
self.run_rules(context, self.rules[r])
# context.history.pop(-1)
context.history.append(rule)
for rule in self.dependencies[rule.name]:
self.run_rules(context, rule)
for rule in self.dependencies["_rule"]:
self.run_rules(context, rule)
context.tkn_scope = 0
return ret, read

Expand All @@ -57,10 +49,14 @@ def run(self, context, source):
dependencies
"""
unrecognized_tkns = []
context.state = "starting"
for rule in self.dependencies["_start"]:
self.run_rules(context, rule)
context.state = "running"
while context.tokens != []:
context.tkn_scope = len(context.tokens)
for rule in self.primary_rules:
if type(context.scope) not in rule.scope and rule.scope != []:
for rule in rules.primaries:
if rule.scope and context.scope not in rule.scope:
continue
ret, jump = self.run_rules(context, rule)
if ret is True:
Expand All @@ -82,6 +78,9 @@ def run(self, context, source):
unrecognized_tkns.append(context.tokens[0])
context.pop_tokens(1) # ##################################
# #############################################################
context.state = "ending"
for rule in self.dependencies["_end"]:
self.run_rules(context, rule)
if unrecognized_tkns != []:
print(context.debug)
if context.debug > 0:
Expand Down
48 changes: 21 additions & 27 deletions norminette/rules/__init__.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,30 @@
__all__ = (
"rules",
"primary_rules",
"Rule",
"PrimaryRule",
)

import operator
import itertools
import importlib
import os
from operator import attrgetter

from norminette.rules.rule import PrimaryRule
from norminette.rules.rule import Rule


def partition(predicate, iterable):
it1, it2 = itertools.tee(iterable)
return itertools.filterfalse(predicate, it1), filter(predicate, it2)

from norminette.rules.rule import Rule, Primary, Check

path = os.path.dirname(os.path.realpath(__file__))

for f in os.listdir(path):
name, _ = os.path.splitext(f)
importlib.import_module("norminette.rules." + name)
class Rules:
__slots__ = (
"all",
"primaries",
"checks",
)

_all_rules = Rule.__subclasses__()[1:] + PrimaryRule.__subclasses__()
_all_rules = map(type.__call__, _all_rules) # In 3.11^ we can just use `operator.call``
__instance = None

_is_primary_rule = operator.attrgetter("primary")
_rules, _primary_rules = partition(_is_primary_rule, _all_rules)
def __new__(cls):
if not cls.__instance:
cls.__instance = super().__new__(cls)
return cls.__instance

rules = {rule.__class__.__name__: rule for rule in _rules}
def __init__(self) -> None:
path = os.path.dirname(os.path.realpath(__file__))
for f in os.listdir(path):
name, _ = os.path.splitext(f)
importlib.import_module("norminette.rules." + name)

primary_rules = sorted(_primary_rules, reverse=True, key=operator.attrgetter("priority"))
self.all = Rule.__subclasses__()
self.checks = Check.__subclasses__()
self.primaries = sorted(Primary.__subclasses__(), reverse=True, key=attrgetter("priority"))
10 changes: 5 additions & 5 deletions norminette/rules/check_assignation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check

assigns = [
"RIGHT_ASSIGN",
Expand All @@ -17,10 +17,10 @@
special_assigns = ["INC", "DEC"]


class CheckAssignation(Rule):
def __init__(self):
super().__init__()
self.depends_on = ["IsAssignation"]
class CheckAssignation(Rule, Check):
depends_on = (
"IsAssignation",
)

def check_brace_assign(self, context, i):
i += 1
Expand Down
18 changes: 8 additions & 10 deletions norminette/rules/check_assignation_indent.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check
from norminette.exceptions import CParsingError


Expand Down Expand Up @@ -42,15 +42,13 @@
nest_kw = ["RPARENTHESIS", "LPARENTHESIS", "NEWLINE"]


class CheckAssignationIndent(Rule):
def __init__(self):
super().__init__()
self.depends_on = [
"IsAssignation",
"IsFuncPrototype",
"IsFunctionCall",
"IsVarDeclaration",
]
class CheckAssignationIndent(Rule, Check):
depends_on = (
"IsAssignation",
"IsFuncPrototype",
"IsFunctionCall",
"IsVarDeclaration",
)

def run(self, context):
"""
Expand Down
10 changes: 5 additions & 5 deletions norminette/rules/check_block_start.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check
from norminette.scope import GlobalScope, ControlStructure


class CheckBlockStart(Rule):
def __init__(self):
super().__init__()
self.depends_on = ["IsBlockStart"]
class CheckBlockStart(Rule, Check):
depends_on = (
"IsBlockStart",
)

def run(self, context):
"""
Expand Down
11 changes: 6 additions & 5 deletions norminette/rules/check_brace.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check


class CheckBrace(Rule):
def __init__(self):
super().__init__()
self.depends_on = ["IsBlockStart", "IsBlockEnd"]
class CheckBrace(Rule, Check):
depends_on = (
"IsBlockStart",
"IsBlockEnd",
)

def run(self, context):
"""
Expand Down
4 changes: 2 additions & 2 deletions norminette/rules/check_comment.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check


class CheckComment(Rule):
class CheckComment(Rule, Check):
def run(self, context):
"""
Comments are forbidden inside functions and in the middle of instructions.
Expand Down
10 changes: 5 additions & 5 deletions norminette/rules/check_comment_line_len.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check


class CheckCommentLineLen(Rule):
def __init__(self):
super().__init__()
self.depends_on = ["IsComment"]
class CheckCommentLineLen(Rule, Check):
depends_on = (
"IsComment",
)

def run(self, context):
"""
Expand Down
10 changes: 5 additions & 5 deletions norminette/rules/check_control_statement.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check


forbidden_cs = ["FOR", "SWITCH", "CASE", "GOTO"]
Expand All @@ -17,10 +17,10 @@
]


class CheckControlStatement(Rule):
def __init__(self):
super().__init__()
self.depends_on = ["IsControlStatement"]
class CheckControlStatement(Rule, Check):
depends_on = (
"IsControlStatement",
)

def check_nest(self, context, i):
depth = 1
Expand Down
10 changes: 5 additions & 5 deletions norminette/rules/check_declaration.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check


class CheckDeclaration(Rule):
def __init__(self):
super().__init__()
self.depends_on = ["IsDeclaration"]
class CheckDeclaration(Rule, Check):
depends_on = (
"IsDeclaration",
)

def run(self, context):
"""
Expand Down
8 changes: 2 additions & 6 deletions norminette/rules/check_empty_line.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check


class CheckEmptyLine(Rule):
def __init__(self):
super().__init__()
self.depends_on = []

class CheckEmptyLine(Rule, Check):
def run(self, context):
"""
Empty line must not contains tabs or spaces
Expand Down
10 changes: 5 additions & 5 deletions norminette/rules/check_enum_var_decl.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check


class CheckEnumVarDecl(Rule):
def __init__(self):
super().__init__()
self.depends_on = ["IsEnumVarDecl"]
class CheckEnumVarDecl(Rule, Check):
depends_on = (
"IsEnumVarDecl",
)

def run(self, context):
"""
Expand Down
20 changes: 9 additions & 11 deletions norminette/rules/check_expression_statement.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check

kw = [
# C reserved keywords #
Expand Down Expand Up @@ -36,16 +36,14 @@
]


class CheckExpressionStatement(Rule):
def __init__(self):
super().__init__()
self.depends_on = [
"IsExpressionStatement",
"IsControlStatement",
"IsFunctionCall",
"IsAssignation",
"IsCast",
]
class CheckExpressionStatement(Rule, Check):
depends_on = (
"IsExpressionStatement",
"IsControlStatement",
"IsFunctionCall",
"IsAssignation",
"IsCast",
)

def run(self, context):
"""
Expand Down
11 changes: 6 additions & 5 deletions norminette/rules/check_func_arguments_name.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from norminette.rules import Rule
from norminette.rules import Rule, Check

type_specifiers = ["CHAR", "DOUBLE", "ENUM", "FLOAT", "INT", "UNION", "VOID", "SHORT"]

Expand All @@ -13,10 +13,11 @@
arg_separator = ["COMMA", "CLOSING_PARENTHESIS"]


class CheckFuncArgumentsName(Rule):
def __init__(self):
super().__init__()
self.depends_on = ["IsFuncDeclaration", "IsFuncPrototype"]
class CheckFuncArgumentsName(Rule, Check):
depends_on = (
"IsFuncDeclaration",
"IsFuncPrototype",
)

def check_arg_format(self, context, pos):
"""
Expand Down
Loading

0 comments on commit 8b11426

Please sign in to comment.