Selaa lähdekoodia

Add variables to assembly language

Variables can now be set using the `ld` instruction, and can then be
treated like any address on the tape. During the final step of the
transpilation, the calls to the variables will be replaced with their
actual address on the tape.
ApisNecros 3 viikkoa sitten
vanhempi
säilyke
219f0513ec
3 muutettua tiedostoa jossa 62 lisäystä ja 2 poistoa
  1. 5 0
      tests/addition-with-vars.icasm
  2. 8 0
      tests/jumps-with-variables.icasm
  3. 49 2
      yaict

+ 5 - 0
tests/addition-with-vars.icasm

@@ -0,0 +1,5 @@
+ld @op1, 10
+ld @op2, 37
+add @op2, @op1, 0d2
+add 0d2, 3, 0d12
+hlt

+ 8 - 0
tests/jumps-with-variables.icasm

@@ -0,0 +1,8 @@
+// Countdown from 15 to 0 by increments of 5
+ld @increment, -5
+ld @counter, 15
+jz @counter, 10
+add @increment, @counter, @counter
+jnz 1, 0
+out @counter
+hlt

+ 49 - 2
yaict

@@ -18,6 +18,10 @@ let tapePointer = 0;
  * A dictionary of labels and the line numbers they start at
  */
 const labelDictionary = {};
+/**
+ * A dictionary of variables created in the assembly
+ */
+const variableDictionary = {};
 /**
  * The dictionary of opcodes and their values
  */
@@ -66,6 +70,9 @@ function transpileAssembly(assembly) {
         ASM_DICTIONARY[instruction](...line);
     }
 
+    // Replace variables with address
+    placeVariables();
+
     // Clean the values on the tape
     tape = tape.map((inst) => strToDecimal(inst));
 }
@@ -79,7 +86,19 @@ function transpileAssembly(assembly) {
  * @param {number} value
  */
 function loadToAddress(address, value) {
-    tape[strToDecimal(address)] = value;
+    if (isVariable(address)) {
+        if (!variableDictionary[address]) {
+            variableDictionary[address] = {
+                value: value,
+                address: null,
+            };
+        } else {
+            variableDictionary[address]["value"] = value;
+        }
+    }
+    else {
+        tape[strToDecimal(address)] = value;
+    }
 }
 
 /**
@@ -178,6 +197,21 @@ function insertHalt() {
 
 /* HELPER FUNCTIONS */
 
+/**
+ * Places variables in the dictionary on the tape
+ * 
+ * Places the values loaded into variables at the end of the tape,
+ * and stores those addresses.
+ */
+function placeVariables() {
+    // move the tape pointer to the end of the tape
+    tapePointer = tape.length;
+    for (const variable of Object.keys(variableDictionary)) {
+        variableDictionary[variable]["address"] = ++tapePointer;
+        tape[tapePointer] = variableDictionary[variable]["value"];
+    }
+}
+
 /**
  * Check if a given parameter is, or contains, a label
  *
@@ -198,7 +232,18 @@ function isLabel(parameter) {
  * @returns {string} The memory address
  */
 function isAddress(parameter) {
-    return !!parameter.match(/^0d/);
+    return isVariable(parameter) || !!parameter.match(/^0d/);
+}
+
+/**
+ * Check if a parameter resembles a variable
+ *
+ * @param {any} parameter 
+ * @returns {boolean}
+ */
+function isVariable(parameter) {
+    if (typeof parameter != "string") { return false; }
+    return !!parameter.match(/^\@/);
 }
 
 /**
@@ -222,6 +267,8 @@ function strToDecimal(decimalValue) {
         return decimalValue;
     }
 
+    if (isVariable(decimalValue)) { return variableDictionary[decimalValue]["address"]; }
+
     return parseInt(decimalValue.replace(/^0d/, ""), 10);
 }