PDS-x BASIC yeni askim.

 Pdsx benim yarattigim bir dil. Pythonda kodlamayi seviyorum ama indentation error hatalarindan biktim usandim artik. Hayir neyin nereden basladigini bile anlamakta zorlaniyorum. Kafamda bozuktu. Bende Neden Basic gibi bir Python olmasin ki dedim.

Sonra gaza geldim. Cunku pythonu kutuphanelerini sarmalarsam (Wrapper) Basic gibi yazarim dedim. e sadece o is oyle olmuyor buna lexer yaacaksin, Parser yazacaksin. Kodu yurutmek icinde kod yurutucusu (executer) yazacaksin. Bunlarlada bitmez syntax i oturtman gerekir falan. belgelendirmen test dosyalari yazman falan da gerekir. iyi bir planlama ile chatgpt ye yaptirabilirim dedim. 

Oldu ama oyle oldu. chat gpt kadar oldu.

Ilk basta begendim. ama promtlarda isteklerimi soylemem onun yapacagi anlamaina gelmiyor baglamda ne anladiysa onu yapiyor bu arada chatgpt gibi yapay zeka bircok arkadaslarla tanistim ve sorgu isinin erbabi oldum.
 

ben once bayagi kolaya kactim
bu yeni projem. pdsX interpreter versiyon 5

import re             # regex her bir seyi ayirt etmeye gerekli

import random    # rastgele sayi uretecem ya lazim olur

import sqlite3    # Basic ISAM varya onu sqlite ile taklit edecegim

import numpy as np    # Fonksiyonlarini taklit edecegim, veri yapilarini calacagim

import pandas as pd    # Fonksiyonlarini taklit edecegim, veri yapilarini calacagim

import scipy.stats as stats # Fonksiyonlarini taklit edecegim, veri yapilarini calacagim, istatistik kolayca yaparim

from collections import defaultdict, namedtuple 

from types import SimpleNamespace

import os #her python dosya islemlerinin olmazsa olmazi

import logging # loglamak bu kadar kolay olmasaydi koymazdim. Hata bulmada cok yararli.

import time # interpreterin zaman isleri icin

import sys # Gerekli bu olmadan python ne ki?

import argparse # Bu da gereklilik. Kod satirindan komut calistirmanin anahtari

import struct 


# Hata loglama için logging ayarı

logging.basicConfig(filename='interpreter_errors.log', level=logging.ERROR, format='%(asctime)s - %(message)s')


