From 1986463294063b9fbbcdea535f489b7dbff6db5a Mon Sep 17 00:00:00 2001
From: Vetle Larsen <vetlelarzen@gmail.com>
Date: Fri, 5 Apr 2024 13:49:36 +0200
Subject: [PATCH] Trying to run, but something doesnt work. Error at line 90 in
 typecheckvisitor

---
 index.ts                |   2 +
 package-lock.json       |   2 +-
 src/environment.ts      |   2 +
 src/evaluateVisitor.ts  | 112 ++++++++++++++++++++++-----
 src/interpreter.ts      |  12 +--
 src/parser.ts           | 167 +++++++++++++++++++++++++++++-----------
 src/typeCheckVisitor.ts |  40 ++++++----
 7 files changed, 255 insertions(+), 82 deletions(-)

diff --git a/index.ts b/index.ts
index 02d5694..f6dde36 100644
--- a/index.ts
+++ b/index.ts
@@ -20,3 +20,5 @@ function main() {
   }
 }
 main();
+
+//let blabla = b / f + g + 1[km/s];
diff --git a/package-lock.json b/package-lock.json
index 2abd3bc..d3fd99f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,5 @@
 {
-  "name": "INF222-Obligatory2-Skeleton",
+  "name": "inf-222-v-24-obligatory-2-skeleton",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
diff --git a/src/environment.ts b/src/environment.ts
index 7102d23..17864eb 100644
--- a/src/environment.ts
+++ b/src/environment.ts
@@ -15,11 +15,13 @@ function lookup<T>(x: string, env: Environment<T>): T | undefined {
 function isDefined<T>(x: string, env: Environment<T>): boolean {
   // 1. Return a Boolean value that represents whether an environment specified in parameter `x` has a variable specified in the parameter `x`.
   // TODO: YOUR CODE HERE // Hint: You can find which methods to use at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
+  return env.env.has(x);
 }
 
 function declare<T>(x: string, v: T, env: Environment<T>): void {
   // 1. Add a variable represented by the parameter `x` into the environment represented by the parameters `env`.
   // TODO: YOUR CODE HERE // Hint: You can find which methods to use at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
+  env.env.set(x, v);
 }
 
 export function newEnv<T>(): Environment<T> {
diff --git a/src/evaluateVisitor.ts b/src/evaluateVisitor.ts
index 13d0340..8961add 100644
--- a/src/evaluateVisitor.ts
+++ b/src/evaluateVisitor.ts
@@ -32,16 +32,16 @@ export class EvaluateVisitor implements AbstractVisitor {
         // 1.1.2. Visit the child `expr` of the node, and store the result in a variable.
         let expr = this.visit(node.expr);
         // 1.1.3. Add a variable and the stored evaluation result to the environment.
-        // TODO: YOUR CODE HERE
+        this.env.declare(node.assignee.name, expr, this.env);
         // 1.1.4. Return the stored evaluation result.
         return expr;
 
       // 1.2. If it is an identifier, then:
       case "Identifier":
         // 1.2.1. Cast the node to type `Identifier`.
-        // TODO: YOUR CODE HERE
+        node = node as Identifier;
         // 1.2.2. Lookup the value of the variable from the environment, and store that value in a variable.
-        let lookedUp = /* YOUR CODE HERE */;
+        let lookedUp = this.env.lookup(node.name, this.env);
         // 1.2.3. If the value is not undefined, then:
         if (lookedUp !== undefined) {
           // 1.2.3.1. Return the value.
@@ -53,13 +53,14 @@ export class EvaluateVisitor implements AbstractVisitor {
       // 1.3. If it is a group expression, then:
       case "GroupExpr":
         // 1.3.1. Cast the node to type `GroupExpr`.
+        node = node as GroupExpr;
         // 1.3.2. Return the result of visiting the child `subExpr` of the node.
-        // TODO: YOUR CODE HERE
+        this.visit(node.subExpr);
 
       // 1.4. If it is a measured number, then:
       case "MeasuredNumber":
         // 1.4.1. Cast the node to type `MeasuredNumber`.
-        // TODO: YOUR CODE HERE
+        node = node as MeasuredNumber;
         // 1.4.2. Depending on the physical unit of the node:
         switch (node.unit.value) {
           // 1.4.2.1. If it is grams:
@@ -73,16 +74,67 @@ export class EvaluateVisitor implements AbstractVisitor {
             };
           // 1.4.2.2. If it is kilograms:
           case "kg":
-            // TODO: YOUR CODE HERE
+            return {
+              value: node.numericalValue*1000,
+              unit: { ...node.unit, value: "g" },
+            };
           // 1.4.2.3. If it is hours:
           case "h":
-            // TODO: YOUR CODE HERE
+            return {
+              value: node.numericalValue*3600,
+              unit: { ...node.unit, value: "s" },
+            };
           // 1.4.2._. If it is ???what???:
-          case /* TODO: YOUR CODE HERE */:
-            // TODO: YOUR CODE HERE
-            
-          // TODO: YOUR CODE HERE FOR THE OTHER CASES
-            
+          case "min":
+            return {
+              value: node.numericalValue*60,
+              unit: { ...node.unit, value: "s" },
+            };
+          case "s":
+            return {
+              value: node.numericalValue,
+              unit: { ...node.unit, value: "s" },
+            }
+          case "m":
+            return {
+              value: node.numericalValue,
+              unit: { ...node.unit, value: "m" },
+            }
+          case "km":
+            return {
+              value: node.numericalValue*1000,
+              unit: { ...node.unit, value: "m" },
+            }
+          case "km/h":
+            return {
+              value: node.numericalValue/3.6,
+              unit: { ...node.unit, value: "m/s" },
+            }
+          case "km/s":
+            return {
+              value: node.numericalValue*1000,
+              unit: { ...node.unit, value: "m/s" },
+            }
+          case "km/min":
+            return {
+              value: node.numericalValue*16.6667,
+              unit: { ...node.unit, value: "m/s" },
+            }
+          case "m/h":
+            return {
+              value: node.numericalValue*0.277778,
+              unit: { ...node.unit, value: "m/s"},
+            }
+          case "m/s":
+            return {
+              value: node.numericalValue,
+              unit: { ...node.unit, value: "m/s" },
+            }
+          case "m/min":
+            return {
+              value: node.numericalValue*0.0166667,
+              unit: { ...node.unit, value: "m/s" },
+            }
           // 1.4.2.14. Otherwise:
           default:
             // 1.4.2.14.1. Throw an error.
@@ -92,25 +144,28 @@ export class EvaluateVisitor implements AbstractVisitor {
       // 1.5. If it is an addition-like expression, then:
       case "Additive":
         // 1.5.1. Cast the node to type `Additive`.
-        // TODO: YOUR CODE HERE
+        node = node as Additive;
         // 1.5.2. Visit the `left` child of this node, and store the result in a variable.
-        // TODO: YOUR CODE HERE
+        let left = this.visit(node.left)
         // 1.5.3. Visit the `right` child of this node, and store the result in a variable.
-        // TODO: YOUR CODE HERE
+        let right = this.visit(node.right)
         // 1.5.4. Depending on the `op` of this node:
         // 1.5.4.1. If it is `+`, then:
         if (node.op.value === "+") {
           // 1.5.4.1.1. Return an object that represents a value and a physical unit:
           return {
             // 1.5.4.1.1.1. The property `value` is the summation of the left and the right child of the node.
-            value: /* TODO: YOUR CODE HERE */,
+            value: left.value + right.value,
             // 1.5.4.1.1.2. The property `unit` is the unit of the left child of the node.
             // 1.5.4.1.1.2.1. Alternatively, it could have been the value of the right child of the node, as both of them have the same unit.
-            unit: additiveLeft.unit,
+            unit: left.unit,
           };
         // 1.5.4.2. Otherwise, if it is `-`, then:
         } else if (node.op.value === "-") {
-          // TODO: YOUR CODE HERE
+          return {
+            value: left.value - right.value,
+          unit: left.unit,
+          };
         }
         // 1.5.4.3. Otherwise, the operation should be prohibited, and an error is reported.
         else {
@@ -119,7 +174,26 @@ export class EvaluateVisitor implements AbstractVisitor {
 
       // 1.6. If it is a multiplication-like expression, then:
       case "Multiplicative":
-        // TODO: YOUR CODE HERE
+        node = node as Multiplicative;
+
+        let leftNode = this.visit(node.left);
+        let rightNode = this.visit(node.right);
+        
+        if (node.op.value === "*") {
+          return {
+            value: leftNode.value * rightNode.value,
+            unit: leftNode.unit,
+          };
+        }
+        else if (node.op.value === "/") {
+          return {
+            value: leftNode.value / rightNode.value,
+            unit: leftNode.unit,
+          };
+        }
+        else {
+          throw new Error("System failure");
+        }
         
       // 1.7. Otherwise:
       default:
diff --git a/src/interpreter.ts b/src/interpreter.ts
index ee575ed..db4174d 100644
--- a/src/interpreter.ts
+++ b/src/interpreter.ts
@@ -24,18 +24,20 @@ export function interpret(program: string): Environment<EvaluatedResult> {
   // 4.3. For each statement in the AST: 
   for (let statement of parsed) {
     // 4.3.1. Visit it using the typechecking visitor.
-    // TODO: YOUR CODE HERE
+    typeCheckVisitor.visit(statement);
   }
 
   // 5. Evaluate the AST.
   // 5.1. Initialize a new environment that will store _values_ of variables.
-  // TODO: YOUR CODE HERE
+  let valueCheckEnv = newEnv<EvaluatedResult>();
   // 5.2. Initialize an evaluating visitor.
-  // TODO: YOUR CODE HERE
+  let valueCheckVisitor = new EvaluateVisitor(valueCheckEnv);
   // 5.3. For each statement in the AST:
   // 5.3.1. Visit it using the evaluating visitor.
-  // TODO: YOUR CODE HERE
+  for (let statement of parsed) {
+    valueCheckVisitor.visit(statement);
+  } 
 
   // 6. Return the environment that stores the values of variables.
-  return /* TODO: YOUR CODE HERE */ ;
+  return valueCheckEnv ;
 }
diff --git a/src/parser.ts b/src/parser.ts
index 4d4ed82..2583851 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -37,12 +37,12 @@ export function parseProgram(tokens: Token[]): AstNode[] {
 
   function advance(): void {
     // 1. Increment the value of `currentPosition` by 1.
-    // TODO: YOUR CODE HERE
+    currentPosition++;
   }
 
   function peek() {
     // 1. Return the element of array `tokens` at a position immediately after the current position.
-    // TODO: YOUR CODE HERE
+    return tokens[currentPosition + 1];
   }
 
   function error() {
@@ -77,19 +77,31 @@ export function parseProgram(tokens: Token[]): AstNode[] {
     // 1.1.1. Advance the position of the parser.
     // 1.2. Otherwise, i.e., if it is not an equality sign, report an error. 
 
-    // TODO: YOUR CODE HERE
+    if (peek().kind === "Equals") {
+      advance();
+    }
+    else throw error();
   }
 
   function Semicolon(): void {
-    // TODO: YOUR CODE HERE
+    if (peek().kind === "Separator") {
+      advance();
+    }
+    else throw error();
   }
 
-  function /* TODO: YOUR CODE HERE */(): void {
-    // TODO: YOUR CODE HERE
+  function OpeningBracket(): void {
+    if (peek().kind === "OpeningBracket"){
+      advance();
+    }
+    else throw error();
   }
 
-  function /* TODO: YOUR CODE HERE */(): void {
-    // TODO: YOUR CODE HERE
+  function ClosingBracket(): void {
+    if (peek().kind === "ClosingBracket"){
+      advance();
+    }
+    else throw error();
   }
 
 
@@ -103,10 +115,13 @@ export function parseProgram(tokens: Token[]): AstNode[] {
     // 1.1. If it is a numeric literal, then:
     // 1.1.1. Advance the position of the parser.
     // 1.2. Otherwise, i.e., if it is not a numeric literal, report an error.
-    // TODO: YOUR CODE HERE
+    if (peek().kind === "Number"){
+      advance();
+    }
+    else throw error();
     
     // 2. Return the numerical value of the token.
-    return parseInt(/* TODO: YOUR CODE HERE */, 10);
+    return parseInt(getCurrentToken().value, 10);
   }
   
   function Identifier(): Identifier {
@@ -118,13 +133,13 @@ export function parseProgram(tokens: Token[]): AstNode[] {
       // 2.2. Return an object with two properties: `name` and `nodeType`.
       return {
         // 2.2.1. The property `name` should be the value of the current token.
-        // TODO: YOUR CODE HERE
+        name: getCurrentToken().value,
         // 2.2.2. The property `nodeType` should be `Identifier`.
         nodeType: "Identifier"
       };
     }
     // 3. Throw an error otherwise (i.e., if the kind of the peek'ed token is not `Identifier`.
-    throw error();
+    else throw error();
   }
 
   function PhysicalUnit(): PhysicalUnit {
@@ -142,30 +157,39 @@ export function parseProgram(tokens: Token[]): AstNode[] {
         // 3.1.2.1. Return an object with the following properties:
         return {
           // 3.1.2.1.1. Property `value` should be the value of the token, casted to type `Time`
-          // TODO: YOUR CODE HERE
+          value: unitValue as Time,
           // 3.1.2.1.2. Property `kind` should be `PhysicalUnitEnum.Time`
-          // TODO: YOUR CODE HERE
+          kind: PhysicalUnitEnum.Time,
           // 3.1.2.1.3. Property `nodeType` should be `PhysicalUnit`
-          // TODO: YOUR CODE HERE
+          nodeType: "PhysicalUnit"
         };
       // 3.1.3. Otherwise, if that value is one of the mass units, then:
-      } else if (/* TODO: YOUR CODE HERE */) {
+      } else if (["g", "kg"]) {
         // 3.1.3.1. Return an object with the following properties:
+        return {
         // 3.1.3.1.1. Property `value` should be the value of the token, casted to type `Mass`
+          value: unitValue as Mass,
         // 3.1.3.1.2. Property `kind` should be `PhysicalUnitEnum.Mass`
+          kind: PhysicalUnitEnum.Mass,
         // 3.1.3.1.3. Property `nodeType` should be `PhysicalUnit`
-
-        // TODO: YOUR CODE HERE
+          nodeType: "PhysicalUnit"
+        };
         
       // 3.1.4. Otherwise, if that value is one of the (???what???) units, then:
-      } else if (/* TODO: YOUR CODE HERE */) {
-        // TODO: YOUR CODE HERE
+      } else if (["m", "km"]) {
+        return {
+          value: unitValue as Distance,
+          kind: PhysicalUnitEnum.Distance,
+          nodeType: "PhysicalUnit"
+        }
       } 
       // 3.1.5. Otherwise, if that value is one of the (???what???) units, then:
-      else if (
-        // TODO: YOUR CODE HERE
-      ) {
-        // TODO: YOUR CODE HERE
+      else if (["km/h", "km/s", "km/min", "m/h", "m/s", "m/min"]) {
+        return {
+          value: unitValue as Velocity,
+          kind: PhysicalUnitEnum.Velocity,
+          nodeType: "PhysicalUnit"
+        }
       }
     }
     // 3.2. Otherwise, i.e., if the kind of the token is not `PhysicalUnit`, throw an error.
@@ -190,28 +214,35 @@ export function parseProgram(tokens: Token[]): AstNode[] {
     // 2. Expect an identifier, and store it in a variable.
     let assignee = Identifier();
     // 3. Expect an equality symbol `=`.
-    // TODO: YOUR CODE HERE
+    Equals();
     // 4. Expect an expression, and store it in a variable.
-    // TODO: YOUR CODE HERE
+    let expr = Expr();
     // 5. Expect a semicolon.
-    // TODO: YOUR CODE HERE
+    Semicolon();
     // 6. Return an AST node that represents an assignment statement -- it is an object with:
     return {
       // 6.1. A property that represents the assignee (i.e., the variable that has been assigned to).
       assignee,
       // 6.2. A property that represents the expression on the right-hand side of the assignment statement.
-      // TODO: YOUR CODE HERE
+      expr,
       // 6.3. A property `nodeType` which is (???what???).
-      // TODO: YOUR CODE HERE
+      nodeType : "AssignmentStatement"
     };
   }
 
   function Expr(): Expr {
-    // TODO: YOUR CODE HERE
+    return Additive();
   }
 
   function GroupExpr(): GroupExpr {
-    // TODO: YOUR CODE HERE
+    OpeningBracket();
+    let subExpr = Expr();
+    ClosingBracket();
+
+    return {
+      subExpr,
+      nodeType: "GroupExpr"
+    };
   }
 
   function PrimitiveExpr(): PrimitiveExpr {
@@ -227,10 +258,10 @@ export function parseProgram(tokens: Token[]): AstNode[] {
       case "Number":
         // 2.2.1. Expect a measured number.
         // 2.2.2. Return an AST node that represents it.
-        // TODO: YOUR CODE HERE
+        return MeasuredNumber();
       // 2.3. If it is a (???what???):
-      case /* TODO: YOUR CODE HERE */:
-        // TODO: YOUR CODE HERE
+      case "OpeningBracket":
+        return GroupExpr();
       // 2.4. Otherwise, if it is none of the above:
       default:
         // 2.4.1. Throw an error.
@@ -239,7 +270,14 @@ export function parseProgram(tokens: Token[]): AstNode[] {
   }
 
   function MeasuredNumber(): MeasuredNumber {
-    // TODO: YOUR CODE HERE
+    let numericalValue = NumericalLiteral();
+    let unit = PhysicalUnit();
+    
+    return {
+      numericalValue,
+      unit,
+      nodeType: "MeasuredNumber"
+    };
   }
 
   function OpAddSub(): Operator {
@@ -247,7 +285,7 @@ export function parseProgram(tokens: Token[]): AstNode[] {
     // 1.1. If it is either `+` or `-`, then:
     if (peek().kind == "OpAddSub") {
       // 1.1.1. Advance the position of the parser.
-      // TODO: YOUR CODE HERE
+      advance();
     }
     // 1.2. Otherwise, i.e., if it is not `+` or `-`, report an error.
     else throw error();
@@ -264,7 +302,10 @@ export function parseProgram(tokens: Token[]): AstNode[] {
         };
       // 2.2. If it is `-`, then:
       case "-":
-        // TODO: YOUR CODE HERE
+        return {
+          value: "-",
+          nodeType: "OpAddSub"
+        }
       // 2.3. Otherwise, i.e., if it is neither `+` nor `-`:
       default:
         // 2.3.1. Throw an error.
@@ -273,29 +314,58 @@ export function parseProgram(tokens: Token[]): AstNode[] {
   }
 
   function OpMulDiv(): Operator {
-    // TODO: YOUR CODE HERE
+    // 1. Peek the next input token.
+    // 1.1. If it is either `+` or `-`, then:
+    if (peek().kind == "OpMulDiv") {
+      // 1.1.1. Advance the position of the parser.
+      advance();
+    }
+    // 1.2. Otherwise, i.e., if it is not `+` or `-`, report an error.
+    else throw error();
+    // 2. Depending on the value of the token:
+    switch (getCurrentToken().value) {
+      // 2.1. If it is `+`, then:
+      case "*":
+        // 2.1.1. Return an AST node that represents an addition-like operator -- it is an object with:
+        return {
+          // 2.1.1.1. A property `value` which is `+`.
+          value: "*",
+          // 2.1.1.2. A property `nodeType` which is `OpAddSub`.
+          nodeType: "OpMulDiv"
+        };
+      // 2.2. If it is `-`, then:
+      case "/":
+        return {
+          value: "/",
+          nodeType: "OpMulDiv"
+        }
+      // 2.3. Otherwise, i.e., if it is neither `+` nor `-`:
+      default:
+        // 2.3.1. Throw an error.
+        throw error();
+    }
   }
 
   function Additive(): PrimitiveExpr | Multiplicative | Additive {
     // 1. Expect a multiplicative expression, and store it in a variable.
-    let left: PrimitiveExpr | Multiplicative | Additive = Multiplicative();
+    let left: PrimitiveExpr | Multiplicative | Additive = Multiplicative(); //May be a problem
     // 2. Emulate repetition in the grammar `{ ... }*` by peeking the next input token. See also item 2.2. below.
     // 2.1. Check whether that peek'ed token is `+` or `-`.
     while (peek().kind === "OpAddSub") {
       // 3. Expect (i.e., consume) that peek'ed token, and store it in a variable.
       let op = OpAddSub();
       // 4. Expect a multiplicative expression, and store it in a variable.
-      let right = /* TODO: YOUR CODE HERE */;
+      let right = Multiplicative();
       // 5. Update the expression stored in item 1. to be an AST node that represents an additive expression -- it is an object with: 
       left = {
         // 5.1. A property that represents the left operand of the multiplicative expression.
         left,
         // 5.2. A property that represents the operator of the multiplicative expression.
-        // TODO: YOUR CODE HERE
+        op,
         // 5.3. A property that represents the right operand of the multiplicative expression.
         right,
         // 5.4. A property `nodeType` which is (???what???).
-        nodeType: /* TODO: YOUR CODE HERE */,
+        nodeType: "Additive"
       };
     // 2.2. Make an iteration of the loop to process the possible remaining part of the addition-like expression.
     }
@@ -304,7 +374,18 @@ export function parseProgram(tokens: Token[]): AstNode[] {
   }
 
   function Multiplicative(): Multiplicative | PrimitiveExpr {
-    // TODO: YOUR CODE HERE
+    let left: Multiplicative | PrimitiveExpr = PrimitiveExpr(); //May be a problem
+    while (peek().kind === "OpMulDiv") {
+      let op = OpMulDiv();
+      let right = PrimitiveExpr();
+      left = {
+        left,
+        op,
+        right,
+        nodeType: "Multiplicative"
+      };
+    }
+    return left;
   }
 
 }
diff --git a/src/typeCheckVisitor.ts b/src/typeCheckVisitor.ts
index 7cf66bb..7d801fc 100644
--- a/src/typeCheckVisitor.ts
+++ b/src/typeCheckVisitor.ts
@@ -22,28 +22,32 @@ export class TypeCheckVisitor implements AbstractVisitor {
       // 1.1. If it is a measured number, then:
       case "MeasuredNumber":
         // 1.1.1. Cast the node to type `MeasuredNumber`.
-        // TODO: YOUR CODE HERE
+        node = node as MeasuredNumber;
         // 1.1.2. Return the physical unit of the node.
         return node.unit.kind;
 
       // 1.2. If it is a (???what???), then:
-      case /* TODO: YOUR CODE HERE */:
-        // TODO: YOUR CODE HERE
+      case "GroupExpr":
+        node = node as GroupExpr;
+        return this.visit(node.subExpr);
 
       // 1.3. If it is an assignment statement, then:
       case "AssignmentStatement":
-        // TODO: YOUR CODE HERE
+        node = node as Assignment;
+        let right = this.visit(node.expr);
+        this.env.declare(node.assignee.name, right, this.env);
+        return right;
 
       // 1.4. If it is an identifier, then:
       case "Identifier":
         // 1.4.1. Cast the node to type `Identifier`.
-        // TODO: YOUR CODE HERE
+        node = node as Identifier;
         // 1.4.2. Lookup the type (i.e., its physical unit) of the variable in the environment.
-        // TODO: YOUR CODE HERE
+        let fromEnv = this.env.lookup(node.name, this.env);
         // 1.4.3. If the looked up type is not undefined, then:
         if (fromEnv !== undefined) {
           // 1.4.3.1. Return the looked up type.
-          // TODO: YOUR CODE HERE
+          return fromEnv;
         } else {
           // 1.4.4. Otherwise, i.e., if the looked up type is undefined, then report an error.
           throw new Error("Variable " + node.name + " is not defined");
@@ -51,20 +55,23 @@ export class TypeCheckVisitor implements AbstractVisitor {
 
       // 1.5. If it is an addition-like expression, then:
       case "Additive": {
-        // TODO: YOUR CODE HERE
+        node = node as Additive;
+        return this.visit(node.left);
       }
 
       // 1.6. It it is a multiplication-like expression, then:
       case "Multiplicative": {        
-        // TODO: YOUR CODE HERE
-        
+        node = node as Multiplicative;
+
+        let left = this.visit(node.left);
+        let right = this.visit(node.right);
         // 1.6.4. Depending on the operation `op` of the node:
         // 1.6.4.1. If it is `*`, then:
         if (node.op.value === "*") {
           // 1.6.4.1.1. If the physical quantity of `left` is (???what???) and the physical quantity of `right` is (???what???), or vice versa, then:
-          if ( /** TODO: YOUR CODE HERE **/ ) {
+          if (left === PhysicalUnitEnum.Velocity && right === PhysicalUnitEnum.Time || left === PhysicalUnitEnum.Time && right === PhysicalUnitEnum.Velocity) {
             // 1.6.4.1.1.1. Return the physical unit representing length.
-            // TODO: YOUR CODE HERE
+            return PhysicalUnitEnum.Distance;
           } else {
             // 1.6.4.1.2. Otherwise, report an error.
             throw new Error(
@@ -76,8 +83,13 @@ export class TypeCheckVisitor implements AbstractVisitor {
           }
         // 1.6.4.2. Otherwise, if it is `/`, then:
         } else if (node.op.value === "/") {
-          // TODO: YOUR CODE HERE
-        }
+          if (left === PhysicalUnitEnum.Distance && right === PhysicalUnitEnum.Time) {
+            return PhysicalUnitEnum.Velocity;
+          }
+          if (right === 0) {
+            throw new Error("Division by zero");
+          }
+        } 
         // 1.6.4.3. Otherwise, if it any other operator, report an error.
         throw new Error("Failure!");
       }
-- 
GitLab