Full type checking for expression evaluation
authorNick Downing <nick@ndcode.org>
Sun, 15 May 2022 07:23:52 +0000 (17:23 +1000)
committerNick Downing <nick@ndcode.org>
Sun, 15 May 2022 07:23:52 +0000 (17:23 +1000)
applesoft_basic.t

index 2661a93..17315d8 100644 (file)
@@ -235,90 +235,128 @@ def evaluate(self, context):
   raise NotImplementedError()
 @method(NodeExpressionOr)
 def evaluate(self, context):
-  return float(
-    self.children[0].evaluate(context) != 0. or
-      self.children[1].evaluate(context) != 0.
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if not isinstance(value0, float) or not isinstance(value1, float):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return float(value0 != 0. or value1 != 0.)
 @method(NodeExpressionAnd)
 def evaluate(self, context):
-  return float(
-    self.children[0].evaluate(context) != 0. and
-      self.children[1].evaluate(context) != 0.
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if not isinstance(value0, float) or not isinstance(value1, float):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return float(value0 != 0. and value1 != 0.)
 @method(NodeExpressionLT)
 def evaluate(self, context):
-  return float(
-    self.children[0].evaluate(context) <
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if (
+    (not isinstance(value0, str) or not isinstance(value1, str)) and
+      (not isinstance(value0, float) or not isinstance(value1, float))
+  ):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return float(value0 < value1)
 @method(NodeExpressionEqual)
 def evaluate(self, context):
-  return float(
-    self.children[0].evaluate(context) ==
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if (
+    (not isinstance(value0, str) or not isinstance(value1, str)) and
+      (not isinstance(value0, float) or not isinstance(value1, float))
+  ):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return float(value0 == value1)
 @method(NodeExpressionGT)
 def evaluate(self, context):
-  return float(
-    self.children[0].evaluate(context) >
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if (
+    (not isinstance(value0, str) or not isinstance(value1, str)) and
+      (not isinstance(value0, float) or not isinstance(value1, float))
+  ):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return float(value0 > value1)
 @method(NodeExpressionGE)
 def evaluate(self, context):
-  return float(
-    self.children[0].evaluate(context) >=
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if (
+    (not isinstance(value0, str) or not isinstance(value1, str)) and
+      (not isinstance(value0, float) or not isinstance(value1, float))
+  ):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return float(value0 >= value1)
 @method(NodeExpressionLE)
 def evaluate(self, context):
-  return float(
-    self.children[0].evaluate(context) <=
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if (
+    (not isinstance(value0, str) or not isinstance(value1, str)) and
+      (not isinstance(value0, float) or not isinstance(value1, float))
+  ):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return float(value0 <= value1)
 @method(NodeExpressionNE)
 def evaluate(self, context):
-  return float(
-    self.children[0].evaluate(context) !=
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if (
+    (not isinstance(value0, str) or not isinstance(value1, str)) and
+      (not isinstance(value0, float) or not isinstance(value1, float))
+  ):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return float(value0 != value1)
 @method(NodeExpressionAdd)
 def evaluate(self, context):
-  return (
-    self.children[0].evaluate(context) +
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if (
+    (not isinstance(value0, str) or not isinstance(value1, str)) and
+      (not isinstance(value0, float) or not isinstance(value1, float))
+  ):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return value0 + value1
 @method(NodeExpressionSubtract)
 def evaluate(self, context):
-  return (
-    self.children[0].evaluate(context) -
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if not isinstance(value0, float) or not isinstance(value1, float):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return value0 - value1
 @method(NodeExpressionMultiply)
 def evaluate(self, context):
-  return (
-    self.children[0].evaluate(context) *
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if not isinstance(value0, float) or not isinstance(value1, float):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return value0 * value1
 @method(NodeExpressionDivide)
 def evaluate(self, context):
-  return (
-    self.children[0].evaluate(context) /
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if not isinstance(value0, float) or not isinstance(value1, float):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return value0 / value1
 @method(NodeExpressionPower)
 def evaluate(self, context):
-  return (
-    self.children[0].evaluate(context) **
-      self.children[1].evaluate(context)
-  )
+  value0 = self.children[0].evaluate(context)
+  value1 = self.children[1].evaluate(context)
+  if not isinstance(value0, float) or not isinstance(value1, float):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return value0 ** value1
 @method(NodeExpressionSign)
 def evaluate(self, context):
-  return self.sign * self.children[0].evaluate(context)
+  value = self.children[0].evaluate(context)
+  if not isinstance(value, float):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return self.sign * value
 @method(NodeExpressionNot)
 def evaluate(self, context):
-  return float(
-    self.children[0].evaluate(context) == 0.
-  )
+  value = self.children[0].evaluate(context)
+  if not isinstance(value, float):
+    raise Exception(f'?TYPE MISMATCH ERROR IN {context.line_number():d}')
+  return float(value == 0.)
 @method(NodeExpressionIntLiteral)
 def evaluate(self, context):
   return float(self.children[0].int_value)