class pdsXInterpreter:

    def __init__(self):

        self.global_vars = {}  # GLOBAL değişkenler

        self.shared_vars = defaultdict(list)  # DIM SHARED değişkenler

        self.local_scopes = [{}]  # Yerel kapsam yığını

        self.types = {}  # TYPE tanımları

        self.classes = {}  # CLASS tanımları

        self.functions = {}  # FUNCTION tanımları

        self.subs = {}  # SUB tanımları

        self.labels = {}  # Etiketler

        self.program = []  # Program satırları

        self.program_counter = 0

        self.call_stack = []  # GOSUB, SUB, FUNCTION için yığın

        self.running = False

        self.db_connections = {}  # Veritabanı bağlantıları

        self.file_handles = {}  # Dosya kolları

        self.error_handler = None  # ON ERROR GOTO için

        self.debug_mode = False  # DEBUG modu

        self.loop_stack = []  # DO...LOOP, FOR...NEXT için yığın

        self.select_stack = []  # SELECT CASE için yığın

        self.if_stack = []  # IF...THEN...ELSE için yığın

        self.data_list = []  # DATA komutları için liste

        self.data_pointer = 0  # READ komutu için işaretçi

        self.transaction_active = {}  # Transaction durumları

        self.type_table = {  # Veri tipleri tablosu

            "STRING": str,

            "INTEGER": int,

            "LONG": int,

            "SINGLE": float,

            "DOUBLE": float,

            "BYTE": int,

            "SHORT": int,

            "UNSIGNED INTEGER": int,

            "CHAR": str,

            "LIST": list,

            "DICT": dict,

            "SET": set,

            "TUPLE": tuple,

            "ARRAY": np.array,

            "DATAFRAME": pd.DataFrame,

            "POINTER": None,  # Bellek simülasyonu

            "STRUCT": dict,  # Basit struct simülasyonu

            "UNION": None,  # Tek değer depolama

            "ENUM": dict,

            "VOID": None,

            "BITFIELD": int

        }

        self.function_table = {

            "MID$": lambda s, start, length: s[start-1:start-1+length],

            "LEN": len,

            "RND": random.random,

            "ABS": abs,

            "INT": int,

            "LEFT$": lambda s, n: s[:n],

            "RIGHT$": lambda s, n: s[-n:],

            "LTRIM$": lambda s: s.lstrip(),

            "RTRIM$": lambda s: s.rstrip(),

            "STRING$": lambda n, c: c * n,

            "SPACE$": lambda n: " " * n,

            "INSTR": lambda start, s, sub: s.find(sub, start-1) + 1,

            "UCASE$": lambda s: s.upper(),

            "LCASE$": lambda s: s.lower(),

            "STR$": lambda n: str(n),

            "SQR": np.sqrt,

            "SIN": np.sin,

            "COS": np.cos,

            "TAN": np.tan,

            "LOG": np.log,

            "EXP": np.exp,

            "ATN": np.arctan,

            "FIX": lambda x: int(x),

            "ROUND": lambda x, n=0: round(x, n),

            "SGN": lambda x: -1 if x < 0 else (1 if x > 0 else 0),

            "MOD": lambda x, y: x % y,

            "MIN": lambda *args: min(args),

            "MAX": lambda *args: max(args),

            "TIMER": lambda: time.time(),

            "DATE$": lambda: time.strftime("%m-%d-%Y"),

            "TIME$": lambda: time.strftime("%H:%M:%S"),

            "INKEY$": lambda: input()[:1],

            "ENVIRON$": lambda var: os.environ.get(var, ""),

            "COMMAND$": lambda: " ".join(sys.argv[1:]),

            "CSRLIN": lambda: 1,  # Basit simülasyon

            "POS": lambda x: 1,  # Basit simülasyon

            "VAL": lambda s: float(s) if s.replace(".", "").isdigit() else 0,

            "ASC": lambda c: ord(c[0]),

            "MEAN": np.mean,

            "MEDIAN": np.median,

            "MODE": lambda x: stats.mode(x)[0][0],

            "STD": np.std,

            "VAR": np.var,

            "SUM": np.sum,

            "PROD": np.prod,

            "PERCENTILE": np.percentile,

            "QUANTILE": np.quantile,

            "CORR": lambda x, y: np.corrcoef(x, y)[0, 1],

            "COV": np.cov,

            "DESCRIBE": lambda df: df.describe(),

            "GROUPBY": lambda df, col: df.groupby(col),

            "FILTER": lambda df, cond: df.query(cond),

            "SORT": lambda df, col: df.sort_values(col),

            "HEAD": lambda df, n=5: df.head(n),

            "TAIL": lambda df, n=5: df.tail(n),

            "MERGE": lambda df1, df2, on: pd.merge(df1, df2, on=on),

            "TTEST": lambda sample1, sample2: stats.ttest_ind(sample1, sample2),

            "CHISQUARE": lambda observed: stats.chisquare(observed),

            "ANOVA": lambda *groups: stats.f_oneway(*groups),

            "REGRESS": lambda x, y: stats.linregress(x, y),

            "EOF": lambda n: self.file_handles[n].eof(),

            "LOC": lambda n: self.file_handles[n].tell(),

            "LOF": lambda n: os.path.getsize(self.file_handles[n].name),

            "FREEFILE": lambda: min(set(range(1, 100)) - set(self.file_handles.keys())),

            "CHR$": lambda n: chr(n),

            "INPUT$": lambda n, f: self.file_handles[f].read(n),

            "MKI$": lambda n: struct.pack("i", n).decode('latin1'),

            "MKS$": lambda n: struct.pack("f", n).decode('latin1'),

            "MKD$": lambda n: struct.pack("d", n).decode('latin1')

        }


    def current_scope(self):

        return self.local_scopes[-1]


    def parse_program(self, code):

        self.program = []

        current_sub = None

        current_function = None

        current_type = None

        current_class = None

        type_fields = {}

        class_methods = {}

        lines = code.split("\n")

        i = 0

        while i < len(lines):

            line = lines[i].strip()

            if not line:

                i += 1

                continue

            line_upper = line.upper()

            if line_upper.startswith("SUB "):

                sub_name = line[4:].split("(")[0].strip()

                self.subs[sub_name] = i + 1

                current_sub = sub_name

                i += 1

            elif line_upper.startswith("FUNCTION "):

                func_name = line[8:].split("(")[0].strip()

                self.functions[func_name] = i + 1

                current_function = func_name

                i += 1

            elif line_upper.startswith("TYPE "):

                type_name = line[5:].strip()

                current_type = type_name

                type_fields[type_name] = []

                i += 1

            elif line_upper.startswith("END TYPE"):

                self.types[current_type] = namedtuple(current_type, [f[0] for f in type_fields[current_type]])

                current_type = None

                i += 1

            elif current_type:

                match = re.match(r"(\w+)\s+AS\s+(\w+)", line, re.IGNORECASE)

                if match:

                    field_name, field_type = match.groups()

                    type_fields[current_type].append((field_name, field_type))

                else:

                    raise Exception(f"TYPE tanımı hatası: {line}")

                i += 1

            elif line_upper.startswith("CLASS "):

                class_name = line[6:].strip()

                current_class = class_name

                class_methods[class_name] = {}

                i += 1

            elif line_upper.startswith("END CLASS"):

                class_def = type(current_class, (), {

                    **class_methods[current_class],

                    '_vars': {},

                    '__init__': lambda self: None

                })

                self.classes[current_class] = class_def

                current_class = None

                i += 1

            elif current_class and line_upper.startswith("SUB "):

                method_name = line[4:].split("(")[0].strip()

                class_methods[current_class][method_name] = lambda self, *args: self._vars.get(method_name, lambda: None)(*args)

                i += 1

            elif line_upper == "END SUB" or line_upper == "END FUNCTION":

                current_sub = None

                current_function = None

                i += 1

            elif line_upper.startswith("LABEL "):

                label_name = line[6:].strip()

                self.labels[label_name] = i

                i += 1

            elif line_upper.startswith("DATA "):

                data_items = line[5:].split(",")

                self.data_list.extend([item.strip() for item in data_items])

                i += 1

            else:

                if current_sub or current_function:

                    self.program.append((line, current_sub or current_function))

                else:

                    self.program.append((line, None))

                i += 1


    def evaluate_expression(self, expr, scope_name=None):

        expr = expr.strip()

        namespace = {}

        namespace.update(self.global_vars)

        namespace.update(self.current_scope())

        for var in self.shared_vars:

            if scope_name in self.shared_vars[var] or not self.shared_vars[var]:

                namespace[var] = self.shared_vars[var]

        namespace.update(self.function_table)

        namespace["np"] = np

        namespace["pd"] = pd

        namespace["stats"] = stats

        try:

            return eval(expr, namespace)

        except Exception as e:

            raise Exception(f"İfade değerlendirme hatası: {expr}, Hata: {str(e)}")


    def execute_command(self, command, scope_name=None):

        command = command.strip()

        if not command:

            return None

        command_upper = command.upper()


        try:

            # Hata Yönetimi

            if command_upper.startswith("ON ERROR GOTO"):

                match = re.match(r"ON ERROR GOTO\s+(\w+)", command, re.IGNORECASE)

                if match:

                    label = match.group(1)

                    if label in self.labels:

                        self.error_handler = self.labels[label]

                    else:

                        raise Exception(f"Etiket bulunamadı: {label}")

                    return None

                else:

                    raise Exception("ON ERROR GOTO komutunda sözdizimi hatası")


            if command_upper == "RESUME":

                if self.error_handler is not None:

                    return self.error_handler

                else:

                    raise Exception("RESUME için hata işleyicisi tanımlı değil")


            if command_upper == "DEBUG ON":

                self.debug_mode = True

                return None

            if command_upper == "DEBUG OFF":

                self.debug_mode = False

                return None


            # WHILE...WEND Desteği

            if command_upper.startswith("WHILE"):

                match = re.match(r"WHILE\s+(.+)", command, re.IGNORECASE)

                if match:

                    condition = match.group(1)

                    self.loop_stack.append({

                        "start": self.program_counter,

                        "type": "WHILE",

                        "condition": condition

                    })

                    if not self.evaluate_expression(condition, scope_name):

                        while self.program_counter < len(self.program) and \

                              self.program[self.program_counter][0].upper() != "WEND":

                            self.program_counter += 1

                    return None

                else:

                    raise Exception("WHILE komutunda sözdizimi hatası")


            if command_upper == "WEND":

                if self.loop_stack and self.loop_stack[-1]["type"] == "WHILE":

                    loop_info = self.loop_stack[-1]

                    if self.evaluate_expression(loop_info["condition"], scope_name):

                        return loop_info["start"]

                    else:

                        self.loop_stack.pop()

                    return None

                else:

                    raise Exception("WEND için eşleşen WHILE bulunamadı")


            # FOR...NEXT Desteği

            if command_upper.startswith("FOR"):

                match = re.match(r"FOR\s+(\w+)\s*=\s*(.+)\s+TO\s+(.+)(?:\s+STEP\s+(.+))?", command, re.IGNORECASE)

                if match:

                    var_name, start_expr, end_expr, step_expr = match.groups()

                    start = self.evaluate_expression(start_expr, scope_name)

                    end = self.evaluate_expression(end_expr, scope_name)

                    step = self.evaluate_expression(step_expr, scope_name) if step_expr else 1

                    if var_name in self.global_vars:

                        self.global_vars[var_name] = start

                    else:

                        self.current_scope()[var_name] = start

                    self.loop_stack.append({

                        "start": self.program_counter,

                        "type": "FOR",

                        "var": var_name,

                        "end": end,

                        "step": step

                    })

                    return None

                else:

                    raise Exception("FOR komutunda sözdizimi hatası")


            if command_upper.startswith("NEXT"):

                if self.loop_stack and self.loop_stack[-1]["type"] == "FOR":

                    loop_info = self.loop_stack[-1]

                    var_name = loop_info["var"]

                    current_value = self.global_vars.get(var_name, self.current_scope().get(var_name))

                    current_value += loop_info["step"]

                    if var_name in self.global_vars:

                        self.global_vars[var_name] = current_value

                    else:

                        self.current_scope()[var_name] = current_value

                    if (loop_info["step"] > 0 and current_value <= loop_info["end"]) or \

                       (loop_info["step"] < 0 and current_value >= loop_info["end"]):

                        return loop_info["start"]

                    else:

                        self.loop_stack.pop()

                    return None

                else:

                    raise Exception("NEXT için eşleşen FOR bulunamadı")


            # DO...LOOP Desteği

            if command_upper.startswith("DO"):

                match = re.match(r"DO\s+(WHILE|UNTIL)?\s*(.+)?", command, re.IGNORECASE)

                if match:

                    loop_type, condition = match.groups()

                    self.loop_stack.append({

                        "start": self.program_counter,

                        "type": loop_type or "NONE",

                        "condition": condition or "True"

                    })

                    return None

                else:

                    raise Exception("DO komutunda sözdizimi hatası")


            if command_upper.startswith("LOOP"):

                match = re.match(r"LOOP\s+(WHILE|UNTIL)?\s*(.+)?", command, re.IGNORECASE)

                if match and self.loop_stack:

                    loop_type, condition = match.groups()

                    loop_info = self.loop_stack[-1]

                    if loop_type and condition:

                        cond_result = self.evaluate_expression(condition, scope_name)

                        if (loop_type == "WHILE" and cond_result) or (loop_type == "UNTIL" and not cond_result):

                            return loop_info["start"]

                        else:

                            self.loop_stack.pop()

                    elif loop_info["type"] == "WHILE":

                        if self.evaluate_expression(loop_info["condition"], scope_name):

                            return loop_info["start"]

                        else:

                            self.loop_stack.pop()

                    elif loop_info["type"] == "UNTIL":

                        if not self.evaluate_expression(loop_info["condition"], scope_name):

                            return loop_info["start"]

                        else:

                            self.loop_stack.pop()

                    else:

                        return loop_info["start"]

                    return None

                else:

                    raise Exception("LOOP için eşleşen DO bulunamadı")


            # SELECT CASE Desteği

            if command_upper.startswith("SELECT CASE"):

                match = re.match(r"SELECT CASE\s+(.+)", command, re.IGNORECASE)

                if match:

                    expr = match.group(1)

                    value = self.evaluate_expression(expr, scope_name)

                    self.select_stack.append({"value": value, "matched": False, "start": self.program_counter})

                    return None

                else:

                    raise Exception("SELECT CASE komutunda sözdizimi hatası")


            if command_upper.startswith("CASE"):

                if not self.select_stack:

                    raise Exception("CASE için eşleşen SELECT CASE bulunamadı")

                select_info = self.select_stack[-1]

                match = re.match(r"CASE\s+(.+)", command, re.IGNORECASE)

                if match:

                    case_expr = match.group(1)

                    if case_expr.upper() == "ELSE":

                        if not select_info["matched"]:

                            select_info["matched"] = True

                        else:

                            while self.program_counter < len(self.program) and \

                                  self.program[self.program_counter][0].upper() != "END SELECT":

                                self.program_counter += 1

                    else:

                        case_value = self.evaluate_expression(case_expr, scope_name)

                        if select_info["value"] == case_value and not select_info["matched"]:

                            select_info["matched"] = True

                        else:

                            while self.program_counter < len(self.program) and \

                                  self.program[self.program_counter][0].upper() not in ("CASE", "END SELECT"):

                                self.program_counter += 1

                    return None

                else:

                    raise Exception("CASE komutunda sözdizimi hatası")


            if command_upper == "END SELECT":

                if self.select_stack:

                    self.select_stack.pop()

                    return None

                else:

                    raise Exception("END SELECT için eşleşen SELECT CASE bulunamadı")


            # IF...THEN...ELSE...END IF Desteği

            if command_upper.startswith("IF"):

                match = re.match(r"IF\s+(.+)\s+THEN", command, re.IGNORECASE)

                if match:

                    condition = match.group(1)

                    cond_result = self.evaluate_expression(condition, scope_name)

                    self.if_stack.append({"condition": cond_result, "start": self.program_counter, "else_found": False})

                    if not cond_result:

                        while self.program_counter < len(self.program) and \

                              self.program[self.program_counter][0].upper() not in ("ELSE", "END IF"):

                            self.program_counter += 1

                    return None

                else:

                    raise Exception("IF komutunda sözdizimi hatası")


            if command_upper == "ELSE":

                if not self.if_stack:

                    raise Exception("ELSE için eşleşen IF bulunamadı")

                if_info = self.if_stack[-1]

                if if_info["condition"] or if_info["else_found"]:

                    while self.program_counter < len(self.program) and \

                          self.program[self.program_counter][0].upper() != "END IF":

                        self.program_counter += 1

                if_info["else_found"] = True

                return None


            if command_upper == "END IF":

                if self.if_stack:

                    self.if_stack.pop()

                    return None

                else:

                    raise Exception("END IF için eşleşen IF bulunamadı")


            # Değişken ve Veri Yönetimi

            if command_upper.startswith("DEFINT"):

                match = re.match(r"DEFINT\s+(\w+)", command, re.IGNORECASE)

                if match:

                    var_name = match.group(1)

                    self.current_scope()[var_name] = 0

                    return None

                else:

                    raise Exception("DEFINT komutunda sözdizimi hatası")


            if command_upper.startswith("DEFSNG"):

                match = re.match(r"DEFSNG\s+(\w+)", command, re.IGNORECASE)

                if match:

                    var_name = match.group(1)

                    self.current_scope()[var_name] = 0.0

                    return None

                else:

                    raise Exception("DEFSNG komutunda sözdizimi hatası")


            if command_upper.startswith("DEFDBL"):

                match = re.match(r"DEFDBL\s+(\w+)", command, re.IGNORECASE)

                if match:

                    var_name = match.group(1)

                    self.current_scope()[var_name] = 0.0

                    return None

                else:

                    raise Exception("DEFDBL komutunda sözdizimi hatası")


            if command_upper.startswith("DEFSTR"):

                match = re.match(r"DEFSTR\s+(\w+)", command, re.IGNORECASE)

                if match:

                    var_name = match.group(1)

                    self.current_scope()[var_name] = ""

                    return None

                else:

                    raise Exception("DEFSTR komutunda sözdizimi hatası")


            if command_upper.startswith("GLOBAL"):

                match = re.match(r"GLOBAL\s+(\w+)\s+AS\s+(\w+)", command, re.IGNORECASE)

                if match:

                    var_name, var_type = match.groups()

                    self.global_vars[var_name] = self.type_table.get(var_type, None)()

                    return None

                else:

                    raise Exception("GLOBAL komutunda sözdizimi hatası")


            if command_upper.startswith("DIM SHARED"):

                match = re.match(r"DIM SHARED\s+(.+)\s+AS\s+(\w+)", command, re.IGNORECASE)

                if match:

                    scopes, var_type = match.groups()

                    var_name = scopes.split(",")[-1].strip()

                    scope_list = [s.strip() for s in scopes.split(",")[:-1]]

                    self.shared_vars[var_name] = scope_list

                    return None

                else:

                    raise Exception("DIM SHARED komutunda sözdizimi hatası")


            if command_upper.startswith("DIM"):

                match = re.match(r"DIM\s+(\w+)\s+AS\s+(\w+)", command, re.IGNORECASE)

                if match:

                    var_name, var_type = match.groups()

                    if var_type in self.types:

                        self.current_scope()[var_name] = self.types[var_type](*[None for _ in self.types[var_type]._fields])

                    elif var_type in self.classes:

                        self.current_scope()[var_name] = self.classes[var_type]()

                    elif var_type == "ARRAY":

                        self.current_scope()[var_name] = np.array([])

                    elif var_type == "DATAFRAME":

                        self.current_scope()[var_name] = pd.DataFrame()

                    elif var_type == "STRING":

                        self.current_scope()[var_name] = ""

                    elif var_type in ("INTEGER", "LONG"):

                        self.current_scope()[var_name] = 0

                    elif var_type in ("SINGLE", "DOUBLE"):

                        self.current_scope()[var_name] = 0.0

                    elif var_type == "BYTE":

                        self.current_scope()[var_name] = 0

                    elif var_type == "SHORT":

                        self.current_scope()[var_name] = 0

                    elif var_type == "UNSIGNED INTEGER":

                        self.current_scope()[var_name] = 0

                    elif var_type == "CHAR":

                        self.current_scope()[var_name] = ''

                    elif var_type == "LIST":

                        self.current_scope()[var_name] = []

                    elif var_type == "DICT":

                        self.current_scope()[var_name] = {}

                    elif var_type == "SET":

                        self.current_scope()[var_name] = set()

                    elif var_type == "TUPLE":

                        self.current_scope()[var_name] = ()

                    else:

                        raise Exception(f"Tanımlanamayan veri tipi: {var_type}")

                    return None

                else:

                    raise Exception("DIM komutunda sözdizimi hatası")


            if command_upper.startswith("LET"):

                match = re.match(r"LET\s+(\w+)\s*=\s*(.+)", command, re.IGNORECASE)

                if match:

                    var_name, expr = match.groups()

                    value = self.evaluate_expression(expr, scope_name)

                    if var_name in self.global_vars:

                        self.global_vars[var_name] = value

                    elif var_name in self.shared_vars and (scope_name in self.shared_vars[var_name] or not self.shared_vars[var_name]):

                        self.shared_vars[var_name] = value

                    elif var_name in self.current_scope():

                        self.current_scope()[var_name] = value

                    else:

                        raise Exception(f"Tanımlanmamış değişken: {var_name}")

                    return None

                else:

                    raise Exception("LET komutunda sözdizimi hatası")


            # Girdi/Çıktı

            if command_upper.startswith("PRINT"):

                print_str = command[5:].strip()

                parts = re.split(r'([;,])', print_str)

                output = ""

                for j in range(0, len(parts), 2):

                    arg = parts[j].strip()

                    if arg:

                        value = self.evaluate_expression(arg, scope_name)

                        output += str(value)

                    if j + 1 < len(parts) and parts[j+1] == ',':

                        output += " "

                if print_str.strip().endswith(';'):

                    print(output, end='')

                else:

                    print(output)

                return None


            if command_upper.startswith("INPUT"):

                match = re.match(r"INPUT\s+\"(.+)\"?,\s*(\w+)", command, re.IGNORECASE)

                if match:

                    prompt, var_name = match.groups()

                    if prompt:

                        value = input(prompt + " ")

                    else:

                        value = input("> ")

                    self.current_scope()[var_name] = value

                    return None

                else:

                    raise Exception("INPUT komutunda sözdizimi hatası")


            if command_upper.startswith("LINE INPUT"):

                match = re.match(r"LINE INPUT\s+\"(.+)\"?,\s*(\w+)", command, re.IGNORECASE)

                if match:

                    prompt, var_name = match.groups()

                    if prompt:

                        value = input(prompt + " ")

                    else:

                        value = input("> ")

                    self.current_scope()[var_name] = value

                    return None

                else:

                    raise Exception("LINE INPUT komutunda sözdizimi hatası")


            if command_upper.startswith("WRITE"):

                match = re.match(r"WRITE\s+(.+)", command, re.IGNORECASE)

                if match:

                    expr = match.group(1)

                    value = self.evaluate_expression(expr, scope_name)

                    print(f'"{value}"' if isinstance(value, str) else value)

                    return None

                else:

                    raise Exception("WRITE komutunda sözdizimi hatası")


            # Atama

            if re.match(r"\w+\s*=\s*.+", command, re.IGNORECASE):

                match = re.match(r"(\w+)\s*=\s*(.+)", command, re.IGNORECASE)

                if match:

                    var_name, expr = match.groups()

                    value = self.evaluate_expression(expr, scope_name)

                    if var_name in self.global_vars:

                        self.global_vars[var_name] = value

                    elif var_name in self.shared_vars and (scope_name in self.shared_vars[var_name] or not self.shared_vars[var_name]):

                        self.shared_vars[var_name] = value

                    elif var_name in self.current_scope():

                        self.current_scope()[var_name] = value

                    else:

                        raise Exception(f"Tanımlanmamış değişken: {var_name}")

                    return None


            # Alt Programlar

            if command_upper.startswith("GOTO"):

                match = re.match(r"GOTO\s+(\w+)", command, re.IGNORECASE)

                if match:

                    label = match.group(1)

                    if label in self.labels:

                        return self.labels[label]

                    else:

                        raise Exception(f"Etiket bulunamadı: {label}")

                else:

                    raise Exception("GOTO komutunda sözdizimi hatası")


            if command_upper.startswith("GOSUB"):

                match = re.match(r"GOSUB\s+(\w+)", command, re.IGNORECASE)

                if match:

                    label = match.group(1)

                    if label in self.labels:

                        self.call_stack.append(self.program_counter)

                        return self.labels[label]

                    else:

                        raise Exception(f"Etiket bulunamadı: {label}")

                else:

                    raise Exception("GOSUB komutunda sözdizimi hatası")


            if command_upper == "RETURN":

                if self.call_stack:

                    return self.call_stack.pop()

                else:

                    raise Exception("RETURN için eşleşen GOSUB bulunamadı")


            if command_upper.startswith("CALL"):

                match = re.match(r"CALL\s+(\w+)", command, re.IGNORECASE)

                if match:

                    sub_name = match.group(1)

                    if sub_name in self.subs:

                        self.call_stack.append(self.program_counter)

                        self.local_scopes.append({})

                        return self.subs[sub_name]

                    else:

                        raise Exception(f"Alt program bulunamadı: {sub_name}")

                else:

                    raise Exception("CALL komutunda sözdizimi hatası")


            # Fonksiyon Çağrısı

            if re.match(r"\w+\s*\(.+\)", command, re.IGNORECASE):

                match = re.match(r"(\w+)\s*\((.+)\)", command, re.IGNORECASE)

                if match:

                    func_name, args_str = match.groups()

                    if func_name in self.functions:

                        self.call_stack.append(self.program_counter)

                        self.local_scopes.append({})

                        return self.functions[func_name]

                    elif func_name in self.function_table:

                        args_tuple = self.evaluate_expression(f"({args_str})", scope_name)

                        return self.function_table[func_name](*args_tuple)

                    else:

                        raise Exception(f"Fonksiyon bulunamadı: {func_name}")

                else:

                    raise Exception("Fonksiyon çağrısında sözdizimi hatası")


            # Dosya İşlemleri

            if command_upper.startswith("OPEN"):

                if "FOR ISAM" not in command_upper:

                    match = re.match(r"OPEN\s+\"(.+)\"\s+FOR\s+(INPUT|OUTPUT|APPEND|BINARY)\s+AS\s+#(\d+)", command, re.IGNORECASE)

                    if match:

                        file_path, mode, file_num = match.groups()

                        mode_map = {"INPUT": "r", "OUTPUT": "w", "APPEND": "a", "BINARY": "rb+"}

                        self.file_handles[int(file_num)] = open(file_path, mode_map[mode])

                        return None

                    else:

                        raise Exception("OPEN komutunda sözdizimi hatası")


            if command_upper.startswith("PRINT #"):

                match = re.match(r"PRINT\s+#(\d+),\s*(.+)", command, re.IGNORECASE)

                if match:

                    file_num, data = match.groups()

                    file = self.file_handles.get(int(file_num))

                    if file:

                        file.write(str(self.evaluate_expression(data, scope_name)) + "\n")

                        file.flush()

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("PRINT # komutunda sözdizimi hatası")


            if command_upper.startswith("INPUT #"):

                match = re.match(r"INPUT\s+#(\d+),\s*(\w+)", command, re.IGNORECASE)

                if match:

                    file_num, var_name = match.groups()

                    file = self.file_handles.get(int(file_num))

                    if file:

                        self.current_scope()[var_name] = file.readline().strip()

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("INPUT # komutunda sözdizimi hatası")


            if command_upper.startswith("LINE INPUT #"):

                match = re.match(r"LINE INPUT\s+#(\d+),\s*(\w+)", command, re.IGNORECASE)

                if match:

                    file_num, var_name = match.groups()

                    file = self.file_handles.get(int(file_num))

                    if file:

                        self.current_scope()[var_name] = file.readline().strip()

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("LINE INPUT # komutunda sözdizimi hatası")


            if command_upper.startswith("SEEK"):

                match = re.match(r"SEEK\s+#(\d+),\s*(.+)", command, re.IGNORECASE)

                if match:

                    file_num, position = match.groups()

                    file = self.file_handles.get(int(file_num))

                    if file:

                        file.seek(self.evaluate_expression(position, scope_name))

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("SEEK komutunda sözdizimi hatası")


            if command_upper.startswith("GET #"):

                match = re.match(r"GET\s+#(\d+),\s*(.+),\s*(\w+)", command, re.IGNORECASE)

                if match:

                    file_num, position, var_name = match.groups()

                    file = self.file_handles.get(int(file_num))

                    if file:

                        file.seek(self.evaluate_expression(position, scope_name))

                        self.current_scope()[var_name] = file.read(1)  # Basit okuma

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("GET # komutunda sözdizimi hatası")


            if command_upper.startswith("PUT #"):

                match = re.match(r"PUT\s+#(\d+),\s*(.+),\s*(.+)", command, re.IGNORECASE)

                if match:

                    file_num, position, data = match.groups()

                    file = self.file_handles.get(int(file_num))

                    if file:

                        file.seek(self.evaluate_expression(position, scope_name))

                        file.write(str(self.evaluate_expression(data, scope_name)))

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("PUT # komutunda sözdizimi hatası")


            if command_upper.startswith("CLOSE"):

                match = re.match(r"CLOSE\s+#(\d+)", command, re.IGNORECASE)

                if match:

                    file_num = match.group(1)

                    num = int(file_num)

                    if num in self.file_handles:

                        self.file_handles[num].close()

                        del self.file_handles[num]

                    elif num in self.db_connections:

                        self.db_connections[num].close()

                        del self.db_connections[num]

                    else:

                        raise Exception(f"Kapatılacak dosya #{file_num} bulunamadı")

                    return None

                else:

                    raise Exception("CLOSE komutunda sözdizimi hatası")


            if command_upper.startswith("KILL"):

                match = re.match(r"KILL\s+\"(.+)\"", command, re.IGNORECASE)

                if match:

                    file_name = match.group(1)

                    os.remove(file_name)

                    return None

                else:

                    raise Exception("KILL komutunda sözdizimi hatası")


            if command_upper.startswith("NAME"):

                match = re.match(r"NAME\s+\"(.+)\"\s+AS\s+\"(.+)\"", command, re.IGNORECASE)

                if match:

                    old_name, new_name = match.groups()

                    os.rename(old_name, new_name)

                    return None

                else:

                    raise Exception("NAME komutunda sözdizimi hatası")


            if command_upper.startswith("FILES"):

                match = re.match(r"FILES\s+\"(.+)\"", command, re.IGNORECASE)

                if match:

                    pattern = match.group(1)

                    print("\n".join(os.listdir(pattern)))

                    return None

                else:

                    raise Exception("FILES komutunda sözdizimi hatası")


            if command_upper.startswith("CHDIR"):

                match = re.match(r"CHDIR\s+\"(.+)\"", command, re.IGNORECASE)

                if match:

                    path = match.group(1)

                    os.chdir(path)

                    return None

                else:

                    raise Exception("CHDIR komutunda sözdizimi hatası")


            if command_upper.startswith("MKDIR"):

                match = re.match(r"MKDIR\s+\"(.+)\"", command, re.IGNORECASE)

                if match:

                    path = match.group(1)

                    os.mkdir(path)

                    return None

                else:

                    raise Exception("MKDIR komutunda sözdizimi hatası")


            if command_upper.startswith("RMDIR"):

                match = re.match(r"RMDIR\s+\"(.+)\"", command, re.IGNORECASE)

                if match:

                    path = match.group(1)

                    os.rmdir(path)

                    return None

                else:

                    raise Exception("RMDIR komutunda sözdizimi hatası")


            # Veritabanı İşlemleri

            if command_upper.startswith("OPEN") and "FOR ISAM" in command_upper:

                match = re.match(r"OPEN\s+\"(.+)\"\s+FOR\s+ISAM\s+AS\s+#(\d+)", command, re.IGNORECASE)

                if match:

                    db_file, file_num = match.groups()

                    conn = sqlite3.connect(db_file)

                    self.db_connections[int(file_num)] = conn

                    self.transaction_active[int(file_num)] = False

                    return None

                else:

                    raise Exception("OPEN FOR ISAM komutunda sözdizimi hatası")


            if command_upper.startswith("DEFINE TABLE"):

                match = re.match(r"DEFINE TABLE\s+(\w+)\s*\((.+)\)", command, re.IGNORECASE)

                if match:

                    table_name, fields = match.groups()

                    fields = [f.strip() for f in fields.split(",")]

                    columns = []

                    for field in fields:

                        match_field = re.match(r"(\w+)\s+AS\s+(\w+)(?:\s+CHECK\((.+)\))?", field, re.IGNORECASE)

                        if match_field:

                            col_name, col_type, constraint = match_field.groups()

                            sql_type = {"STRING": "TEXT", "INTEGER": "INTEGER", "DOUBLE": "REAL"}.get(col_type.upper(), "TEXT")

                            column_def = f"{col_name} {sql_type}"

                            if constraint:

                                column_def += f" CHECK({constraint})"

                            columns.append(column_def)

                        else:

                            raise Exception(f"Alan tanımı hatası: {field}")

                    sql = f"CREATE TABLE IF NOT EXISTS {table_name} ({', '.join(columns)})"

                    for conn in self.db_connections.values():

                        conn.execute(sql)

                        conn.commit()

                    return None

                else:

                    raise Exception("DEFINE TABLE komutunda sözdizimi hatası")


            if command_upper.startswith("PUT"):

                match = re.match(r"PUT\s+#(\d+),\s*(AUTOKEY|\w+),\s*(.+)", command, re.IGNORECASE)

                if match:

                    file_num, key, value = match.groups()

                    conn = self.db_connections.get(int(file_num))

                    if conn:

                        if key.upper() == "AUTOKEY":

                            conn.execute("INSERT INTO data (value) VALUES (?)", (value,))

                        else:

                            conn.execute("INSERT OR REPLACE INTO data (key, value) VALUES (?, ?)", (key, value))

                        if not self.transaction_active.get(int(file_num), False):

                            conn.commit()

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("PUT komutunda sözdizimi hatası")


            if command_upper.startswith("GET"):

                match = re.match(r"GET\s+#(\d+),\s*(\w+),\s*(\w+)", command, re.IGNORECASE)

                if match:

                    file_num, key, var_name = match.groups()

                    conn = self.db_connections.get(int(file_num))

                    if conn:

                        cursor = conn.execute("SELECT value FROM data WHERE key = ?", (key,))

                        result = cursor.fetchone()

                        self.current_scope()[var_name] = result[0] if result else None

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("GET komutunda sözdizimi hatası")


            if command_upper.startswith("DELETE"):

                match = re.match(r"DELETE\s+#(\d+),\s*(\w+)", command, re.IGNORECASE)

                if match:

                    file_num, key = match.groups()

                    conn = self.db_connections.get(int(file_num))

                    if conn:

                        conn.execute("DELETE FROM data WHERE key = ?", (key,))

                        if not self.transaction_active.get(int(file_num), False):

                            conn.commit()

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("DELETE komutunda sözdizimi hatası")


            if command_upper.startswith("SELECT"):

                match = re.match(r"SELECT\s+(.+)\s+FROM\s+(\w+)\s*(?:WHERE\s+(.+))?\s+INTO\s+(\w+)", command, re.IGNORECASE)

                if match:

                    columns, table, where, var_name = match.groups()

                    for num, conn in self.db_connections.items():

                        query = f"SELECT {columns} FROM {table}"

                        if where:

                            query += f" WHERE {where}"

                        df = pd.read_sql_query(query, conn)

                        self.current_scope()[var_name] = df

                        break

                    return None

                else:

                    raise Exception("SELECT komutunda sözdizimi hatası")


            if command_upper == "BEGIN TRANSACTION":

                match = re.match(r"BEGIN TRANSACTION\s+#(\d+)", command, re.IGNORECASE)

                if match:

                    file_num = int(match.group(1))

                    if file_num in self.db_connections:

                        self.transaction_active[file_num] = True

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("BEGIN TRANSACTION komutunda sözdizimi hatası")


            if command_upper == "COMMIT":

                match = re.match(r"COMMIT\s+#(\d+)", command, re.IGNORECASE)

                if match:

                    file_num = int(match.group(1))

                    if file_num in self.db_connections:

                        self.db_connections[file_num].commit()

                        self.transaction_active[file_num] = False

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("COMMIT komutunda sözdizimi hatası")


            if command_upper == "ROLLBACK":

                match = re.match(r"ROLLBACK\s+#(\d+)", command, re.IGNORECASE)

                if match:

                    file_num = int(match.group(1))

                    if file_num in self.db_connections:

                        self.db_connections[file_num].rollback()

                        self.transaction_active[file_num] = False

                    else:

                        raise Exception(f"Dosya #{file_num} açık değil")

                    return None

                else:

                    raise Exception("ROLLBACK komutunda sözdizimi hatası")


            if command_upper.startswith("INDEX"):

                match = re.match(r"INDEX\s+(\w+)\s+ON\s+(\w+)", command, re.IGNORECASE)

                if match:

                    table, column = match.groups()

                    for conn in self.db_connections.values():

                        conn.execute(f"CREATE INDEX idx_{column} ON {table} ({column})")

                        conn.commit()

                    return None

                else:

                    raise Exception("INDEX komutunda sözdizimi hatası")


            # Diğer Komutlar

            if command_upper.startswith("RANDOMIZE"):

                random.seed()

                return None


            if command_upper.startswith("READ"):

                match = re.match(r"READ\s+(\w+)", command, re.IGNORECASE)

                if match:

                    var_name = match.group(1)

                    if self.data_pointer < len(self.data_list):

                        self.current_scope()[var_name] = self.data_list[self.data_pointer]

                        self.data_pointer += 1

                    else:

                        raise Exception("DATA listesi tükendi")

                    return None

                else:

                    raise Exception("READ komutunda sözdizimi hatası")


            if command_upper.startswith("RESTORE"):

                self.data_pointer = 0

                return None


            if command_upper.startswith("LOAD"):

                match = re.match(r"LOAD\s+\"(.+)\"", command, re.IGNORECASE)

                if match:

                    file_name = match.group(1)

                    if file_name.endswith(".basX"):

                        self.load_program(file_name)

                        return 0

                    else:

                        raise Exception("Dosya uzantısı .basX olmalı")

                else:

                    raise Exception("LOAD komutunda sözdizimi hatası")


            if command_upper.startswith("SAVE"):

                match = re.match(r"SAVE\s+\"(.+)\"", command, re.IGNORECASE)

                if match:

                    file_name = match.group(1)

                    with open(file_name, "w") as f:

                        f.write("\n".join([line[0] for line in self.program]))

                    return None

                else:

                    raise Exception("SAVE komutunda sözdizimi hatası")


            if command_upper == "RUN":

                self.run()

                return None


            if command_upper == "END":

                self.running = False

                return None


            raise Exception(f"Bilinmeyen komut: {command}")

        except Exception as e:

            error_msg = f"PDSX Hatası: {str(e)}, Satır {self.program_counter + 1}"

            print(error_msg)

            logging.error(error_msg)

            if self.error_handler and self.debug_mode:

                print(f"Hata işleyicisine gidiliyor: {self.error_handler}")

            if self.error_handler:

                self.program_counter = self.error_handler

            else:

                self.running = False

            return None


    def load_program(self, file_name):

        try:

            with open(file_name, "r") as f:

                code = f.read()

            self.parse_program(code)

        except Exception as e:

            error_msg = f"Dosya yükleme hatası: {str(e)}"

            print(error_msg)

            logging.error(error_msg)


    def run(self):

        self.running = True

        self.program_counter = 0

        while self.running and self.program_counter < len(self.program):

            command, scope = self.program[self.program_counter]

            if self.debug_mode:

                print(f"Satır {self.program_counter + 1}: {command}")

                input("Devam etmek için Enter'a basın...")

            try:

                next_line = self.execute_command(command, scope)

                if next_line is not None:

                    self.program_counter = next_line

                else:

                    self.program_counter += 1

                if scope and self.program_counter < len(self.program) and self.program[self.program_counter][0].upper() in ("END SUB", "END FUNCTION"):

                    if self.call_stack:

                        self.local_scopes.pop()

                        self.program_counter = self.call_stack.pop()

                    else:

                        self.running = False

            except Exception as e:

                error_msg = f"Çalıştırma hatası: {str(e)}"

                print(error_msg)

                logging.error(error_msg)

                self.running = False

        for conn in self.db_connections.values():

            conn.close()

        for file in self.file_handles.values():

            file.close()


