Esoasm

From Esolang
Jump to navigation Jump to search

One thing that there is is a distinct lack of is C compilers to esolangs. People have made like ten million C compilers to x86, but not to esolangs. So, I made an assembly language designed to serve as a programming language that can easily be interpreted by a esolang with addressable memory but without free jumps (because you can’t directly implement functions without jumps) so that you can compile C to this assembly language, assemble it, and translate the binary into something that you can easily run in said esolang

Spec

SET
ADD
SUB
MUL
GETMEM
SETMEM
BRANCH
INPUT
OUTPUT
LABEL

Total of 14 op-codes

SET $1 10: var1 = 10; op code 0
SET $1 $2: var1 = var2; op code 1
ADD $1 10: var1 += 10; op code 2
ADD $1 $2: var1 += var2; op code 3
SUB $1 10: var1 -= 10; op code 4
SUB $1 $2: var1 -= var2; op code 5
MUL $1 10: var1 *= 10; op code 6
MUL $1 $2: var1 *= var 2; op code 7
GETMEM $1 $2: var1 = *var2; op code 8
SETMEM $1 $2: *var1 = var2; op code 9
BRANCH $1 %START: if (var1 >= 0){goto START;}; op code 10
BRANCH $1 $2: if (var1 >= 0){goto *var2;}; op code 11
INPUT $1: var1 = getchar(); op code 12
OUTPUT $1: putchar(var1); op code 13

LABEL START: create a label named START pointing to the next line by replaces each instance of %START in the code with the line number of the next line; no op code, because it is purely for the assembler

Assembler

Returns a list, filled with lists of the bytecode of each line.

function assemble(asm_code) {
  let bin_code = [];
  let lineNum = 0;
  let OPS = ["SET", "ADD", "SUB", "MUL", "GETMEM", "SETMEM", "BRANCH", "INPUT", "OUTPUT"];
  for (let line of asm_code.split("\n")) {
    let parts = line.split(" ");
    if (OPS.includes(parts[0])) {
      lineNum++;
    } else if (parts[0] == "LABEL") {
      asm_code = asm_code.split(`%${parts[1]}`).join(lineNum);
    }
  }
  for (let line of asm_code.split("\n")) {
    let nextLine = [-1, 0, 0];
    let parts = line.split(" ");
    if (parts[0] == "SET") {
      nextLine[0] = 0;
      nextLine[1] = parts[1].slice(1);
      nextLine[2] = parts[2];
      if (parts[2][0] == "$"){
        nextLine[0]++;
        nextLine[2] = parts[2].slice(1);
      }
    }
    else if (parts[0] == "ADD") {
      nextLine[0] = 2;
      nextLine[1] = parts[1].slice(1);
      nextLine[2] = parts[2];
      if (parts[2][0] == "$") {
        nextLine[0]++;
        nextLine[2] = parts[2].slice(1);
      }
    }
    else if (parts[0] == "SUB") {
      nextLine[0] = 4;
      nextLine[1] = parts[1].slice(1);
      nextLine[2] = parts[2];
      if (parts[2][0] == "$") {
        nextLine[0]++;
        nextLine[2] = parts[2].slice(1);
      }
    }
    else if (parts[0] == "MUL") {
      nextLine[0] = 6;
      nextLine[1] = parts[1].slice(1);
      nextLine[2] = parts[2];
      if (parts[2][0] == "$") {
        nextLine[0]++;
        nextLine[2] = parts[2].slice(1);
      }
    }
    else if (parts[0] == "GETMEM") {
      nextLine[0] = 8;
      nextLine[1] = parts[1].slice(1);
      nextLine[2] = parts[2].slice(1);
    }
    else if (parts[0] == "SETMEM") {
      nextLine[0] = 9;
      nextLine[1] = parts[1].slice(1);
      nextLine[2] = parts[2].slice(1);
    }
    else if (parts[0] == "BRANCH") {
      nextLine[0] = 10;
      nextLine[1] = parts[1].slice(1);
      nextLine[2] = parts[2];
      if (parts[2][0] == "$") {
        nextLine[0]++;
        nextLine[2] = parts[2].slice(1);
      }
    }
    else if (parts[0] == "INPUT") {
      nextLine[0] = 12;
      nextLine[1] = parts[1].slice(1);
    }
    else if (parts[0] == "OUTPUT") {
      nextLine[0] = 13;
      nextLine[1] = parts[1].slice(1);
    }
    if (nextLine[0]>=0) bin_code.push(nextLine);
  }
  return bin_code;
}

Esolang interpreters

(,)