# 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) 2022
# Chair of Electrical Design Automation
# Technical University of Munich
#
# Copyright (C) 2026
# Modifed by JK TUW ECS
"""Generate a ttk.Treeview representation of a M2-ISA-R model structure."""
import tkinter as tk
from ...metamodel import behav
from .utils import TreeGenContext
from ...metamodel.utils.ExprVisitor import ExprVisitor
from .utils import TreeGenContext
from functools import singledispatchmethod
# pylint: disable=unused-argument
[docs]
class TreeGenVisitor(ExprVisitor):
"""Visitor to generate a ttk.Treeview representation of a M2-ISA-R model structure."""
@singledispatchmethod
[docs]
def generate(self, expr : behav.BaseNode, context=None):
raise NotImplementedError(f"No visit method implemented for type {type(expr).__name__} in {type(expr).__name__}")
@generate.register
[docs]
def visit_operation(self, expr: behav.Operation, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Operation"))
for stmt in expr.statements:
self.generate(stmt, context)
context.pop()
@generate.register
[docs]
def visit_block(self, expr: behav.Block, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Block"))
for stmt in expr.statements:
self.generate(stmt, context)
context.pop()
@generate.register
[docs]
def visit_binary_operation(self, expr: behav.BinaryOperation, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Binary Operation"))
context.push(context.tree.insert(context.parent, tk.END, text="Left"))
self.generate(expr.left, context)
context.pop()
context.push(context.tree.insert(context.parent, tk.END, text="Right"))
self.generate(expr.right, context)
context.pop()
context.tree.insert(context.parent, tk.END, text="Op", values=(expr.op.value,))
context.pop()
@generate.register
[docs]
def visit_slice_operation(self, expr: behav.SliceOperation, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Slice Operation"))
context.push(context.tree.insert(context.parent, tk.END, text="Expr"))
self.generate(expr.expr, context)
context.pop()
context.push(context.tree.insert(context.parent, tk.END, text="Left"))
self.generate(expr.left, context)
context.pop()
context.push(context.tree.insert(context.parent, tk.END, text="Right"))
self.generate(expr.right, context)
context.pop()
context.pop()
@generate.register
[docs]
def concat_operation(self, expr: behav.ConcatOperation, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Concat Operation"))
context.push(context.tree.insert(context.parent, tk.END, text="Left"))
self.generate(expr.left, context)
context.pop()
context.push(context.tree.insert(context.parent, tk.END, text="Right"))
self.generate(expr.right, context)
context.pop()
context.pop()
@generate.register
[docs]
def number_literal(self, expr: behav.NumberLiteral, context: "TreeGenContext"):
context.tree.insert(context.parent, tk.END, text="Number Literal", values=(expr.value,))
@generate.register
[docs]
def int_literal(self, expr: behav.IntLiteral, context: "TreeGenContext"):
context.tree.insert(context.parent, tk.END, text="Int Literal", values=(expr.value,))
@generate.register
[docs]
def scalar_definition(self, expr: behav.ScalarDefinition, context: "TreeGenContext"):
context.tree.insert(context.parent, tk.END, text="Scalar Definition", values=(expr.scalar.name,))
@generate.register
[docs]
def break_(self, expr: behav.Break, context: "TreeGenContext"):
context.tree.insert(context.parent, tk.END, text="Break")
@generate.register
[docs]
def assignment(self, expr: behav.Assignment, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Assignment"))
context.push(context.tree.insert(context.parent, tk.END, text="Target"))
self.generate(expr.target, context)
context.pop()
context.push(context.tree.insert(context.parent, tk.END, text="Expr"))
self.generate(expr.expr, context)
context.pop()
context.pop()
@generate.register
[docs]
def conditional(self, expr: behav.Conditional, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Conditional"))
context.push(context.tree.insert(context.parent, tk.END, text="Conditions"))
for cond in expr.conds:
self.generate(cond, context)
context.pop()
context.push(context.tree.insert(context.parent, tk.END, text="Statements"))
for stmt in expr.stmts:
self.generate(stmt, context)
context.pop()
context.pop()
@generate.register
[docs]
def loop(self, expr: behav.Loop, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Loop"))
context.tree.insert(context.parent, tk.END, text="Post Test", values=(expr.post_test,))
context.push(context.tree.insert(context.parent, tk.END, text="Condition"))
self.generate(expr.cond, context)
context.pop()
context.push(context.tree.insert(context.parent, tk.END, text="Statements"))
for stmt in expr.stmts:
self.generate(stmt, context)
context.pop()
context.pop()
@generate.register
[docs]
def ternary(self, expr: behav.Ternary, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Ternary"))
context.push(context.tree.insert(context.parent, tk.END, text="Cond"))
self.generate(expr.cond, context)
context.pop()
context.push(context.tree.insert(context.parent, tk.END, text="Then Expression"))
self.generate(expr.then_expr, context)
context.pop()
context.push(context.tree.insert(context.parent, tk.END, text="Else Expression"))
self.generate(expr.else_expr, context)
context.pop()
context.pop()
@generate.register
[docs]
def return_(self, expr: behav.Return, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Return"))
if expr.expr is not None:
context.push(context.tree.insert(context.parent, tk.END, text="Expression"))
self.generate(expr.expr, context)
context.pop()
context.pop()
@generate.register
[docs]
def unary_operation(self, expr: behav.UnaryOperation, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Unary Operation"))
context.push(context.tree.insert(context.parent, tk.END, text="Right"))
self.generate(expr.right, context)
context.pop()
context.tree.insert(context.parent, tk.END, text="Op", values=(expr.op.value,))
context.pop()
@generate.register
[docs]
def named_reference(self, expr: behav.NamedReference, context: "TreeGenContext"):
context.tree.insert(context.parent, tk.END, text="Named Reference", values=(f"{expr.reference}",))
@generate.register
[docs]
def indexed_reference(self, expr: behav.IndexedReference, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Indexed Reference"))
context.tree.insert(context.parent, tk.END, text="Reference", values=(f"{expr.reference}",))
# If LHS is a complex expression => RHS also an expression
# TODO: Little Endian only so far supported
if (expr.reference.name == "MEM"):
if expr.right != None:
context.push(context.tree.insert(context.parent, tk.END, text="IndexRange"))
context.push(context.tree.insert(context.parent, tk.END, text="Left"))
self.generate(expr.index, context)
context.pop()
assert(type(expr.right) == behav.NamedReference)
context.push(context.tree.insert(context.parent, tk.END, text="Right"))
self.generate(expr.right, context)
context.pop()
context.pop()
else:
context.push(context.tree.insert(context.parent, tk.END, text="Index"))
self.generate(expr.index, context)
context.pop()
else:
context.push(context.tree.insert(context.parent, tk.END, text="Index"))
self.generate(expr.index, context)
context.pop()
context.pop()
@generate.register
[docs]
def type_conv(self, expr: behav.TypeConv, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Type Conv"))
context.tree.insert(context.parent, tk.END, text="Type", values=(expr.data_type,))
context.tree.insert(context.parent, tk.END, text="Size", values=(expr.size,))
context.push(context.tree.insert(context.parent, tk.END, text="Expr"))
self.generate(expr.expr, context)
context.pop()
context.pop()
@generate.register
[docs]
def callable_(self, expr: behav.Callable, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Callable", values=(expr.ref_or_name.name,)))
for arg, arg_descr in zip(expr.args, expr.ref_or_name.args):
context.push(context.tree.insert(context.parent, tk.END, text="Arg", values=(arg_descr,)))
self.generate(arg, context)
context.pop()
context.pop()
@generate.register
[docs]
def procedure_call(self, expr: behav.ProcedureCall, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="ProcedureCall", values=(expr.ref_or_name.name,)))
for arg, arg_descr in zip(expr.args, expr.ref_or_name.args):
context.push(context.tree.insert(context.parent, tk.END, text="Arg", values=(arg_descr,)))
self.generate(arg, context)
context.pop()
context.pop()
@generate.register
[docs]
def group(self, expr: behav.Group, context: "TreeGenContext"):
context.push(context.tree.insert(context.parent, tk.END, text="Group"))
context.push(context.tree.insert(context.parent, tk.END, text="Expr"))
self.generate(expr.expr, context)
context.pop()
context.pop()