diff --git a/cpp-voxel-engine/imgui.ini b/cpp-voxel-engine/imgui.ini index 8833ca7..24a6ce8 100644 --- a/cpp-voxel-engine/imgui.ini +++ b/cpp-voxel-engine/imgui.ini @@ -5,6 +5,6 @@ Collapsed=0 [Window][Debug] Pos=12,41 -Size=336,392 +Size=778,630 Collapsed=0 diff --git a/python-c-interpriter/main.c b/python-c-interpriter/main.c new file mode 100644 index 0000000..8db617d --- /dev/null +++ b/python-c-interpriter/main.c @@ -0,0 +1,14 @@ +#include "other.h" + +void main() { + int a = 5; + printf("%d", a); + foo(); + int i = 10; + while (i != 0) + { + printf("%d", i); + i -= 1; + + } +} diff --git a/python-c-interpriter/main.py b/python-c-interpriter/main.py new file mode 100644 index 0000000..4564bfa --- /dev/null +++ b/python-c-interpriter/main.py @@ -0,0 +1,159 @@ +import sys +import os +import re + +# ──────── Interpreter State ──────── + +class Frame: + def __init__(self, function_name, locals=None): + self.function_name = function_name + self.locals = locals or {} + +class InterpreterState: + def __init__(self): + self.stack = [] # Call stack + self.functions = {} # name → AST + + def push_frame(self, name): + self.stack.append(Frame(name)) + + def pop_frame(self): + return self.stack.pop() + + def current_frame(self): + return self.stack[-1] if self.stack else None + + def debug_bt(self): + print("\nBacktrace:") + for i, frame in enumerate(reversed(self.stack)): + print(f" #{i} {frame.function_name}") + print() + + def debug_vars(self): + frame = self.current_frame() + print("\nVariables:") + if frame: + for k, v in frame.locals.items(): + print(f" {k} = {v}") + else: + print(" No active frame.") + print() + +# ──────── C Parser (toy) ──────── + +def parse_c_file(filename, included=None): + if included is None: + included = set() + + abs_path = os.path.abspath(filename) + if abs_path in included: + return {} + + included.add(abs_path) + + try: + with open(abs_path) as f: + lines = f.readlines() + except FileNotFoundError: + print(f"Error: File '{filename}' not found.") + return {} + + ast = {} + current_fn = None + body = [] + + for line in lines: + line = line.strip() + if line.startswith("#include"): + match = re.match(r'#include\s+"(.+?)"', line) + if match: + included_ast = parse_c_file(os.path.join(os.path.dirname(abs_path), match.group(1)), included) + ast.update(included_ast) + elif line.startswith("void"): + fn_match = re.match(r'void\s+(\w+)\s*\(\s*\)\s*{', line) + if fn_match: + if current_fn: + ast[current_fn] = body + body = [] + current_fn = fn_match.group(1) + elif line == "}": + if current_fn: + ast[current_fn] = body + current_fn = None + body = [] + elif re.match(r'int\s+\w+\s*=\s*\d+;', line): + var_match = re.match(r'int\s+(\w+)\s*=\s*(\d+);', line) + body.append(('decl', var_match.group(1), int(var_match.group(2)))) + elif re.match(r'printf\(".*",\s*\w+\);', line): + print_match = re.match(r'printf\(".*",\s*(\w+)\);', line) + body.append(('print', print_match.group(1))) + elif re.match(r'\w+\(\);', line): + call_match = re.match(r'(\w+)\(\);', line) + body.append(('call', call_match.group(1))) + return ast + +# ──────── Interpreter Executor ──────── + +class Interpreter: + def __init__(self, state): + self.state = state + + def run_function(self, name): + if name not in self.state.functions: + print(f"Function '{name}' not defined.") + return + self.state.push_frame(name) + body = self.state.functions[name] + for stmt in body: + self.exec_stmt(stmt) + self.state.pop_frame() + + def exec_stmt(self, stmt): + frame = self.state.current_frame() + if stmt[0] == 'decl': + _, var, val = stmt + frame.locals[var] = val + elif stmt[0] == 'print': + var = stmt[1] + print(frame.locals.get(var, 'undefined')) + elif stmt[0] == 'call': + self.run_function(stmt[1]) + +# ──────── Debugger CLI ──────── + +def debugger_loop(state, interp): + print("Mini C Interpreter Debugger") + print("Commands: run, bt, vars, quit") + while True: + cmd = input("(debug) ").strip() + if cmd == "run": + interp.run_function("main") + elif cmd == "bt": + state.debug_bt() + elif cmd == "vars": + state.debug_vars() + elif cmd == "quit": + break + else: + print("Unknown command. Use: run, bt, vars, quit") + +# ──────── Entry Point ──────── + +def main(): + if len(sys.argv) < 2: + print("Usage: python c_interpreter.py ") + return + + filename = sys.argv[1] + ast = parse_c_file(filename) + if not ast: + print("No functions parsed.") + return + + state = InterpreterState() + state.functions = ast + interp = Interpreter(state) + debugger_loop(state, interp) + +if __name__ == "__main__": + main() diff --git a/python-c-interpriter/other.h b/python-c-interpriter/other.h new file mode 100644 index 0000000..964484d --- /dev/null +++ b/python-c-interpriter/other.h @@ -0,0 +1,4 @@ +void foo() { + int x = 10; + printf("%d", x); +}