Преглед изворни кода

Add ability to create labels in icasm

Labels can now be set using a coder-defined string ending in a
semicolon. The label will be stored with the address of the next valid
opcode. In the next update, these labels will be able to be used for
jump instructions.
ApisNecros пре 1 месец
родитељ
комит
f0a9f46685
1 измењених фајлова са 43 додато и 7 уклоњено
  1. 43 7
      yaict

+ 43 - 7
yaict

@@ -14,10 +14,17 @@ let tape = [];
  * progress the pointer by one position.
  */
 let tapePointer = 0;
+/**
+ * A boolean value to determine whether a label is waiting to receive an address
+ */
+let labelStartActive = false;
 /**
  * A dictionary of labels and the line numbers they start at
  */
-const labelDictionary = {};
+const labelDictionary = {
+    /** Stores labels that haven't had their address found yet */
+    _toSet: undefined,
+};
 /**
  * A dictionary of variables created in the assembly
  */
@@ -61,11 +68,27 @@ const ASM_DICTIONARY = {
  */
 function transpileAssembly(assembly) {
     for (const line of assembly) {
-        const instruction = line.shift();
-        if (!ASM_DICTIONARY[instruction]) {
+        let instruction = line.shift();
+        // Check if the "instruction" is actually a label start
+        if (isLabelStart(instruction)) {
+            // Store the label in the dictionary, sans the colon
+            labelDictionary._toSet = instruction.substring(0, instruction.length -1);
+            labelStartActive = true;
+            
+            // If the line only contained the label start, continue to the next line
+            if (line.length == 0) { continue; }
+            // Otherwise, grab the next next string, which must be the instruction
+            instruction = line.shift();
+        }
+        else if (!ASM_DICTIONARY[instruction]) {
             throw new Error(`No function defined for the ${instruction} instruction.`);
         }
 
+        // If a label is waiting to be set, the tape pointer is currently where
+        // the next instruction is going to be put, so we can set the label's
+        // pointer here
+        setLabelStart();
+
         // Call the function for this instruction, and pass the rest of the line as parameters
         ASM_DICTIONARY[instruction](...line);
     }
@@ -213,15 +236,14 @@ function placeVariables() {
 }
 
 /**
- * Check if a given parameter is, or contains, a label
+ * Check if a given string matches a label start definition
  *
  * @param {string} parameter The parameter to check
  *
  * @returns {boolean}
  */
-function isLabel(parameter) {
-    const labelMatcher = new RegExp("\w+(?:\s*[+]\s*\d*)?");
-    return labelMatcher.test(parameter);
+function isLabelStart(parameter) {
+    return /^\w+:$/.test(parameter);
 }
 
 /**
@@ -281,6 +303,18 @@ function instructionNotYetImplemented(instruction) {
     throw new Error(`The ${instruction} instruction has not yet been implemented`);
 }
 
+/**
+ * Assigns a label waiting an address to the current pointer position
+ * 
+ * @returns {void}
+ */
+function setLabelStart() {
+    if (labelDictionary._toSet === undefined) { return };
+
+    labelDictionary[labelDictionary._toSet] = tapePointer;
+    labelDictionary._toSet = undefined;
+}
+
 /* MAIN FUNCTIONALITY */
 
 /**
@@ -315,6 +349,8 @@ function main() {
     transpileAssembly(ret);
 
     console.log("Parsed IntCode: ", tape.join(", "));
+
+    console.log("Labels:", labelDictionary);
 }
 
 main();