// hdgl_bin_interpreter.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>

#define LATTICE_PATH "/sys/kernel/hdgl_lattice/"
#define SLOT_COUNT 32
#define MAX_PROGRAM_LEN 1024

typedef enum { OP_NOP, OP_ADD, OP_MUL, OP_SET, OP_JMP, OP_JZ, OP_HALT } Opcode;

typedef struct {
    Opcode op;
    int a;
    int b;
    double val;
} Instruction;

// -------------------------
// Sysfs Lattice Access
// -------------------------
double read_slot(int idx) {
    char path[128], buf[64];
    snprintf(path,sizeof(path),"%sD%d",LATTICE_PATH,idx);
    FILE* f=fopen(path,"r");
    if(!f){ perror("fopen"); return 0; }
    if(!fgets(buf,sizeof(buf),f)){ fclose(f); return 0; }
    fclose(f);
    return atof(buf);
}

void write_slot(int idx, double val){
    char path[128], buf[64];
    snprintf(path,sizeof(path),"%sD%d",LATTICE_PATH,idx);
    FILE* f=fopen(path,"w");
    if(!f){ perror("fopen"); return; }
    snprintf(buf,sizeof(buf),"%lf\n",val);
    fputs(buf,f);
    fclose(f);
}

// -------------------------
// Lattice Operations
// -------------------------
void add_slot(int a,int b){ write_slot(a, read_slot(a)+read_slot(b)); }
void mul_slot(int a,double v){ write_slot(a, read_slot(a)*v); }
void set_slot(int a,double v){ write_slot(a,v); }

// -------------------------
// Program Loader
// -------------------------
int load_program(const char* filename, Instruction* program){
    FILE* f=fopen(filename,"r");
    if(!f){ perror("fopen"); return 0; }
    char line[128]; int idx=0;
    while(fgets(line,sizeof(line),f)){
        if(line[0]=='#' || strlen(line)<2) continue;
        Instruction inst={0,0,0,0};
        char cmd[16]; 
        if(sscanf(line,"%15s",cmd)!=1) continue;
        if(strcmp(cmd,"ADD")==0){ inst.op=OP_ADD; sscanf(line,"%*s D%d D%d",&inst.a,&inst.b); inst.a--; inst.b--; }
        else if(strcmp(cmd,"MUL")==0){ inst.op=OP_MUL; sscanf(line,"%*s D%d %lf",&inst.a,&inst.val); inst.a--; }
        else if(strcmp(cmd,"SET")==0){ inst.op=OP_SET; sscanf(line,"%*s D%d %lf",&inst.a,&inst.val); inst.a--; }
        else if(strcmp(cmd,"JMP")==0){ inst.op=OP_JMP; sscanf(line,"%*s %d",&inst.a); }
        else if(strcmp(cmd,"JZ")==0){ inst.op=OP_JZ; sscanf(line,"%*s D%d %d",&inst.a,&inst.b); inst.a--; }
        else if(strcmp(cmd,"HALT")==0){ inst.op=OP_HALT; }
        program[idx++]=inst;
        if(idx>=MAX_PROGRAM_LEN) break;
    }
    fclose(f);
    return idx;
}

// -------------------------
// Interpreter
// -------------------------
void run_program(Instruction* program,int len){
    int ip=0;
    while(ip<len){
        Instruction inst=program[ip];
        switch(inst.op){
            case OP_NOP: ip++; break;
            case OP_ADD: add_slot(inst.a,inst.b); ip++; break;
            case OP_MUL: mul_slot(inst.a,inst.val); ip++; break;
            case OP_SET: set_slot(inst.a,inst.val); ip++; break;
            case OP_JMP: ip=inst.a; break;
            case OP_JZ: if(read_slot(inst.a)==0) ip=inst.b; else ip++; break;
            case OP_HALT: return;
        }
    }
}

// -------------------------
// REPL / Interactive
// -------------------------
void repl(){
    char cmd[256];
    Instruction program[MAX_PROGRAM_LEN];
    int prog_len=0;
    printf("HDGL Binary Interpreter REPL\nType 'help'.\n");
    while(1){
        printf("HDGL-NATIVE> ");
        if(!fgets(cmd,sizeof(cmd),stdin)) break;
        if(strncmp(cmd,"exit",4)==0) break;
        else if(strncmp(cmd,"help",4)==0){
            printf("Commands: load <file>, run, show, set Dn val, step <bf>, exit\n");
        }
        else if(strncmp(cmd,"show",4)==0){
            for(int i=1;i<=SLOT_COUNT;i++) printf("D%d: %lf\n",i,read_slot(i));
        }
        else if(strncmp(cmd,"load",4)==0){
            char fname[128];
            if(sscanf(cmd,"load %127s",fname)==1){
                prog_len=load_program(fname,program);
                printf("Program loaded: %d instructions\n",prog_len);
            }
        }
        else if(strncmp(cmd,"run",3)==0){
            if(prog_len>0) run_program(program,prog_len);
        }
        else if(strncmp(cmd,"set",3)==0){
            int idx; double val;
            if(sscanf(cmd,"set D%d %lf",&idx,&val)==2) set_slot(idx,val);
        }
        else printf("Unknown command.\n");
    }
}

// -------------------------
// Main
// -------------------------
int main(){
    repl();
    return 0;
}
