import traceback
from math import *
from itertools import *
import struct



def run(expression, analysis, cursor):
    if not expression:
        return ""
    new_locals = {
        "analysis": analysis,
        "a": analysis,
        "v": analysis.map.to_phys(cursor),
        "s": None,
        "S": None,
        "read": lambda offset, size: analysis.file.read(offset, size),
        "uint64": lambda offset, msb=False: struct.unpack("{}Q".format(msb and ">" or "<"), analysis.file.read(offset, 8))[0],
        "int64": lambda offset, msb=False: struct.unpack("{}q".format(msb and ">" or "<"), analysis.file.read(offset, 8))[0],
        "uint32": lambda offset, msb=False: struct.unpack("{}I".format(msb and ">" or "<"), analysis.file.read(offset, 4))[0],
        "int32": lambda offset, msb=False: struct.unpack("{}i".format(msb and ">" or "<"), analysis.file.read(offset, 4))[0],
        "uint16": lambda offset, msb=False: struct.unpack("{}H".format(msb and ">" or "<"), analysis.file.read(offset, 2))[0],
        "int16": lambda offset, msb=False: struct.unpack("{}h".format(msb and ">" or "<"), analysis.file.read(offset, 2))[0],
        "uint8": lambda offset: struct.unpack("B", analysis.file.read(offset, 1))[0],
        "int8": lambda offset: struct.unpack("b", analysis.file.read(offset, 1))[0],
    }

    if analysis.sel.start is not None:
        new_locals["s"] = analysis.map.to_phys(analysis.sel.start)
        new_locals["S"] = analysis.map.to_phys(analysis.sel.end)
        
    return str(eval(expression, globals(), new_locals))


def verify_syntax(expression, mode="exec"):
    try:
        compile(expression, "<no file>", mode)
        return ""
    except SyntaxError as e:
        return str(e)