if __name__ == "__main__":

    parser = argparse.ArgumentParser(description="pdsX Interpreter")

    parser.add_argument("file", nargs='?', help="The .basX file to run")

    args = parser.parse_args()


    interpreter = pdsXInterpreter()


    if args.file:

        if args.file.endswith(".basX"):

            interpreter.load_program(args.file)

            interpreter.run()

        else:

            print("Hata: Dosya uzantısı .basX olmalı")

    else:

        print("Kullanım: pdsX dosya_adi.basX")

```

Bu program, bir BASIC diline (özellikle QBasic/QuickBASIC ve MS-DOS BASIC komutlarını) ilham alan, ancak Python ile implemente edilmiş **pdsX Interpreter**'dır. Bu yorumlar, her satırın ne yaptığını, sınıfların ve fonksiyonların amacını detaylıca açıklamaktadır. Yorumlar, kodun mantığını tamamen anlamak için yapılmıştır.


---


### 📜 **GENEL AÇIKLAMA: pdsXInterpreter Sınıfı**

Bu sınıf, bir **BASIC dili yorumlayıcısı** (interpreter) simüle etmektedir.  

- **Amacı:** `.basX` uzantılı dosyalarda yazılmış BASIC benzeri kodları okuyup, satır satır yorumlamak ve çalıştırmak.  

- **Temel Özellikler:** Değişken tanımlama (`DIM`, `GLOBAL`), alt programlar (`SUB`, `FUNCTION`), veritabanı işlemleri (`OPEN FOR ISAM`), dosya I/O, matematiksel fonksiyonlar, döngüler (`FOR`, `WHILE`, `DO...LOOP`), karar yapıları (`IF...THEN`, `SELECT CASE`), DATA/READ, hata yönetimi (`ON ERROR GOTO`) gibi temel BASIC özelliklerini destekler.  

- **Kullanım:** Python kütüphanelerini (`numpy`, `pandas`, `sqlite3`, `scipy`) kullanarak BASIC'in "fonksiyonel" davranışlarını taklit eder. Örneğin, `PRINT #1, x` komutu bir dosyaya yazarken, `SELECT ... INTO df` komutu bir SQLite tablosunu pandas DataFrame'e yükler.  

