c_eval(expr)

Evaluate a C arithmetic/logic expression and return the result

Examples:

>>> c_eval('10 + (5 / 3)')
11
>>> c_eval('!0')
1
>>> c_eval('sizeof(x)')
128
Parameters:
  • expr (str) –

    C expression

Returns:
  • result( Union[int, float] ) –

    the expression evaluation result

Raises:
  • EvalError

    expression evaluation error

Source code in cstruct/c_expr.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
def c_eval(expr: str) -> Union[int, float]:
    """
    Evaluate a C arithmetic/logic expression and return the result

    Examples:
        >>> c_eval('10 + (5 / 3)')
        11
        >>> c_eval('!0')
        1
        >>> c_eval('sizeof(x)')
        128

    Args:
        expr: C expression

    Returns:
        result: the expression evaluation result

    Raises:
        EvalError: expression evaluation error
    """
    try:
        expr = expr.replace("!", " not ").replace("&&", " and ").replace("||", " or ")
        return eval_node(ast.parse(expr.strip()).body[0])
    except EvalError:
        raise
    except Exception:
        raise EvalError

eval_attribute_node(node)

Evaluate node attribute, e.g. 'self.x' Only 'self' is allowed. The attribute must be a number.

Parameters:
  • node (Attribute) –

    attribute node

Returns:
  • result( Union[int, float] ) –

    the attribute value

Raises:
  • EvalError

    expression result is not a number, or not self attribute

  • ContextNotFound

    context is not defined

Source code in cstruct/c_expr.py
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
def eval_attribute_node(node: ast.Attribute) -> Union[int, float]:
    """
    Evaluate node attribute, e.g. 'self.x'
    Only 'self' is allowed. The attribute must be a number.

    Args:
        node: attribute node

    Returns:
        result: the attribute value

    Raises:
        EvalError: expression result is not a number, or not self attribute
        ContextNotFound: context is not defined
    """
    if not node.value or node.value.id != "self":  # type: ignore
        raise EvalError("only self is allowed")
    context = get_cstruct_context()
    if context is None:
        raise ContextNotFound("context is not defined")
    result = getattr(context, node.attr)
    if not isinstance(result, (int, float)):
        raise EvalError("expression result is not a number")
    return result

eval_compare(node)

Evaluate a compare node

Source code in cstruct/c_expr.py
119
120
121
122
123
124
125
126
127
def eval_compare(node) -> bool:
    "Evaluate a compare node"
    right = eval_node(node.left)
    for operation, comp in zip(node.ops, node.comparators):
        left = right
        right = eval_node(comp)
        if not OPS[type(operation)](left, right):
            return False
    return True

eval_div(node)

Evaluate div node (integer/float)

Source code in cstruct/c_expr.py
130
131
132
133
134
135
136
137
def eval_div(node) -> Union[int, float]:
    "Evaluate div node (integer/float)"
    left = eval_node(node.left)
    right = eval_node(node.right)
    if isinstance(left, float) or isinstance(right, float):
        return operator.truediv(left, right)
    else:
        return operator.floordiv(left, right)

eval_get(node)

Get definition/struct by name

Source code in cstruct/c_expr.py
111
112
113
114
115
116
def eval_get(node) -> Union[int, float, Type["AbstractCStruct"]]:
    "Get definition/struct by name"
    try:
        return DEFINES[node.id]
    except KeyError:
        return STRUCTS[node.id]

get_cstruct_context()

Get the calling CStruct instance from the stack (if any)

Source code in cstruct/c_expr.py
149
150
151
152
153
154
155
156
157
158
159
160
def get_cstruct_context() -> Optional["AbstractCStruct"]:
    """
    Get the calling CStruct instance from the stack (if any)
    """
    from .abstract import AbstractCStruct

    stack = inspect.stack()
    for frame in stack:
        caller_self = frame.frame.f_locals.get("self")
        if isinstance(caller_self, AbstractCStruct):
            return caller_self
    return None