From 1f40d69b16f6f7d8465781a8c59f6d3c0ba87a70 Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Sun, 15 May 2022 17:23:52 +1000 Subject: [PATCH] Full type checking for expression evaluation --- applesoft_basic.t | 150 +++++++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 56 deletions(-) diff --git a/applesoft_basic.t b/applesoft_basic.t index 2661a93..17315d8 100644 --- a/applesoft_basic.t +++ b/applesoft_basic.t @@ -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) -- 2.34.1