- **Yapı:** Kod, tek bir sınıf içinde tüm yorumlayıcı mantığını barındırır. Bu, basitlik ve entegrasyon sağlar ama genişletilebilirliği zorlaştırır.


---


## ✅ **SINIF: `pdsXInterpreter`**


```python

import re             # Regex: Metinleri parçalamak, komutları analiz etmek için gerekli (örn: "FOR i=1 TO 10" parse etmek)

import random         # Rastgele sayı üretmek için (RND fonksiyonu için)

import sqlite3        # Veritabanı (ISAM) işlemlerini gerçekleştirmek için (OPEN FOR ISAM, DEFINE TABLE, GET/PUT)

import numpy as np    # Matematiksel fonksiyonlar (SIN, COS, LOG, MEAN, STD, SUM vb.) ve ARRAY tipi için

import pandas as pd   # Veri çerçeveleri (DATAFRAME) ve SQL sorguları (SELECT ... INTO df) için

import scipy.stats as stats # İstatistiksel fonksiyonlar (CORR, TTEST, CHISQUARE, REGRESS vb.) için

from collections import defaultdict, namedtuple 

# defaultdict: SHARED değişkenler için (birden fazla kapsamda paylaşılabilir)

# namedtuple: TYPE tanımları için yapısal veri tipleri oluşturmak için (örn: TYPE Point AS (x AS INTEGER, y AS INTEGER))

from types import SimpleNamespace  # Kullanılmıyor gibi görünüyor, muhtemelen eski bir deneme

import os             # Dosya sistemi işlemleri (OPEN, CLOSE, KILL, NAME, FILES, CHDIR, MKDIR, RMDIR)

import logging        # Hata loglama için: interpreter_errors.log dosyasına hataları kaydeder

import time           # Zaman fonksiyonları (TIMER, DATE$, TIME$)

import sys            # Komut satırı argümanları (COMMAND$), program çalışırken sistem bilgileri için

import argparse       # Komut satırından .basX dosyası almak için (argparse.ArgumentParser)

import struct         # MKI$, MKS$, MKD$ fonksiyonları için byte paketleme/depaketleme (binary veri)


# Hata loglama için logging ayarı

logging.basicConfig(filename='interpreter_errors.log', level=logging.ERROR, format='%(asctime)s - %(message)s')

```


---


### 🔧 **`__init__` METODU: Sınıfın Kurulumu (Constructor)**


