def not_op(node: ASTNode): left = node.left if TypeChecker.isLooselyNumeric(left) or TypeChecker.isStrictlyBoolean( left): node.dataType = TypeChecker.BOOLEAN return Result(True) else: return Result(False, getUniaryOpTypeErr(node))
def add(node: ASTNode, _): isatLeastOneString = Types.isStrictlyString( node.left) or Types.isStrictlyString(node.right) if isatLeastOneString: node.value = str(node.left.value) + str(node.right.value) node.dataType = Types.STRING else: node.value = node.left.value + node.right.value node.dataType = Types.NUMERIC
def logical_op(node: ASTNode): left = node.left right = node.right valid = lambda node: TypeChecker.isStrictlyBoolean( node) or TypeChecker.isLooselyNumeric(node) if valid(left) and valid(right): node.dataType = TypeChecker.BOOLEAN return Result(True) else: return Result(False, getBinaryOpTypeErr(node))
def hybridAdd(node: ASTNode): left = node.left right = node.right validType = lambda node: TypeChecker.isStrictlyString( node) or TypeChecker.isLooselyNumeric(node) if validType(left) and validType(right): node.dataType = TypeChecker.NUMERIC if TypeChecker.isLooselyNumeric( left) and TypeChecker.isLooselyNumeric( right) else TypeChecker.STRING return Result(True) else: return Result(False, getBinaryOpTypeErr(node))
def strictArithmeticBinaryOp(node: ASTNode): """ Apply type system rules for '*', '/', '-', '^' :param node: :return: """ left = node.left right = node.right if TypeChecker.isLooselyNumeric(left) and TypeChecker.isLooselyNumeric( right): node.dataType = TypeChecker.NUMERIC return Result(True) else: return Result(False, getBinaryOpTypeErr(node))
def negate(node: ASTNode): left = node.left if TypeChecker.isLooselyNumeric(left): node.dataType = TypeChecker.NUMERIC return Result(True) else: return Result(False, getUniaryOpTypeErr(node))
def reverse_string(node: ASTNode): left = node.left if TypeChecker.isStrictlyString(left): node.dataType = TypeChecker.STRING return Result(True) else: return Result(False, getUniaryOpTypeErr(node))
def relationOp(node: ASTNode): left = node.left right = node.right if not TypeChecker.isEqual(left, right): return Result( False, f'incomparables types: {left.dataType} and {right.dataType}') else: node.dataType = TypeChecker.BOOLEAN return Result(True)
def array(node: ASTNode, _): if Types.isAtomic(node.left): node.left.value = [node.left.value] node.value = node.left.value node.value.append(node.right.value) isLooselyNumeric = lambda type: type == Types.NUMERICARRAY or type == Types.INTARRAY isNumericBool = lambda type: type == Types.INTARRAY or type == Types.NUMERICARRAY or type == Types.BOOLEANARRAY or type == Types.NUMERIC_BOOL_ARR if Types.isAtomic(node.left): ltype = Types.getArrayTypeBasedOnAtomic(node.left) else: ltype = node.left.dataType rtype = Types.getArrayTypeBasedOnAtomic(node.right) if ltype == rtype: node.dataType = ltype elif isLooselyNumeric(ltype) and isLooselyNumeric(rtype): node.dataType = Types.NUMERICARRAY elif isNumericBool(ltype) and isNumericBool(rtype): node.dataType = Types.NUMERIC_BOOL_ARR
def array_sep(node: ASTNode): left, right = node.left, node.right status, err = None, None isLooselyNumeric = lambda type: type == TypeChecker.NUMERICARRAY or type == TypeChecker.INTARRAY isNumericBool = lambda type: type == TypeChecker.INTARRAY or type == TypeChecker.NUMERICARRAY or type == TypeChecker.BOOLEANARRAY or type == TypeChecker.NUMERIC_BOOL_ARR if TypeChecker.isAtomic(left): ltype = TypeChecker.getArrayTypeBasedOnAtomic(left) else: ltype = left.dataType rtype = TypeChecker.getArrayTypeBasedOnAtomic(right) if ltype == rtype: node.dataType = ltype status = True elif isLooselyNumeric(ltype) and isLooselyNumeric(rtype): node.dataType = TypeChecker.NUMERICARRAY status = True elif isNumericBool(ltype) and isNumericBool(rtype): node.dataType = TypeChecker.NUMERIC_BOOL_ARR status = True else: status = False err = f"Array cannot hold different types: {TypeChecker.getAtomicTypeBasedOnArray(ltype)} and {TypeChecker.getAtomicTypeBasedOnArray(rtype)}" return Result(status, err)