def compare_values(value1, value2, operator):
    def is_hex(val):
        try:
            int(val, 16)
            return True
        except ValueError:
            return False
    def convert_value(val):
        if isinstance(val, (int, float)):
            return val
        if is_hex(val):
            return int(val, 16)
        try:
            return float(val) if '.' in val else int(val)
        except ValueError:
            raise ValueError(f"Invalid value: {val}")
    value1 = convert_value(value1)
    value2 = convert_value(value2)
    if operator == "==":
        return value1 == value2
    elif operator == "!=":
        return value1 != value2
    elif operator == ">>":
        return value1 > value2
    elif operator == "<<":
        return value1 < value2
    elif operator == ">=":
        return value1 >= value2
    elif operator == "<=":
        return value1 <= value2
    else:
        raise ValueError("Invalid comparison operator")

try:
    from machine import ADC, Pin, PWM
    from time import sleep
    import sys

    Terminated = False

    Registers = {
        "RA": 0,
        "RB": 0,
        "RC": 0,
        "RD": 0,
        "RE": 0,
    }

    Logic = {
        "CMP": False,
        "ADC26": 0,
        "ADC27": 0,
        "ADC28": 0,
        "Pin": 0,
    }

    Stack = {}

    with open("hasm.txt", "r") as file:
        code = file.readlines()
        ln = 0
        while ln < len(code):
            if Terminated:
                break
            line = code[ln].strip()
            if not line:
                ln += 1
                continue
            if line.startswith("test"):
                print("TEST", Registers, Logic, Stack, "TEST")
            if line.startswith("lda"):
                value = line.split()[1]
                try:
                    int_address = value[1:]
                    if int_address in Stack:
                        Registers["RA"] = float(Stack[int_address])
                    else:
                        if int_address in Logic and int_address != "CMP":
                            Registers["RA"] = float(Logic[int_address])
                        else:
                            Registers["RA"] = float(value)
                except:
                    if int_address in Logic and int_address != "CMP":
                        Registers["RA"] = float(Logic[int_address])
                    else:
                        Registers["RA"] = float(value)
            elif line.startswith("ldb"):
                value = line.split()[1]
                try:
                    int_address = value[1:]
                    
                    if int_address in Stack:
                        Registers["RB"] = float(Stack[int_address])
                    else:
                        if int_address in Logic and int_address != "CMP":
                            Registers["RB"] = float(Logic[int_address])
                        else:
                            Registers["RB"] = float(value)
                except:
                    if int_address in Logic and int_address != "CMP":
                        Registers["RB"] = float(Logic[int_address])
                    else:
                        Registers["RB"] = float(value)
            elif line.startswith("ldc"):
                value = line.split()[1]
                try:
                    int_address = value[1:]
                    
                    if int_address in Stack:
                        Registers["RC"] = float(Stack[int_address])
                    else:
                        if int_address in Logic and int_address != "CMP":
                            Registers["RC"] = float(Logic[int_address])
                        else:
                            Registers["RC"] = float(value)
                except:
                    if int_address in Logic and int_address != "CMP":
                        Registers["RC"] = float(Logic[int_address])
                    else:
                        Registers["RC"] = float(value)
            elif line.startswith("ldd"):
                value = line.split()[1]
                try:
                    int_address = value[1:]
                    
                    if int_address in Stack:
                        Registers["RD"] = float(Stack[int_address])
                    else:
                        if int_address in Logic and int_address != "CMP":
                            Registers["RD"] = float(Logic[int_address])
                        else:
                            Registers["RD"] = float(value)
                except:
                    if int_address in Logic and int_address != "CMP":
                        Registers["RD"] = float(Logic[int_address])
                    else:
                        Registers["RD"] = float(value)
            elif line.startswith("lde"):
                value = line.split()[1]
                try:
                    int_address = value[1:]
                    
                    if int_address in Stack:
                        Registers["RE"] = float(Stack[int_address])
                    else:
                        if int_address in Logic and int_address != "CMP":
                            Registers["RE"] = float(Logic[int_address])
                        else:
                            Registers["RE"] = float(value)
                except:
                    if int_address in Logic and int_address != "CMP":
                        Registers["RE"] = float(Logic[int_address])
                    else:
                        Registers["RE"] = float(value)
            elif line.startswith("ldstk"):
                address = line.split()[1]
                int_address = address[1:]
                value = line.split()[2]
                if value in Registers:
                    Stack[int_address] = float(Registers[value])
                elif value.startswith("@"):
                    try:
                        Stack[int_address] = float(Stack[int(value[1:], 16)])
                    except:
                        Stack[int_address] = 0
                else:
                    if int_address in Logic and int_address != "CMP":
                        Stack[int_address] = float(Logic[int_address])
                    else:
                        Stack[int_address] = float(value)
            elif line.startswith("add"):
                try:
                    value1 = float(Registers[str(line.split()[2])])
                except KeyError:
                    try:
                        address = line.split()[2]
                        int_address = address[1:]
                        value1 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value1 = float(Logic[line.split()[2]])
                        except KeyError:
                            value1 = float(line.split()[2])
                try:
                    value2 = float(Registers[str(line.split()[3])])
                except KeyError:
                    try:
                        address = line.split()[3]
                        int_address = address[1:]
                        value2 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value2 = float(Logic[line.split()[3]])
                        except KeyError:
                            value2 = float(line.split()[3])
                try:
                    variable = line.split()[1]
                    if variable.startswith("@"):
                        int_address = variable[1:]
                        Stack[int_address] = float(float(value1) + float(value2))
                    elif variable in Registers:
                        Registers[str(variable)] = float(float(value1) + float(value2))
                    elif variable in Logic and variable != "CMP":
                        Logic[str(variable)] = float(float(value1) + float(value2))
                except:
                    pass
            elif line.startswith("sub"):
                try:
                    value1 = float(Registers[str(line.split()[2])])
                except KeyError:
                    try:
                        address = line.split()[2]
                        int_address = address[1:]
                        value1 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value1 = float(Logic[line.split()[2]])
                        except KeyError:
                            value1 = float(line.split()[2])
                try:
                    value2 = float(Registers[str(line.split()[3])])
                except KeyError:
                    try:
                        address = line.split()[3]
                        int_address = address[1:]
                        value2 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value2 = float(Logic[line.split()[3]])
                        except KeyError:
                            value2 = float(line.split()[3])
                try:
                    variable = line.split()[1]
                    if variable.startswith("@"):
                        int_address = variable[1:]
                        Stack[int_address] = float(float(value1) - float(value2))
                    elif variable in Registers:
                        Registers[str(variable)] = float(float(value1) - float(value2))
                    elif variable in Logic and variable != "CMP":
                        Logic[str(variable)] = float(float(value1) - float(value2))
                except:
                    pass
            elif line.startswith("mul"):
                try:
                    value1 = float(Registers[str(line.split()[2])])
                except KeyError:
                    try:
                        address = line.split()[2]
                        int_address = address[1:]
                        value1 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value1 = float(Logic[line.split()[2]])
                        except KeyError:
                            value1 = float(line.split()[2])
                try:
                    value2 = float(Registers[str(line.split()[3])])
                except KeyError:
                    try:
                        address = line.split()[3]
                        int_address = address[1:]
                        value2 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value2 = float(Logic[line.split()[3]])
                        except KeyError:
                            value2 = float(line.split()[3])
                try:
                    variable = line.split()[1]
                    if variable.startswith("@"):
                        int_address = variable[1:]
                        Stack[int_address] = float(float(value1) * float(value2))
                    elif variable in Registers:
                        Registers[str(variable)] = float(float(value1) * float(value2))
                    elif variable in Logic and variable != "CMP":
                        Logic[str(variable)] = float(float(value1) * float(value2))
                except:
                    pass
            elif line.startswith("div"):
                try:
                    value1 = float(Registers[str(line.split()[2])])
                except KeyError:
                    try:
                        address = line.split()[2]
                        int_address = address[1:]
                        value1 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value1 = float(Logic[line.split()[2]])
                        except KeyError:
                            value1 = float(line.split()[2])
                try:
                    value2 = float(Registers[str(line.split()[3])])
                except KeyError:
                    try:
                        address = line.split()[3]
                        int_address = address[1:]
                        value2 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value2 = float(Logic[line.split()[3]])
                        except KeyError:
                            value2 = float(line.split()[3])
                try:
                    variable = line.split()[1]
                    if variable.startswith("@"):
                        int_address = variable[1:]
                        Stack[int_address] = float(float(value1) / float(value2))
                    elif variable in Registers:
                        Registers[str(variable)] = float(float(value1) / float(value2))
                    elif variable in Logic and variable != "CMP":
                        Logic[str(variable)] = float(float(value1) / float(value2))
                except:
                    pass
            elif line.startswith("idiv"):
                try:
                    value1 = float(Registers[str(line.split()[2])])
                except KeyError:
                    try:
                        address = line.split()[2]
                        int_address = address[1:]
                        value1 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value1 = float(Logic[line.split()[2]])
                        except KeyError:
                            value1 = float(line.split()[2])
                try:
                    value2 = float(Registers[str(line.split()[3])])
                except KeyError:
                    try:
                        address = line.split()[3]
                        int_address = address[1:]
                        value2 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value2 = float(Logic[line.split()[3]])
                        except KeyError:
                            value2 = float(line.split()[3])
                try:
                    variable = line.split()[1]
                    if variable.startswith("@"):
                        int_address = variable[1:]
                        Stack[int_address] = float(float(value1) // float(value2))
                    elif variable in Registers:
                        Registers[str(variable)] = float(float(value1) // float(value2))
                    elif variable in Logic and variable != "CMP":
                        Logic[str(variable)] = float(float(value1) // float(value2))
                except:
                    pass
            elif line.startswith("pow"):
                try:
                    value1 = float(Registers[str(line.split()[2])])
                except KeyError:
                    try:
                        address = line.split()[2]
                        int_address = address[1:]
                        value1 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value1 = float(Logic[line.split()[2]])
                        except KeyError:
                            value1 = float(line.split()[2])
                try:
                    value2 = float(Registers[str(line.split()[3])])
                except KeyError:
                    try:
                        address = line.split()[3]
                        int_address = address[1:]
                        value2 = float(Stack[int_address])
                    except KeyError:
                        try:
                            value2 = float(Logic[line.split()[3]])
                        except KeyError:
                            value2 = float(line.split()[3])
                try:
                    variable = line.split()[1]
                    if variable.startswith("@"):
                        int_address = variable[1:]
                        Stack[int_address] = float(float(value1) ^ float(value2))
                    elif variable in Registers:
                        Registers[str(variable)] = float(float(value1) ^ float(value2))
                    elif variable in Logic and variable != "CMP":
                        Logic[str(variable)] = float(float(value1) ^ float(value2))
                except:
                    pass
            elif line.startswith("relcmp"):
                Logic["CMP"] = False
            elif line.startswith("jmpc"):
                if Logic["CMP"] == True:
                    jump_value = line.split()[1]
                    if jump_value.startswith("+"):
                        jump_target = int(jump_value[1:])
                        ln += jump_target
                    elif jump_value.startswith("-"):
                        jump_target = -int(jump_value[1:])
                        ln += jump_target
                    else:
                        ln = int(jump_value) - 1
                    if 0 <= ln < len(code):
                        continue
                    else:
                        Terminated = True
                        sys.exit(0)
            elif line.startswith("jmpnc"):
                if Logic["CMP"] == False:
                    jump_value = line.split()[1]
                    if jump_value.startswith("+"):
                        jump_target = int(jump_value[1:])
                        ln += jump_target
                    elif jump_value.startswith("-"):
                        jump_target = -int(jump_value[1:])
                        ln += jump_target
                    else:
                        ln = int(jump_value) - 1
                    if 0 <= ln < len(code):
                        continue
                    else:
                        Terminated = True
                        sys.exit(0)
            elif line.startswith("jmp"):
                jump_value = line.split()[1]
                if jump_value.startswith("+"):
                    jump_target = int(jump_value[1:])
                    ln += jump_target
                elif jump_value.startswith("-"):
                    jump_target = -int(jump_value[1:])
                    ln += jump_target
                else:
                    ln = int(jump_value) - 1
                if 0 <= ln < len(code):
                    continue
                else:
                    Terminated = True
                    sys.exit(0)
            elif line.startswith("cmp"):
                try:
                    value1 = str(Registers[str(line.split()[1])])
                except KeyError:
                    try:
                        address = line.split()[1]
                        int_address = address[1:]
                        value1 = str(Stack[int_address])
                    except KeyError:
                        if line.split()[1] in ["ADC26", "ADC27", "ADC28", "Pin"]:
                            value1 = str(float(Logic[str(line.split()[1])]))
                        else:
                            value1 = str(float(line.split()[1]))
                operator = str(line.split()[2])
                try:
                    value2 = str(Registers[str(line.split()[3])])
                except KeyError:
                    try:
                        address = line.split()[3]
                        int_address = address[1:]
                        value2 = str(Stack[int_address])
                    except KeyError:
                        if line.split()[3] in ["ADC26", "ADC27", "ADC28", "Pin"]:
                            value1 = str(float(Logic[str(line.split()[3])]))
                        else:
                            value2 = str(float(line.split()[3]))
                Logic["CMP"] = compare_values(eval(value1), eval(value2), operator)
            elif line.startswith("syscall"):
                if int(Registers["RA"]) == 1:
                    Terminated = True
                    sys.exit(0)
                elif int(Registers["RA"]) == 2:
                    sleep(Registers["RB"])
                elif int(Registers["RA"]) == 3:
                    Pin(int(Registers["RB"]), Pin.OUT).value(int(Registers["RC"]))
                elif int(Registers["RA"]) == 4:
                    Logic["Pin"] = Pin(int(Registers["RB"]), Pin.IN, Pin.PULL_DOWN).value()
                elif int(Registers["RA"]) == 5:
                    Logic["ADC" + f"{int(Registers['RB'])}"] = ADC(Pin(int(Registers["RB"]))).read_u16()
                elif int(Registers["RA"]) == 6:
                    pwm_pin = PWM(Pin(int(Registers["RB"])))
                    pwm_pin.freq(int(Registers["RC"]))
                    if Registers["RD"] == 1:
                        if 0 <= Registers["RE"] <= 65536:
                            pwm_pin.duty_u16(int(Registers["RE"]))
                        elif 0 >= Registers["RE"]:
                            pwm_pin.duty_u16(0)
                        elif 100 <= Registers["RE"]:
                            pwm_pin.duty_u16(65535)
                    elif Registers["RD"] == 2:
                        if 0 <= Registers["RE"] <= 100:
                            duty_value = int((Registers["RE"] / 100) * 65535)
                            pwm_pin.duty_u16(duty_value)
                        elif 0 >= Registers["RE"]:
                            pwm_pin.duty_u16(0)
                        elif 100 <= Registers["RD"]:
                            pwm_pin.duty_u16(65535)
            ln += 1
except KeyboardInterrupt:
    sys.exit(0)
except Exception as E:
    from machine import Pin
    Pin(22, Pin.OUT).value(1)
    print(E)
    sys.exit(0)