```python

class pdsXInterpreter:

    def __init__(self):

        # GLOBAL DEĞİŞKENLER: Program boyunca erişilebilir, her scope'da geçerli

        self.global_vars = {}  


        # DIM SHARED DEĞİŞKENLER: Birden fazla SUB/FUNCTION tarafından paylaşılan değişkenler.

        # Anahtar: değişken adı, Değer: hangi isimli scope'larda paylaşıldığı listesi (örn: ["MAIN", "SUB1"])

        self.shared_vars = defaultdict(list)  


        # YEREL KAPSAMLAR: SUB/FUNCTION çağrıldığında yeni bir scope açılır. Stack yapısı.

        # Her çağrıda son eleman ([-1]) geçerli scope'tur.

        self.local_scopes = [{}]  


        # TYPE TANIMLARI: STRUCT benzeri yapılar. namedtuple ile oluşturulur.

        # Örnek: TYPE Point AS (x AS INTEGER, y AS INTEGER) → self.types["Point"] = <namedtuple>

        self.types = {}  


        # CLASS TANIMLARI: OOP sınıf tanımı (sınırlı destek). Lambda metotlarla simüle edilir.

        # Örnek: CLASS MyClass ... END CLASS → self.classes["MyClass"] = <type object>

        self.classes = {}  


        # FUNCTION TANIMLARI: Tanımlanan kullanıcı fonksiyonlarının başlangıç satır numaraları

        # KEY: fonksiyon adı, VALUE: program listesindeki satır indeksi

        self.functions = {}  


        # SUB TANIMLARI: Alt programların başlangıç satır numaraları

        self.subs = {}  


        # ETİKETLER (LABEL): GOTO/GOSUB için kullanılan etiketlerin satır numaraları

        self.labels = {}  


        # PROGRAM SATIRLARI: Parse edilen tüm kod satırları. Tuple: (komut_str, scope_ismi)

        # Scope_ismi: Eğer bir SUB/FUNCTION içindese, o fonksiyonun adı, aksi halde None

        self.program = []  


        # PROGRAM SAYACI: Şu an yürütülen satırın indeksi

        self.program_counter = 0


        # ÇAĞRI YIĞINI (CALL STACK): GOSUB, CALL, FUNCTION çağrısında geri dönülmesi gereken adresi saklar

        self.call_stack = []  


        # YÜRÜTME DURUMU: True ise program çalışıyor, False ise durdu

        self.running = False


        # VERİTABANI BAĞLANTILARI: OPEN FOR ISAM komutuyla açılan SQLite bağlantıları

        # KEY: dosya numarası (#1, #2), VALUE: sqlite3.Connection nesnesi

        self.db_connections = {}  


        # DOSYA KOLLARI: OPEN komutuyla açılan dosya handle'ları

        # KEY: dosya numarası (#1, #2), VALUE: Python file nesnesi

        self.file_handles = {}  


        # HATA İŞLEYİCİSİ: ON ERROR GOTO ile belirlenen etiket satır numarası

        # Eğer hata oluşursa, program_counter bu değere atlanır

        self.error_handler = None  


        # DEBUG MODU: True ise her satırda input() ile durdurulur, debug çıktısı verilir

        self.debug_mode = False  


        # DÖNGÜ YIĞINI: DO...LOOP, WHILE...WEND, FOR...NEXT döngülerinin başlangıç noktalarını ve koşulları tutar

        self.loop_stack = []  


        # SELECT CASE YIĞINI: SELECT CASE bloklarının durumunu (değer, eşleşti mi?) tutar

        self.select_stack = []  


        # IF...THEN...ELSE YIĞINI: IF bloklarının durumunu (koşul sonucu, ELSE bulundu mu?) tutar

        self.if_stack = []  


        # DATA LİSTESİ: DATA komutlarıyla eklenen verilerin listesi

        # Örnek: DATA 10, "Hello", 3.14 → ["10", "Hello", "3.14"]

        self.data_list = []  


        # DATA İŞARETCİSİ: READ komutunda hangi veri okunacak olduğunu gösterir (sıfırdan başlar)

        self.data_pointer = 0  


        # TRANSAKSİYON DURUMLARI: OPEN FOR ISAM sonrası BEGIN TRANSACTION ile başlatılan işlemler

        # KEY: db dosya numarası, VALUE: bool (True = transaction aktif)

        self.transaction_active = {}  


        # VERİ TİPLERİ TABLOSU: BASIC veri tiplerini Python tiplerine eşler

        # Örnek: "INTEGER" → int, "STRING" → str, "ARRAY" → np.array, "DATAFRAME" → pd.DataFrame

        self.type_table = {  

            "STRING": str,

            "INTEGER": int,

            "LONG": int,

            "SINGLE": float,

            "DOUBLE": float,

            "BYTE": int,

            "SHORT": int,

            "UNSIGNED INTEGER": int,

            "CHAR": str,

            "LIST": list,

            "DICT": dict,

            "SET": set,

            "TUPLE": tuple,

            "ARRAY": np.array,

            "DATAFRAME": pd.DataFrame,

            "POINTER": None,  # Bellek adresi simülasyonu (gerçekleşmiyor)

            "STRUCT": dict,   # STRUCT: key-value olarak saklanır

            "UNION": None,    # Tek değer depolama (simülasyon yok)

            "ENUM": dict,     # Enum: sözlük olarak simüle edilebilir

            "VOID": None,

            "BITFIELD": int   # Bit operasyonları için (ancak uygulanmamış)

        }


        # FONKSİYON TABLOSU: Built-in fonksiyonlar ve onların Python karşılıkları

        # KEY: fonksiyon adı (örn: "MID$", "LEN"), VALUE: lambda veya referans fonksiyon

        # Bu fonksiyonlar, execute_command içinde eval() ile çağrılır.

        self.function_table = {

            "MID$": lambda s, start, length: s[start-1:start-1+length],  # BASIC MID$(str, start, len) → Python slicing

            "LEN": len,  # String uzunluğu

            "RND": random.random,  # 0.0 - 1.0 arası rastgele sayı

            "ABS": abs,

            "INT": int,  # Tam sayıya çevirir (yukarı yuvarlama değil!)

            "LEFT$": lambda s, n: s[:n],

            "RIGHT$": lambda s, n: s[-n:],

            "LTRIM$": lambda s: s.lstrip(),

            "RTRIM$": lambda s: s.rstrip(),

            "STRING$": lambda n, c: c * n,  # "A" * 5 → "AAAAA"

            "SPACE$": lambda n: " " * n,

            "INSTR": lambda start, s, sub: s.find(sub, start-1) + 1,  # 1-tabanlı indeks!

            "UCASE$": lambda s: s.upper(),

            "LCASE$": lambda s: s.lower(),

            "STR$": lambda n: str(n),

            "SQR": np.sqrt,

            "SIN": np.sin,

            "COS": np.cos,

            "TAN": np.tan,

            "LOG": np.log,

            "EXP": np.exp,

            "ATN": np.arctan,

            "FIX": lambda x: int(x),  # Ondalıklı kısmı keser

            "ROUND": lambda x, n=0: round(x, n),

            "SGN": lambda x: -1 if x < 0 else (1 if x > 0 else 0),

            "MOD": lambda x, y: x % y,

            "MIN": lambda *args: min(args),

            "MAX": lambda *args: max(args),

            "TIMER": lambda: time.time(),  # Unix zaman damgası (saniye)

            "DATE$": lambda: time.strftime("%m-%d-%Y"),

            "TIME$": lambda: time.strftime("%H:%M:%S"),

            "INKEY$": lambda: input()[:1],  # Klavyeden ilk karakteri okur (BASIC'te beklemeyen INKEY$)

            "ENVIRON$": lambda var: os.environ.get(var, ""),  # Ortam değişkeni okuma

            "COMMAND$": lambda: " ".join(sys.argv[1:]),  # Komut satırı argümanları

            "CSRLIN": lambda: 1,  # Ekran satırı konumu (simülasyon: hep 1)

            "POS": lambda x: 1,   # Ekran sütunu (simülasyon)

            "VAL": lambda s: float(s) if s.replace(".", "").isdigit() else 0,  # String→Sayı dönüşümü

            "ASC": lambda c: ord(c[0]),  # Karakterin ASCII değeri

            "MEAN": np.mean,

            "MEDIAN": np.median,

            "MODE": lambda x: stats.mode(x)[0][0],  # En çok tekrar eden değer

            "STD": np.std,

            "VAR": np.var,

            "SUM": np.sum,

            "PROD": np.prod,

            "PERCENTILE": np.percentile,

            "QUANTILE": np.quantile,

            "CORR": lambda x, y: np.corrcoef(x, y)[0, 1],  # Korelasyon katsayısı

            "COV": np.cov,  # Kovaryans matrisi döner

            "DESCRIBE": lambda df: df.describe(),  # Pandas describe()

            "GROUPBY": lambda df, col: df.groupby(col),

            "FILTER": lambda df, cond: df.query(cond),  # Pandas query ile filtreleme

            "SORT": lambda df, col: df.sort_values(col),

            "HEAD": lambda df, n=5: df.head(n),

            "TAIL": lambda df, n=5: df.tail(n),

            "MERGE": lambda df1, df2, on: pd.merge(df1, df2, on=on),

            "TTEST": lambda sample1, sample2: stats.ttest_ind(sample1, sample2),

            "CHISQUARE": lambda observed: stats.chisquare(observed),

            "ANOVA": lambda *groups: stats.f_oneway(*groups),

            "REGRESS": lambda x, y: stats.linregress(x, y),

            "EOF": lambda n: self.file_handles[n].eof(),  # Dosya sonu kontrolü (Python'da EOF yok, simülasyon eksik!)

            "LOC": lambda n: self.file_handles[n].tell(),  # Dosya imleci konumu

            "LOF": lambda n: os.path.getsize(self.file_handles[n].name),  # Dosya boyutu

            "FREEFILE": lambda: min(set(range(1, 100)) - set(self.file_handles.keys())),  # Kullanılmayan en küçük dosya numarası

            "CHR$": lambda n: chr(n),  # ASCII kodundan karakter

            "INPUT$": lambda n, f: self.file_handles[f].read(n),  # Dosyadan n bayt oku

            "MKI$": lambda n: struct.pack("i", n).decode('latin1'),  # 32-bit tamsayıyı stringe dönüştür

            "MKS$": lambda n: struct.pack("f", n).decode('latin1'),  # 32-bit float

            "MKD$": lambda n: struct.pack("d", n).decode('latin1')  # 64-bit double

        }

```


---


### 🔍 **`current_scope()` METODU: Geçerli Yerel Kapsamı Döndürür**


```python

    def current_scope(self):

        return self.local_scopes[-1]  # Yerel scope stack'inin en üstündeki (son) sözlüğü döndürür

```

> **Amacı:** `DIM`, `LET`, `READ` gibi komutlar için geçerli değişkenlerin bulunduğu kapsama erişim sağlar.  

> **Kullanımı:** `self.current_scope()[var_name] = value` şeklinde değişken atanır.  

> **Not:** `global_vars` ve `shared_vars` burada dahil değildir — ayrı işlem yapılır.


---


### 📚 **`parse_program(code)` METODU: Kodu Satır Satır Analiz Edip Program Listesine Çevirir**


```python

    def parse_program(self, code):

        self.program = []  # Önceki programı temizle

        current_sub = None          # Şu an işlenen SUB'un adı

        current_function = None     # Şu an işlenen FUNCTION'un adı

        current_type = None         # Şu an işlenen TYPE'nin adı

        current_class = None        # Şu an işlenen CLASS'ın adı

        type_fields = {}            # TYPE içindeki alanları saklar: {"Point": [("x", "INTEGER"), ("y", "INTEGER")]}

        class_methods = {}          # CLASS içindeki metotları saklar: {"MyClass": {"method1": lambda ...}}


        lines = code.split("\n")    # Kodu satırlara ayır

        i = 0                       # Satır indeksi

        while i < len(lines):

            line = lines[i].strip() # Boşlukları temizle

            if not line:            # Boş satır atla

                i += 1

                continue

            line_upper = line.upper()


            # SUB TANIMI: SUB Adı(...) → SUB'nin başlangıç satırını kaydet

            if line_upper.startswith("SUB "):

                sub_name = line[4:].split("(")[0].strip()  # "SUB MySub(a,b)" → "MySub"

                self.subs[sub_name] = i + 1               # Sonraki satırda kod başlar

                current_sub = sub_name                    # Artık SUB içindesin

                i += 1


            # FUNCTION TANIMI: FUNCTION Adı(...) → Fonksiyonun başlangıç satırını kaydet

            elif line_upper.startswith("FUNCTION "):

                func_name = line[8:].split("(")[0].strip()

                self.functions[func_name] = i + 1

                current_function = func_name

                i += 1


            # TYPE TANIMI: TYPE Point → Tipin adını kaydet

            elif line_upper.startswith("TYPE "):

                type_name = line[5:].strip()

                current_type = type_name

                type_fields[type_name] = []  # Alan listesini başlat

                i += 1


            # END TYPE: TYPE tanımının bitişi → namedtuple oluştur

            elif line_upper == "END TYPE":

                # namedtuple: (isim, alan_adları_listesi)

                field_names = [f[0] for f in type_fields[current_type]]  # ["x", "y"]

                self.types[current_type] = namedtuple(current_type, field_names)

                current_type = None

                i += 1


            # TYPE İÇİNDEKİ ALAN TANIMLARI: x AS INTEGER

            elif current_type:

                match = re.match(r"(\w+)\s+AS\s+(\w+)", line, re.IGNORECASE)

                if match:

                    field_name, field_type = match.groups()

                    type_fields[current_type].append((field_name, field_type))

                else:

                    raise Exception(f"TYPE tanımı hatası: {line}")

                i += 1


            # CLASS TANIMI: CLASS MyClass

            elif line_upper.startswith("CLASS "):

                class_name = line[6:].strip()

                current_class = class_name

                class_methods[class_name] = {}  # Boş metod listesi

                i += 1


            # END CLASS: Class tanımının bitişi

            elif line_upper.startswith("END CLASS"):

                # Dinamik olarak sınıf oluştur: type(class_name, (base,), methods_dict)

                class_def = type(current_class, (), {

                    **class_methods[current_class],  # Metodları ekle

                    '_vars': {},                     # İç değişkenler için boş bir sözlük

                    '__init__': lambda self: None   # Boş constructor

                })

                self.classes[current_class] = class_def

                current_class = None

                i += 1


            # CLASS İÇİNDEKİ SUB (METOT): SUB MethodName(...)

            elif current_class and line_upper.startswith("SUB "):

                method_name = line[4:].split("(")[0].strip()

                # Lambda: self._vars[method_name] fonksiyonunu çağırır (ama henüz atanmadı!)

                # Bu bir 'hata' içeriyor: Metot tanımı geçersiz çünkü lambda self._vars[method_name] çalışmaz!

                class_methods[current_class][method_name] = lambda self, *args: self._vars.get(method_name, lambda: None)(*args)

                i += 1


            # END SUB / END FUNCTION: SUB/FUNCTION bloğunun sonu

            elif line_upper == "END SUB" or line_upper == "END FUNCTION":

                current_sub = None

                current_function = None

                i += 1


            # ETİKET TANIMI: LABEL MyLabel

            elif line_upper.startswith("LABEL "):

                label_name = line[6:].strip()

                self.labels[label_name] = i  # Etiketin satır numarası

                i += 1


            # DATA KOMUTU: DATA 10, "abc", 3.14

            elif line_upper.startswith("DATA "):

                data_items = line[5:].split(",")

                self.data_list.extend([item.strip() for item in data_items])

                i += 1


            # GENEL KOMUTLAR: SUB/FUNCTION dışındaki satırlar

            else:

                if current_sub or current_function:

                    # SUB/FUNCTION içindeki satır: (satır, scope_ismi)

                    self.program.append((line, current_sub or current_function))

                else:

                    # Ana program satırı: (satır, None)

                    self.program.append((line, None))

                i += 1

```


> **⚠️ UYARI:** `CLASS` içindeki `SUB` metotlarının tanımı **yanlış**!  

> `lambda self, *args: self._vars.get(method_name, lambda: None)(*args)`  

> Burada `_vars[method_name]` hiçbir zaman atanmaz. Bu nedenle metotlar çalışmaz.  

> **Düzeltme önerisi:** `class_methods[current_class][method_name] = lambda self, *args: ...` yerine,  

> gerçek bir fonksiyon tanımı olmalı ve `__init__` içinde `self.method_name = ...` yapılmalı.


---


### 🧮 **`evaluate_expression(expr, scope_name=None)` METODU: İfadeyi Yorumlar ve Sonucu Döndürür**


```python

    def evaluate_expression(self, expr, scope_name=None):

        expr = expr.strip()

        namespace = {}  # Değişkenlerin ve fonksiyonların bulunduğu isim alanı


        # Global değişkenleri ekle

        namespace.update(self.global_vars)


        # Mevcut (yerel) scope değişkenlerini ekle

        namespace.update(self.current_scope())


        # SHARED değişkenleri ekle: scope_name ile eşleşenleri veya global shared olanları

        for var in self.shared_vars:

            if scope_name in self.shared_vars[var] or not self.shared_vars[var]:

                namespace[var] = self.shared_vars[var]


        # Built-in fonksiyonları ekle

        namespace.update(self.function_table)


        # Numpy, Pandas, Scipy modüllerini ekle (eval() içinde kullanabilmek için)

        namespace["np"] = np

        namespace["pd"] = pd

        namespace["stats"] = stats


        try:

            return eval(expr, namespace)  # Python'da ifadeyi dinamik olarak değerlendir

        except Exception as e:

            raise Exception(f"İfade değerlendirme hatası: {expr}, Hata: {str(e)}")

```


> **Amacı:** `"x + y * 2"`, `"RND() * 10"`, `"LEN(name)"`, `"SUM(array)"` gibi ifadeleri çalıştırır.  

> **Güvenlik:** `eval()` tehlikeli olabilir ama bu bir eğitim/deneysel yorumlayıcı olduğu için kabul edilmiştir.  

> **Scope Yönetimi:** `scope_name` parametresi, SUB/FUNCTION içindeki `SHARED` değişkenlerin doğru şekilde bağlanmasını sağlar.


---


### ⚙️ **`execute_command(command, scope_name=None)` METODU: Bir Komutu Yorumlar ve Çalıştırır**


Bu metot, programın kalbi. Her satır burada işlenir.  

