1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3#
4# Copyright (C) 2024 Antmicro
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18# SPDX-License-Identifier: Apache-2.0
19
20from typing import Iterable
21from peakrdl_renode.csharp.ast import CodeCC, CodeGenerator, Expr, Node, Type
22from itertools import chain
23from .ast import *
24
25class GT(BinaryOp):
26    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
27        super().__init__('>', lhs, rhs, Type.bool, **kwargs)
28
29class LT(BinaryOp):
30    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
31        super().__init__('<', lhs, rhs, Type.bool, **kwargs)
32
33class GTE(BinaryOp):
34    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
35        super().__init__('>=', lhs, rhs, Type.bool, **kwargs)
36
37class LTE(BinaryOp):
38    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
39        super().__init__('<=', lhs, rhs, Type.bool, **kwargs)
40
41class EQ(BinaryOp):
42    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
43        super().__init__('==', lhs, rhs, Type.bool, **kwargs)
44
45class NEQ(BinaryOp):
46    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
47        super().__init__('!=', lhs, rhs, Type.bool, **kwargs)
48
49class Add(BinaryOp):
50    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
51        super().__init__('+', lhs, rhs, lhs.type, **kwargs)
52
53class Sub(BinaryOp):
54    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
55        super().__init__('-', lhs, rhs, lhs.type, **kwargs)
56
57class Mul(BinaryOp):
58    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
59        super().__init__('*', lhs, rhs, lhs.type, **kwargs)
60
61class Div(BinaryOp):
62    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
63        super().__init__('/', lhs, rhs, lhs.type, **kwargs)
64
65class SHL(BinaryOp):
66    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
67        if lhs.type.width is None: raise RuntimeError('Invalid operand for bitshift')
68        ty_ = lhs.type if lhs.type.width >= 32 else Type.int
69        super().__init__('<<', lhs, rhs, ty_, **kwargs)
70
71class SHR(BinaryOp):
72    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
73        if lhs.type.width is None: raise RuntimeError('Invalid operand for bitshift')
74        ty_ = lhs.type if lhs.type.width >= 32 else Type.int
75        super().__init__('>>', lhs, rhs, ty_, **kwargs)
76
77class USHR(BinaryOp):
78    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
79        if lhs.type.width is None: raise RuntimeError('Invalid operand for bitshift')
80        ty_ = lhs.type if lhs.type.width >= 32 else Type.int
81        super().__init__('>>>', lhs, rhs, ty_, **kwargs)
82
83class AND(BinaryOp):
84    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
85        super().__init__('&', lhs, rhs, lhs.type, **kwargs)
86
87class OR(BinaryOp):
88    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
89        super().__init__('|', lhs, rhs, lhs.type, **kwargs)
90
91class LAND(BinaryOp):
92    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
93        super().__init__('&&', lhs, rhs, Type.bool, **kwargs)
94
95class LOR(BinaryOp):
96    def __init__(self, lhs: Expr, rhs: Expr, **kwargs):
97        super().__init__('||', lhs, rhs, Type.bool, **kwargs)
98
99class Cond(Expr):
100    def __init__(self, cond: Expr, then_: Expr, else_: Expr, **kwargs):
101        super().__init__(then_.type, **kwargs)
102
103        self.cond = cond
104        self.then_ = then_
105        self.else_ = else_
106
107        cond.parent = (self, 'cond')
108        then_.parent = (self, 'then_')
109        else_.parent = (self, 'else_')
110
111    def children(self) -> Iterable[Node]:
112        return [self.cond, self.then_, self.else_]
113
114    def tokenize(self, cg: CodeGenerator) -> Iterable[str | CodeCC]:
115        return chain(
116            self.emit_comment_tokens(inline=True),
117            self.cond.tokenize(cg),
118            [' ? '],
119            self.then_.tokenize(cg),
120            [' : '],
121            self.else_.tokenize(cg)
122        )
123