Source code for m2isar.metamodel.code_info

# SPDX-License-Identifier: Apache-2.0
#
# This file is part of the M2-ISA-R project: https://github.com/tum-ei-eda/M2-ISA-R
#
# Copyright (C) 2024
# Chair of Electrical Design Automation
# Technical University of Munich

from dataclasses import dataclass, field
from enum import Enum, auto


[docs] class LineInfoPlacement(Enum):
[docs] AFTER = auto()
[docs] BEFORE = auto()
@dataclass
[docs] class CodeInfoBase: """Base class for tracking code info."""
[docs] file_path: str
[docs] start_chr: int
[docs] stop_chr: int
[docs] start_line_no: int
[docs] stop_line_no: int
[docs] id: int = field(default=None, kw_only=True)
"""Automatically calculated unique ID for tracking purposes in consumer programs."""
[docs] __id_counter = 0
[docs] database = {}
"""A global database of all created CodeInfo objects."""
[docs] def __post_init__(self): if self.id is None: self.id = CodeInfoBase.__id_counter CodeInfoBase.__id_counter += 1 CodeInfoBase.database[self.id] = self
[docs] def line_eq(self, other): if isinstance(other, self.__class__) or isinstance(self, other.__class__): return self.file_path == other.file_path and \ self.start_line_no == other.start_line_no #and \ #self.stop_line_no == other.stop_line_no raise NotImplementedError
[docs] def __hash__(self) -> int: return hash(self.id)
[docs] def line_hash(self): return hash((self.file_path, self.start_line_no, self.stop_line_no))
@dataclass(eq=False)
[docs] class LineInfo(CodeInfoBase):
[docs] placement: LineInfoPlacement = field(default=LineInfoPlacement.AFTER, kw_only=True)
@dataclass(eq=False)
[docs] class FunctionInfo(CodeInfoBase):
[docs] fn_name: str
@dataclass(eq=False)
[docs] class BranchInfo(LineInfo):
[docs] branch_id: int = field(default=None, kw_only=True)
@dataclass(eq=False)
[docs] class BranchEntryInfo(BranchInfo):
[docs] placement: LineInfoPlacement = field(default=LineInfoPlacement.BEFORE, init=False)
[docs] def __post_init__(self): super().__post_init__() if self.branch_id is None: self.branch_id = self.id
[docs] class InfoFactory: def __init__(self, cls_to_use):
[docs] self.cls_to_use = cls_to_use
[docs] self.tracker: "dict[tuple[str, int, int], CodeInfoBase]" = {}
[docs] def make(self, file_path, start_chr, stop_chr, start_line_no, stop_line_no, *args, **kwargs): ret = self.tracker.get((file_path, start_chr, stop_chr)) if ret is None: ret = self.cls_to_use(file_path, start_chr, stop_chr, start_line_no, stop_line_no, *args, **kwargs) self.tracker[((file_path, start_chr, stop_chr))] = ret return ret
[docs] LineInfoFactory = InfoFactory(LineInfo)
[docs] FunctionInfoFactory = InfoFactory(FunctionInfo)
[docs] BranchEntryInfoFactory = InfoFactory(BranchEntryInfo)