**Her komut bloğu ayrı ayrı analiz edilmiştir.**


#### ❗ **HATA YÖNETİMİ (ON ERROR GOTO, RESUME)**


```python

        # Hata Yönetimi

        if command_upper.startswith("ON ERROR GOTO"):

            match = re.match(r"ON ERROR GOTO\s+(\w+)", command, re.IGNORECASE)

            if match:

                label = match.group(1)

                if label in self.labels:

                    self.error_handler = self.labels[label]  # Hata olduğunda bu satıra git

                else:

                    raise Exception(f"Etiket bulunamadı: {label}")

                return None

            else:

                raise Exception("ON ERROR GOTO komutunda sözdizimi hatası")

        if command_upper == "RESUME":

            if self.error_handler is not None:

                return self.error_handler  # Hata işlemeden sonra buraya dön

            else:

                raise Exception("RESUME için hata işleyicisi tanımlı değil")

```


#### 🔄 **DÖNGÜLER**


##### WHILE...WEND

```python

        if command_upper.startswith("WHILE"):

            match = re.match(r"WHILE\s+(.+)", command, re.IGNORECASE)

            if match:

                condition = match.group(1)

                self.loop_stack.append({

                    "start": self.program_counter,      # Döngünün başlangıç satırı

                    "type": "WHILE",

                    "condition": condition              # Koşul ifadesi

                })

                if not self.evaluate_expression(condition, scope_name):

                    # Koşul yanlışsa, WEND'e kadar atla

                    while self.program_counter < len(self.program) and \

                          self.program[self.program_counter][0].upper() != "WEND":

                        self.program_counter += 1

                return None

            else:

                raise Exception("WHILE komutunda sözdizimi hatası")

        if command_upper == "WEND":

            if self.loop_stack and self.loop_stack[-1]["type"] == "WHILE":

                loop_info = self.loop_stack[-1]

                if self.evaluate_expression(loop_info["condition"], scope_name):

                    return loop_info["start"]  # Başa dön

                else:

                    self.loop_stack.pop()      # Döngü bitti

                return None

            else:

                raise Exception("WEND için eşleşen WHILE bulunamadı")

```


##### FOR...NEXT

```python

        if command_upper.startswith("FOR"):

            match = re.match(r"FOR\s+(\w+)\s*=\s*(.+)\s+TO\s+(.+)(?:\s+STEP\s+(.+))?", command, re.IGNORECASE)

            if match:

                var_name, start_expr, end_expr, step_expr = match.groups()

                start = self.evaluate_expression(start_expr, scope_name)

                end = self.evaluate_expression(end_expr, scope_name)

                step = self.evaluate_expression(step_expr, scope_name) if step_expr else 1

                # Değişkeni mevcut scope'a ata

                if var_name in self.global_vars:

                    self.global_vars[var_name] = start

                else:

                    self.current_scope()[var_name] = start

                self.loop_stack.append({

                    "start": self.program_counter,

                    "type": "FOR",

                    "var": var_name,

                    "end": end,

                    "step": step

                })

                return None

            else:

                raise Exception("FOR komutunda sözdizimi hatası")


        if command_upper.startswith("NEXT"):

            if self.loop_stack and self.loop_stack[-1]["type"] == "FOR":

                loop_info = self.loop_stack[-1]

                var_name = loop_info["var"]

                current_value = self.global_vars.get(var_name, self.current_scope().get(var_name))

                current_value += loop_info["step"]

                if var_name in self.global_vars:

                    self.global_vars[var_name] = current_value

                else:

                    self.current_scope()[var_name] = current_value

                # Döngü şartı kontrolü

                if (loop_info["step"] > 0 and current_value <= loop_info["end"]) or \

                   (loop_info["step"] < 0 and current_value >= loop_info["end"]):

                    return loop_info["start"]  # Başa dön

                else:

                    self.loop_stack.pop()      # Döngü bitti

                return None

            else:

                raise Exception("NEXT için eşleşen FOR bulunamadı")

```


##### DO...LOOP

```python

        if command_upper.startswith("DO"):

            match = re.match(r"DO\s+(WHILE|UNTIL)?\s*(.+)?", command, re.IGNORECASE)

            if match:

                loop_type, condition = match.groups()

                self.loop_stack.append({

                    "start": self.program_counter,

                    "type": loop_type or "NONE",      # NONE: DO...LOOP sonsuz

                    "condition": condition or "True"  # Varsayılan koşul

                })

                return None

            else:

                raise Exception("DO komutunda sözdizimi hatası")


        if command_upper.startswith("LOOP"):

            match = re.match(r"LOOP\s+(WHILE|UNTIL)?\s*(.+)?", command, re.IGNORECASE)

            if match and self.loop_stack:

                loop_type, condition = match.groups()

                loop_info = self.loop_stack[-1]

                if loop_type and condition:

                    cond_result = self.evaluate_expression(condition, scope_name)

                    if (loop_type == "WHILE" and cond_result) or (loop_type == "UNTIL" and not cond_result):

                        return loop_info["start"]  # Koşul sağlanıyorsa dön

                    else:

                        self.loop_stack.pop()      # Döngü bitti

                elif loop_info["type"] == "WHILE":

                    if self.evaluate_expression(loop_info["condition"], scope_name):

                        return loop_info["start"]

                    else:

                        self.loop_stack.pop()

                elif loop_info["type"] == "UNTIL":

                    if not self.evaluate_expression(loop_info["condition"], scope_name):

                        return loop_info["start"]

                    else:

                        self.loop_stack.pop()

                else:

                    return loop_info["start"]      # DO...LOOP (sonsuz)

                return None

            else:

                raise Exception("LOOP için eşleşen DO bulunamadı")

```


#### 🧩 **SELECT CASE**

```python

        if command_upper.startswith("SELECT CASE"):

            match = re.match(r"SELECT CASE\s+(.+)", command, re.IGNORECASE)

            if match:

                expr = match.group(1)

                value = self.evaluate_expression(expr, scope_name)

                self.select_stack.append({"value": value, "matched": False, "start": self.program_counter})

                return None

            else:

                raise Exception("SELECT CASE komutunda sözdizimi hatası")


        if command_upper.startswith("CASE"):

            if not self.select_stack:

                raise Exception("CASE için eşleşen SELECT CASE bulunamadı")

            select_info = self.select_stack[-1]

            match = re.match(r"CASE\s+(.+)", command, re.IGNORECASE)

            if match:

                case_expr = match.group(1)

                if case_expr.upper() == "ELSE":

                    if not select_info["matched"]:

                        select_info["matched"] = True  # Else bloğuna gir

                    else:

                        # Zaten bir CASE matched, ELSE'yi atla

                        while self.program_counter < len(self.program) and \

                              self.program[self.program_counter][0].upper() != "END SELECT":

                            self.program_counter += 1

                else:

                    case_value = self.evaluate_expression(case_expr, scope_name)

                    if select_info["value"] == case_value and not select_info["matched"]:

                        select_info["matched"] = True  # Eşleşme bulundu

                    else:

                        # Eşleşme yoksa, CASE veya END SELECT'e kadar atla

                        while self.program_counter < len(self.program) and \

                              self.program[self.program_counter][0].upper() not in ("CASE", "END SELECT"):

                            self.program_counter += 1

                return None

            else:

                raise Exception("CASE komutunda sözdizimi hatası")


        if command_upper == "END SELECT":

            if self.select_stack:

                self.select_stack.pop()

                return None

            else:

                raise Exception("END SELECT için eşleşen SELECT CASE bulunamadı")

```


#### 🧭 **IF...THEN...ELSE...END IF**

```python

        if command_upper.startswith("IF"):

            match = re.match(r"IF\s+(.+)\s+THEN", command, re.IGNORECASE)

            if match:

                condition = match.group(1)

                cond_result = self.evaluate_expression(condition, scope_name)

                self.if_stack.append({"condition": cond_result, "start": self.program_counter, "else_found": False})

                if not cond_result:

                    # Koşul yanlışsa, ELSE veya END IF'e kadar atla

                    while self.program_counter < len(self.program) and \

                          self.program[self.program_counter][0].upper() not in ("ELSE", "END IF"):

                        self.program_counter += 1

                return None

            else:

                raise Exception("IF komutunda sözdizimi hatası")


        if command_upper == "ELSE":

            if not self.if_stack:

                raise Exception("ELSE için eşleşen IF bulunamadı")

            if_info = self.if_stack[-1]

            if if_info["condition"] or if_info["else_found"]:

                # IF doğruydu veya ELSE zaten göründü → END IF'e kadar atla

                while self.program_counter < len(self.program) and \

                      self.program[self.program_counter][0].upper() != "END IF":

                    self.program_counter += 1

            if_info["else_found"] = True  # ELSE bulundu

            return None


        if command_upper == "END IF":

            if self.if_stack:

                self.if_stack.pop()

                return None

            else:

                raise Exception("END IF için eşleşen IF bulunamadı")

```


#### 📦 **DEĞİŞKEN TANIMLAMA (DEFINT, DEFSNG, DEFDBL, DEFSTR, GLOBAL, DIM, DIM SHARED)**


```python

        if command_upper.startswith("DEFINT"):

            match = re.match(r"DEFINT\s+(\w+)", command, re.IGNORECASE)

            if match:

                var_name = match.group(1)

                self.current_scope()[var_name] = 0  # Integer varsayılan değeri

                return None

            else:

                raise Exception("DEFINT komutunda sözdizimi hatası")


        if command_upper.startswith("DEFSNG"):

            match = re.match(r"DEFSNG\s+(\w+)", command, re.IGNORECASE)

            if match:

                var_name = match.group(1)

                self.current_scope()[var_name] = 0.0  # Single

                return None

            else:

                raise Exception("DEFSNG komutunda sözdizimi hatası")


        if command_upper.startswith("DEFDBL"):

            match = re.match(r"DEFDBL\s+(\w+)", command, re.IGNORECASE)

            if match:

                var_name = match.group(1)

                self.current_scope()[var_name] = 0.0  # Double

                return None

            else:

                raise Exception("DEFDBL komutunda sözdizimi hatası")


        if command_upper.startswith("DEFSTR"):

            match = re.match(r"DEFSTR\s+(\w+)", command, re.IGNORECASE)

            if match:

                var_name = match.group(1)

                self.current_scope()[var_name] = ""   # String

                return None

            else:

                raise Exception("DEFSTR komutunda sözdizimi hatası")


        if command_upper.startswith("GLOBAL"):

            match = re.match(r"GLOBAL\s+(\w+)\s+AS\s+(\w+)", command, re.IGNORECASE)

            if match:

                var_name, var_type = match.groups()

                # Type_table'dan tipi al, örneğin "INTEGER" → int() → 0

                self.global_vars[var_name] = self.type_table.get(var_type, None)()

                return None

            else:

                raise Exception("GLOBAL komutunda sözdizimi hatası")


        if command_upper.startswith("DIM SHARED"):

            match = re.match(r"DIM SHARED\s+(.+)\s+AS\s+(\w+)", command, re.IGNORECASE)

            if match:

                scopes, var_type = match.groups()

                # Örnek: "DIM SHARED MAIN, SUB1, VARNAME AS INTEGER" → VARNAME şeffaf değişken

                var_name = scopes.split(",")[-1].strip()

                scope_list = [s.strip() for s in scopes.split(",")[:-1]]

                self.shared_vars[var_name] = scope_list  # Bu değişken bu scope'larda paylaşılır

                return None

            else:

                raise Exception("DIM SHARED komutunda sözdizimi hatası")


        if command_upper.startswith("DIM"):

            match = re.match(r"DIM\s+(\w+)\s+AS\s+(\w+)", command, re.IGNORECASE)

            if match:

                var_name, var_type = match.groups()

                if var_type in self.types:  # STRUCT/TYPE

                    # namedtuple örneğini oluştur

                    self.current_scope()[var_name] = self.types[var_type](*[None for _ in self.types[var_type]._fields])

                elif var_type in self.classes:  # CLASS instance

                    self.current_scope()[var_name] = self.classes[var_type]()

                elif var_type == "ARRAY":

                    self.current_scope()[var_name] = np.array([])

                elif var_type == "DATAFRAME":

                    self.current_scope()[var_name] = pd.DataFrame()

                elif var_type == "STRING":

                    self.current_scope()[var_name] = ""

                elif var_type in ("INTEGER", "LONG"):

                    self.current_scope()[var_name] = 0

                elif var_type in ("SINGLE", "DOUBLE"):

                    self.current_scope()[var_name] = 0.0

                elif var_type == "BYTE":

                    self.current_scope()[var_name] = 0

                elif var_type == "SHORT":

                    self.current_scope()[var_name] = 0

                elif var_type == "UNSIGNED INTEGER":

                    self.current_scope()[var_name] = 0

                elif var_type == "CHAR":

                    self.current_scope()[var_name] = ''

                elif var_type == "LIST":

                    self.current_scope()[var_name] = []

                elif var_type == "DICT":

                    self.current_scope()[var_name] = {}

                elif var_type == "SET":

                    self.current_scope()[var_name] = set()

                elif var_type == "TUPLE":

                    self.current_scope()[var_name] = ()

                else:

                    raise Exception(f"Tanımlanamayan veri tipi: {var_type}")

                return None

            else:

                raise Exception("DIM komutunda sözdizimi hatası")

```


#### 💬 **ATAMA VE DEĞİŞKEN YÖNETİMİ (LET, DEĞİŞKEN = İFADE)**


```python

        if command_upper.startswith("LET"):

            match = re.match(r"LET\s+(\w+)\s*=\s*(.+)", command, re.IGNORECASE)

            if match:

                var_name, expr = match.groups()

                value = self.evaluate_expression(expr, scope_name)

                if var_name in self.global_vars:

                    self.global_vars[var_name] = value

                elif var_name in self.shared_vars and (scope_name in self.shared_vars[var_name] or not self.shared_vars[var_name]):

                    self.shared_vars[var_name] = value

                elif var_name in self.current_scope():

                    self.current_scope()[var_name] = value

                else:

                    raise Exception(f"Tanımlanmamış değişken: {var_name}")

                return None

            else:

                raise Exception("LET komutunda sözdizimi hatası")


        # Direkt atama: x = 5

        if re.match(r"\w+\s*=\s*.+", command, re.IGNORECASE):

            match = re.match(r"(\w+)\s*=\s*(.+)", command, re.IGNORECASE)

            if match:

                var_name, expr = match.groups()

                value = self.evaluate_expression(expr, scope_name)

                if var_name in self.global_vars:

                    self.global_vars[var_name] = value

                elif var_name in self.shared_vars and (scope_name in self.shared_vars[var_name] or not self.shared_vars[var_name]):

                    self.shared_vars[var_name] = value

                elif var_name in self.current_scope():

                    self.current_scope()[var_name] = value

                else:

                    raise Exception(f"Tanımlanmamış değişken: {var_name}")

                return None

```


#### 🖨️ **GİRİŞ/ÇIKIŞ (PRINT, INPUT, LINE INPUT, WRITE)**


```python

        if command_upper.startswith("PRINT"):

            print_str = command[5:].strip()

            parts = re.split(r'([;,])', print_str)  # , ve ; ile böl

            output = ""

            for j in range(0, len(parts), 2):

                arg = parts[j].strip()

                if arg:

                    value = self.evaluate_expression(arg, scope_name)

                    output += str(value)

                if j + 1 < len(parts) and parts[j+1] == ',':

                    output += " "

            if print_str.strip().endswith(';'):

                print(output, end='')  # Satır sonu olmadan yaz

            else:

                print(output)  # Satır sonu ile yaz

            return None


        if command_upper.startswith("INPUT"):

            match = re.match(r"INPUT\s+\"(.+)\"?,\s*(\w+)", command, re.IGNORECASE)

            if match:

                prompt, var_name = match.groups()

                if prompt:

                    value = input(prompt + " ")

                else:

                    value = input("> ")

                self.current_scope()[var_name] = value

                return None

            else:

                raise Exception("INPUT komutunda sözdizimi hatası")


        if command_upper.startswith("LINE INPUT"):

            match = re.match(r"LINE INPUT\s+\"(.+)\"?,\s*(\w+)", command, re.IGNORECASE)

            if match:

                prompt, var_name = match.groups()

                if prompt:

                    value = input(prompt + " ")

                else:

                    value = input("> ")

                self.current_scope()[var_name] = value

                return None

            else:

                raise Exception("LINE INPUT komutunda sözdizimi hatası")


        if command_upper.startswith("WRITE"):

            match = re.match(r"WRITE\s+(.+)", command, re.IGNORECASE)

            if match:

                expr = match.group(1)

                value = self.evaluate_expression(expr, scope_name)

                # String ise çift tırnakla, değilse normal yaz

                print(f'"{value}"' if isinstance(value, str) else value)

                return None

            else:

                raise Exception("WRITE komutunda sözdizimi hatası")

```


#### 🔄 **ALT PROGRAMLAR (GOTO, GOSUB, RETURN, CALL)**


```python

        if command_upper.startswith("GOTO"):

            match = re.match(r"GOTO\s+(\w+)", command, re.IGNORECASE)

            if match:

                label = match.group(1)

                if label in self.labels:

                    return self.labels[label]  # Etikete git

                else:

                    raise Exception(f"Etiket bulunamadı: {label}")

            else:

                raise Exception("GOTO komutunda sözdizimi hatası")


        if command_upper.startswith("GOSUB"):

            match = re.match(r"GOSUB\s+(\w+)", command, re.IGNORECASE)

            if match:

                label = match.group(1)

                if label in self.labels:

                    self.call_stack.append(self.program_counter)  # Geri dönecek adres

                    return self.labels[label]                     # Etiket satırına git

                else:

                    raise Exception(f"Etiket bulunamadı: {label}")

            else:

                raise Exception("GOSUB komutunda sözdizimi hatası")


        if command_upper == "RETURN":

            if self.call_stack:

                return self.call_stack.pop()  # GOSUB'dan dönen adres

            else:

                raise Exception("RETURN için eşleşen GOSUB bulunamadı")


        if command_upper.startswith("CALL"):

            match = re.match(r"CALL\s+(\w+)", command, re.IGNORECASE)

            if match:

                sub_name = match.group(1)

                if sub_name in self.subs:

                    self.call_stack.append(self.program_counter)

                    self.local_scopes.append({})  # Yeni scope aç

                    return self.subs[sub_name]    # SUB'un başlangıç satırına git

                else:

                    raise Exception(f"Alt program bulunamadı: {sub_name}")

            else:

                raise Exception("CALL komutunda sözdizimi hatası")

```


#### 📌 **FONKSİYON ÇAĞRILARI (FUNC(...))**


```python

        if re.match(r"\w+\s*\(.+\)", command, re.IGNORECASE):

            match = re.match(r"(\w+)\s*\((.+)\)", command, re.IGNORECASE)

            if match:

                func_name, args_str = match.groups()

                if func_name in self.functions:

                    # Kullanıcı tanımlı fonksiyon

                    self.call_stack.append(self.program_counter)

                    self.local_scopes.append({})

                    return self.functions[func_name]  # Fonksiyonun başlangıç satırına git

                elif func_name in self.function_table:

                    # Built-in fonksiyon: "MID$("hello",1,3)" → eval("('hello',1,3)")

                    args_tuple = self.evaluate_expression(f"({args_str})", scope_name)

                    # args_tuple bir tuple olmalı: ('hello', 1, 3)

                    return self.function_table[func_name](*args_tuple)  # Fonksiyonu çağır ve sonucu döndür

                else:

                    raise Exception(f"Fonksiyon bulunamadı: {func_name}")

            else:

                raise Exception("Fonksiyon çağrısında sözdizimi hatası")

```


#### 📁 **DOSYA İŞLEMLERİ (OPEN, PRINT#, INPUT#, CLOSE, KILL, NAME, FILES, CHDIR, MKDIR, RMDIR)**


```python

        if command_upper.startswith("OPEN"):

            if "FOR ISAM" not in command_upper:

                match = re.match(r"OPEN\s+\"(.+)\"\s+FOR\s+(INPUT|OUTPUT|APPEND|BINARY)\s+AS\s+#(\d+)", command, re.IGNORECASE)

                if match:

                    file_path, mode, file_num = match.groups()

                    mode_map = {"INPUT": "r", "OUTPUT": "w", "APPEND": "a", "BINARY": "rb+"}

                    self.file_handles[int(file_num)] = open(file_path, mode_map[mode])

                    return None

                else:

                    raise Exception("OPEN komutunda sözdizimi hatası")


        if command_upper.startswith("PRINT #"):

            match = re.match(r"PRINT\s+#(\d+),\s*(.+)", command, re.IGNORECASE)

            if match:

                file_num, data = match.groups()

                file = self.file_handles.get(int(file_num))

                if file:

                    file.write(str(self.evaluate_expression(data, scope_name)) + "\n")

                    file.flush()  # Hemen yaz

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("PRINT # komutunda sözdizimi hatası")


        if command_upper.startswith("INPUT #"):

            match = re.match(r"INPUT\s+#(\d+),\s*(\w+)", command, re.IGNORECASE)

            if match:

                file_num, var_name = match.groups()

                file = self.file_handles.get(int(file_num))

                if file:

                    self.current_scope()[var_name] = file.readline().strip()

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("INPUT # komutunda sözdizimi hatası")


        if command_upper.startswith("LINE INPUT #"):

            # Aynı(INPUT #) ama tam satır okur

            match = re.match(r"LINE INPUT\s+#(\d+),\s*(\w+)", command, re.IGNORECASE)

            if match:

                file_num, var_name = match.groups()

                file = self.file_handles.get(int(file_num))

                if file:

                    self.current_scope()[var_name] = file.readline().strip()

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("LINE INPUT # komutunda sözdizimi hatası")


        if command_upper.startswith("SEEK"):

            match = re.match(r"SEEK\s+#(\d+),\s*(.+)", command, re.IGNORECASE)

            if match:

                file_num, position = match.groups()

                file = self.file_handles.get(int(file_num))

                if file:

                    file.seek(self.evaluate_expression(position, scope_name))

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("SEEK komutunda sözdizimi hatası")


        if command_upper.startswith("GET #"):

            match = re.match(r"GET\s+#(\d+),\s*(.+),\s*(\w+)", command, re.IGNORECASE)

            if match:

                file_num, position, var_name = match.groups()

                file = self.file_handles.get(int(file_num))

                if file:

                    file.seek(self.evaluate_expression(position, scope_name))

                    self.current_scope()[var_name] = file.read(1)  # Sadece 1 bayt oku

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("GET # komutunda sözdizimi hatası")


        if command_upper.startswith("PUT #"):

            match = re.match(r"PUT\s+#(\d+),\s*(.+),\s*(.+)", command, re.IGNORECASE)

            if match:

                file_num, position, data = match.groups()

                file = self.file_handles.get(int(file_num))

                if file:

                    file.seek(self.evaluate_expression(position, scope_name))

                    file.write(str(self.evaluate_expression(data, scope_name)))

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("PUT # komutunda sözdizimi hatası")


        if command_upper.startswith("CLOSE"):

            match = re.match(r"CLOSE\s+#(\d+)", command, re.IGNORECASE)

            if match:

                file_num = match.group(1)

                num = int(file_num)

                if num in self.file_handles:

                    self.file_handles[num].close()

                    del self.file_handles[num]

                elif num in self.db_connections:

                    self.db_connections[num].close()

                    del self.db_connections[num]

                else:

                    raise Exception(f"Kapatılacak dosya #{file_num} bulunamadı")

                return None

            else:

                raise Exception("CLOSE komutunda sözdizimi hatası")


        if command_upper.startswith("KILL"):

            match = re.match(r"KILL\s+\"(.+)\"", command, re.IGNORECASE)

            if match:

                file_name = match.group(1)

                os.remove(file_name)

                return None

            else:

                raise Exception("KILL komutunda sözdizimi hatası")


        if command_upper.startswith("NAME"):

            match = re.match(r"NAME\s+\"(.+)\"\s+AS\s+\"(.+)\"", command, re.IGNORECASE)

            if match:

                old_name, new_name = match.groups()

                os.rename(old_name, new_name)

                return None

            else:

                raise Exception("NAME komutunda sözdizimi hatası")


        if command_upper.startswith("FILES"):

            match = re.match(r"FILES\s+\"(.+)\"", command, re.IGNORECASE)

            if match:

                pattern = match.group(1)

                print("\n".join(os.listdir(pattern)))  # Belirtilen dizindeki dosyaları yazdır

                return None

            else:

                raise Exception("FILES komutunda sözdizimi hatası")


        if command_upper.startswith("CHDIR"):

            match = re.match(r"CHDIR\s+\"(.+)\"", command, re.IGNORECASE)

            if match:

                path = match.group(1)

                os.chdir(path)

                return None

            else:

                raise Exception("CHDIR komutunda sözdizimi hatası")


        if command_upper.startswith("MKDIR"):

            match = re.match(r"MKDIR\s+\"(.+)\"", command, re.IGNORECASE)

            if match:

                path = match.group(1)

                os.mkdir(path)

                return None

            else:

                raise Exception("MKDIR komutunda sözdizimi hatası")


        if command_upper.startswith("RMDIR"):

            match = re.match(r"RMDIR\s+\"(.+)\"", command, re.IGNORECASE)

            if match:

                path = match.group(1)

                os.rmdir(path)

                return None

            else:

                raise Exception("RMDIR komutunda sözdizimi hatası")

```


#### 🗄️ **VERİTABANI İŞLEMLERİ (OPEN FOR ISAM, DEFINE TABLE, GET, PUT, DELETE, SELECT, BEGIN TRANSACTION, COMMIT, ROLLBACK, INDEX)**


```python

        if command_upper.startswith("OPEN") and "FOR ISAM" in command_upper:

            match = re.match(r"OPEN\s+\"(.+)\"\s+FOR\s+ISAM\s+AS\s+#(\d+)", command, re.IGNORECASE)

            if match:

                db_file, file_num = match.groups()

                conn = sqlite3.connect(db_file)

                self.db_connections[int(file_num)] = conn

                self.transaction_active[int(file_num)] = False  # Başlangıçta transaksiyon kapalı

                return None

            else:

                raise Exception("OPEN FOR ISAM komutunda sözdizimi hatası")


        if command_upper.startswith("DEFINE TABLE"):

            match = re.match(r"DEFINE TABLE\s+(\w+)\s*\((.+)\)", command, re.IGNORECASE)

            if match:

                table_name, fields = match.groups()

                fields = [f.strip() for f in fields.split(",")]

                columns = []

                for field in fields:

                    match_field = re.match(r"(\w+)\s+AS\s+(\w+)(?:\s+CHECK\((.+)\))?", field, re.IGNORECASE)

                    if match_field:

                        col_name, col_type, constraint = match_field.groups()

                        sql_type = {"STRING": "TEXT", "INTEGER": "INTEGER", "DOUBLE": "REAL"}.get(col_type.upper(), "TEXT")

                        column_def = f"{col_name} {sql_type}"

                        if constraint:

                            column_def += f" CHECK({constraint})"

                        columns.append(column_def)

                    else:

                        raise Exception(f"Alan tanımı hatası: {field}")

                sql = f"CREATE TABLE IF NOT EXISTS {table_name} ({', '.join(columns)})"

                for conn in self.db_connections.values():  # Tüm bağlantılara uygula

                    conn.execute(sql)

                    conn.commit()

                return None

            else:

                raise Exception("DEFINE TABLE komutunda sözdizimi hatası")


        if command_upper.startswith("PUT"):

            match = re.match(r"PUT\s+#(\d+),\s*(AUTOKEY|\w+),\s*(.+)", command, re.IGNORECASE)

            if match:

                file_num, key, value = match.groups()

                conn = self.db_connections.get(int(file_num))

                if conn:

                    if key.upper() == "AUTOKEY":

                        conn.execute("INSERT INTO data (value) VALUES (?)", (value,))

                    else:

                        conn.execute("INSERT OR REPLACE INTO data (key, value) VALUES (?, ?)", (key, value))

                    if not self.transaction_active.get(int(file_num), False):

                        conn.commit()

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("PUT komutunda sözdizimi hatası")


        if command_upper.startswith("GET"):

            match = re.match(r"GET\s+#(\d+),\s*(\w+),\s*(\w+)", command, re.IGNORECASE)

            if match:

                file_num, key, var_name = match.groups()

                conn = self.db_connections.get(int(file_num))

                if conn:

                    cursor = conn.execute("SELECT value FROM data WHERE key = ?", (key,))

                    result = cursor.fetchone()

                    self.current_scope()[var_name] = result[0] if result else None

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("GET komutunda sözdizimi hatası")


        if command_upper.startswith("DELETE"):

            match = re.match(r"DELETE\s+#(\d+),\s*(\w+)", command, re.IGNORECASE)

            if match:

                file_num, key = match.groups()

                conn = self.db_connections.get(int(file_num))

                if conn:

                    conn.execute("DELETE FROM data WHERE key = ?", (key,))

                    if not self.transaction_active.get(int(file_num), False):

                        conn.commit()

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("DELETE komutunda sözdizimi hatası")


        if command_upper.startswith("SELECT"):

            match = re.match(r"SELECT\s+(.+)\s+FROM\s+(\w+)\s*(?:WHERE\s+(.+))?\s+INTO\s+(\w+)", command, re.IGNORECASE)

            if match:

                columns, table, where, var_name = match.groups()

                for num, conn in self.db_connections.items():

                    query = f"SELECT {columns} FROM {table}"

                    if where:

                        query += f" WHERE {where}"

                    df = pd.read_sql_query(query, conn)

                    self.current_scope()[var_name] = df

                    break

                return None

            else:

                raise Exception("SELECT komutunda sözdizimi hatası")


        if command_upper == "BEGIN TRANSACTION":

            match = re.match(r"BEGIN TRANSACTION\s+#(\d+)", command, re.IGNORECASE)

            if match:

                file_num = int(match.group(1))

                if file_num in self.db_connections:

                    self.transaction_active[file_num] = True

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("BEGIN TRANSACTION komutunda sözdizimi hatası")


        if command_upper == "COMMIT":

            match = re.match(r"COMMIT\s+#(\d+)", command, re.IGNORECASE)

            if match:

                file_num = int(match.group(1))

                if file_num in self.db_connections:

                    self.db_connections[file_num].commit()

                    self.transaction_active[file_num] = False

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("COMMIT komutunda sözdizimi hatası")


        if command_upper == "ROLLBACK":

            match = re.match(r"ROLLBACK\s+#(\d+)", command, re.IGNORECASE)

            if match:

                file_num = int(match.group(1))

                if file_num in self.db_connections:

                    self.db_connections[file_num].rollback()

                    self.transaction_active[file_num] = False

                else:

                    raise Exception(f"Dosya #{file_num} açık değil")

                return None

            else:

                raise Exception("ROLLBACK komutunda sözdizimi hatası")


        if command_upper.startswith("INDEX"):

            match = re.match(r"INDEX\s+(\w+)\s+ON\s+(\w+)", command, re.IGNORECASE)

            if match:

                table, column = match.groups()

                for conn in self.db_connections.values():

                    conn.execute(f"CREATE INDEX idx_{column} ON {table} ({column})")

                    conn.commit()

                return None

            else:

                raise Exception("INDEX komutunda sözdizimi hatası")

```


#### 🧠 **DİĞER KOMUTLAR (RANDOMIZE, READ, RESTORE, LOAD, SAVE, RUN, END)**


```python

        if command_upper.startswith("RANDOMIZE"):

            random.seed()  # Rastgele sayı üreticiyi sistem saatiyle başlat

            return None


        if command_upper.startswith("READ"):

            match = re.match(r"READ\s+(\w+)", command, re.IGNORECASE)

            if match:

                var_name = match.group(1)

                if self.data_pointer < len(self.data_list):

                    self.current_scope()[var_name] = self.data_list[self.data_pointer]

                    self.data_pointer += 1

                else:

                    raise Exception("DATA listesi tükendi")

                return None

            else:

                raise Exception("READ komutunda sözdizimi hatası")


        if command_upper.startswith("RESTORE"):

            self.data_pointer = 0  # DATA listesini baştan okumaya hazırla

            return None


        if command_upper.startswith("LOAD"):

            match = re.match(r"LOAD\s+\"(.+)\"", command, re.IGNORECASE)

            if match:

                file_name = match.group(1)

                if file_name.endswith(".basX"):

                    self.load_program(file_name)  # Yeni programı yükle

                    return 0  # Yeni programın ilk satırına git

                else:

                    raise Exception("Dosya uzantısı .basX olmalı")

            else:

                raise Exception("LOAD komutunda sözdizimi hatası")


        if command_upper.startswith("SAVE"):

            match = re.match(r"SAVE\s+\"(.+)\"", command, re.IGNORECASE)

            if match:

                file_name = match.group(1)

                with open(file_name, "w") as f:

                    f.write("\n".join([line[0] for line in self.program]))

                return None

            else:

                raise Exception("SAVE komutunda sözdizimi hatası")


        if command_upper == "RUN":

            self.run()  # Programı yeniden çalıştır

            return None


        if command_upper == "END":

            self.running = False  # Yürütme durdurulur

            return None

```


#### ⚠️ **GENEL HATA YÖNETİMİ**


```python

        raise Exception(f"Bilinmeyen komut: {command}")

```


> **Not:** Yukarıdaki tüm komutlar `try-except` bloğu içinde çağrılır. Eğer hata oluşursa:

> - Hata loglanır (`logging.error`)

> - Konsola yazılır

> - `error_handler` varsa, ona atlanır

> - Yoksa program sonlandırılır


---


### 🚀 **`load_program(file_name)` METODU: .basX Dosyasını Okur ve Parse Eder**


```python

    def load_program(self, file_name):

        try:

            with open(file_name, "r") as f:

                code = f.read()

            self.parse_program(code)  # Kodu parse et

        except Exception as e:

            error_msg = f"Dosya yükleme hatası: {str(e)}"

            print(error_msg)

            logging.error(error_msg)

```


> **Amacı:** `.basX` dosyasını okuyup, `parse_program` ile program listesine dönüştürür.


---


### ▶️ **`run()` METODU: Programı Yürütür**


```python

    def run(self):

        self.running = True

        self.program_counter = 0  # Satır sayacını sıfırla

        while self.running and self.program_counter < len(self.program):

            command, scope = self.program[self.program_counter]

            if self.debug_mode:

                print(f"Satır {self.program_counter + 1}: {command}")

                input("Devam etmek için Enter'a basın...")  # Debug modunda dur


            try:

                next_line = self.execute_command(command, scope)  # Komutu çalıştır

                if next_line is not None:

                    self.program_counter = next_line  # GOTO, GOSUB, LOOP gibi yönlendirme

                else:

                    self.program_counter += 1  # Normalde bir sonraki satır


                # SUB/FUNCTION sonu geldiyse, scope'u kapat ve geri dön

                if scope and self.program_counter < len(self.program) and self.program[self.program_counter][0].upper() in ("END SUB", "END FUNCTION"):

                    if self.call_stack:

                        self.local_scopes.pop()  # Yerel scope kapat

                        self.program_counter = self.call_stack.pop()  # GOSUB/CALL'dan dön

                    else:

                        self.running = False  # Hata durumu?

            except Exception as e:

                error_msg = f"Çalıştırma hatası: {str(e)}"

                print(error_msg)

                logging.error(error_msg)

                self.running = False  # Hata durumunda dur

        # Temizlik: Bağlantıları ve dosyaları kapat

        for conn in self.db_connections.values():

            conn.close()

        for file in self.file_handles.values():

            file.close()

```


> **Program döngüsü burada çalışır.**  

> `program_counter` her seferinde güncellenir.  

> `next_line` bir yönlendirme (goto, gosub, döngü başı) ise, `program_counter` ona atlanır.  

> `END` veya hata durumunda döngü sonlanır.


---


### 🎯 **ANA PROGRAM (main)**


```python

if __name__ == "__main__":

    parser = argparse.ArgumentParser(description="pdsX Interpreter")

    parser.add_argument("file", nargs='?', help="The .basX file to run")

    args = parser.parse_args()

    interpreter = pdsXInterpreter()

    if args.file:

        if args.file.endswith(".basX"):

            interpreter.load_program(args.file)

            interpreter.run()

        else:

            print("Hata: Dosya uzantısı .basX olmalı")

    else:

        print("Kullanım: pdsX dosya_adi.basX")

```


> **Komut satırından `.basX` dosyası verilirse**, program yüklenir ve çalıştırılır.  

> Aksi halde kullanım bilgisi verilir.


---


## ✅ **GENEL DEĞERLENDİRME: Güçlü ve Zayıf Yanlar**


### ✅ **GÜÇLÜ YANLAR**

- **Kapsamlı:** BASIC'in büyük bir kısmını (dosya, veritabanı, grafik simülasyonu, istatistik) destekler.

- **Modern Python teknolojileriyle entegre:** `numpy`, `pandas`, `sqlite3` kullanımı çok güçlü.

- **Yapısal:** `stack` kullanarak SCOPE, GOSUB, DÖNGÜ yönetimi akıllıca yapılmış.

- **Loglama ve hata yönetimi** profesyonel düzeyde.

- **Yorum satırları ve açıklama** çok iyi.


### ⚠️ **ZAYIF YANLAR / HATALAR**

1. **`CLASS` metotları çalışmaz!**  

   ```python

   class_methods[current_class][method_name] = lambda self, *args: self._vars.get(method_name, lambda: None)(*args)

   ```

   → `_vars[method_name]` hiçbir zaman atanmaz. Bu bir **bug**.  

   **Düzeltme:** Metotları doğrudan sınıfın `__dict__`'ine eklemeli veya `setattr` ile tanımlamalı.


2. **`EOF()` fonksiyonu** `self.file_handles[n].eof()` → Python'da `file.eof()` yoktur!  

   **Düzeltme:** `file.tell() >= os.path.getsize(file.name)` gibi bir kontrol yapılmalı.


3. **`INKEY$`** `input()[:1]` → Klavyeden bekler. Gerçek BASIC'te beklemez.  

   **Düzeltme:** `msvcrt.getch()` gibi platform-spesifik çözüm gerekir.


4. **`MKI$/MKS$/MKD$`** `decode('latin1')` → Binary veriyi stringe çevirir ama bu veri genellikle binary dosyalarda saklanır.  

   **Düzeltme:** `bytes` olarak saklamak daha doğru olur.


5. **`EXECUTE_COMMAND` çok uzun** → 700+ satır. Bölünmelidir (örneğin: `handle_loop`, `handle_files`, `handle_db`).


6. **`DATA` listesi global** → SUB/FUNCTION içinde `READ` kullandığında aynı listeyi kullanır. Bu doğru, ama dokümantasyon eksik.


---


## 🏁 SONUÇ


Bu program, **BASIC dilinin modern bir Python tabanlı simülasyonudur**.  

**Amaç:** Eğitim, eski BASIC kodlarını çalıştırmak, veya bir domain-specific language (DSL) geliştirmektir.  

**Geliştirme potansiyeli çok yüksek**, ancak bazı kritik hatalar düzeltildiğinde, gerçekten güçlü bir araç haline gelebilir.


> **Öneri:** Kodu modüller halinde bölmek (parser.py, executor.py, db.py, io.py),  

> `CLASS` sistemini düzeltmek,  

> `EOF`, `INKEY$`, `POKE`, `PEEK` gibi fonksiyonları tamamlamak,  

> `DEBUG` moduna `step into` desteği eklemek.


**İyi bir çalışma!** 👏


 

 

Yorumlar

Popüler Yayınlar