Skip to content

Commit

Permalink
making some lines a bit more compact
Browse files Browse the repository at this point in the history
  • Loading branch information
davecom committed Jun 4, 2024
1 parent 8ea3438 commit 01f5cb5
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 68 deletions.
2 changes: 1 addition & 1 deletion NanoBASIC/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
if __name__ == "__main__":
# Parse the file argument
file_parser = ArgumentParser("NanoBASIC")
file_parser.add_argument("basic_file", help="A text file containing NanoBASIC source code.")
file_parser.add_argument("basic_file", help="A text file containing NanoBASIC code.")
arguments = file_parser.parse_args()
execute(arguments.basic_file)
27 changes: 16 additions & 11 deletions NanoBASIC/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,17 @@ def interpret(self, statement: Statement):
if (line_index := self.find_line_index(go_to_line_id)) is not None:
self.statement_index = line_index
else:
raise Interpreter.InterpreterError("Couldn't find GOTO line id.", self.current)
raise Interpreter.InterpreterError("No GOTO line id.", self.current)
case GoSubStatement(line_expr=line_expr):
go_sub_line_id = self.evaluate_numeric(line_expr)
if (line_index := self.find_line_index(go_sub_line_id)) is not None:
self.subroutine_stack.append(self.statement_index + 1) # Setup for RETURN
self.statement_index = line_index
else:
raise Interpreter.InterpreterError("Couldn't find GOSUB line id.", self.current)
raise Interpreter.InterpreterError("No GOSUB line id.", self.current)
case ReturnStatement():
if not self.subroutine_stack: # Check if the stack is empty
raise Interpreter.InterpreterError("Return with no prior corresponding GOSUB.", self.current)
raise Interpreter.InterpreterError("RETURN without GOSUB.", self.current)
self.statement_index = self.subroutine_stack.pop()
case PrintStatement(printables=printables):
accumulated_string: str = ""
Expand All @@ -93,7 +93,7 @@ def interpret(self, statement: Statement):
accumulated_string += "\t"
if isinstance(printable, NumericExpression):
accumulated_string += str(self.evaluate_numeric(printable))
else: # Otherwise, it's a string, because that's the only other thing we allow
else: # Otherwise, it's a string
accumulated_string += str(printable)
print(accumulated_string)
self.statement_index += 1
Expand All @@ -103,7 +103,8 @@ def interpret(self, statement: Statement):
else:
self.statement_index += 1
case _:
raise Interpreter.InterpreterError(f"Unexpected item {self.current} in statement list.", self.current)
raise Interpreter.InterpreterError(f"Unexpected item {self.current} "
f"in statement list.", self.current)

def evaluate_numeric(self, numeric_expression: NumericExpression) -> int:
match numeric_expression:
Expand All @@ -113,12 +114,14 @@ def evaluate_numeric(self, numeric_expression: NumericExpression) -> int:
if name in self.variable_table:
return self.variable_table[name]
else:
raise Interpreter.InterpreterError(f"Var {name} used before initialized.", numeric_expression)
raise Interpreter.InterpreterError(f"Var {name} used "
f"before initialized.", numeric_expression)
case UnaryOperation(operator=operator, expr=expr):
if operator is TokenType.MINUS:
return -self.evaluate_numeric(expr)
else:
raise Interpreter.InterpreterError(f"Expected - but got {operator}.", numeric_expression)
raise Interpreter.InterpreterError(f"Expected - "
f"but got {operator}.", numeric_expression)
case BinaryOperation(operator=operator, left_expr=left, right_expr=right):
if operator is TokenType.PLUS:
return self.evaluate_numeric(left) + self.evaluate_numeric(right)
Expand All @@ -129,9 +132,11 @@ def evaluate_numeric(self, numeric_expression: NumericExpression) -> int:
elif operator is TokenType.DIVIDE:
return self.evaluate_numeric(left) // self.evaluate_numeric(right)
else:
raise Interpreter.InterpreterError(f"Unexpected binary operator {operator}.", numeric_expression)
raise Interpreter.InterpreterError(f"Unexpected binary operator "
f"{operator}.", numeric_expression)
case _:
raise Interpreter.InterpreterError("Expected numeric expression.", numeric_expression)
raise Interpreter.InterpreterError("Expected numeric expression.",
numeric_expression)

def evaluate_boolean(self, boolean_expression: BooleanExpression) -> bool:
left = self.evaluate_numeric(boolean_expression.left_expr)
Expand All @@ -150,5 +155,5 @@ def evaluate_boolean(self, boolean_expression: BooleanExpression) -> bool:
case TokenType.NOT_EQUAL:
return left != right
case _:
raise Interpreter.InterpreterError(f"Unexpected boolean operator {boolean_expression.operator}.",
boolean_expression)
raise Interpreter.InterpreterError(f"Unexpected boolean operator "
f"{boolean_expression.operator}.", boolean_expression)
40 changes: 21 additions & 19 deletions NanoBASIC/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def out_of_tokens(self) -> bool:
@property
def current(self) -> Token:
if self.out_of_tokens:
raise (Parser.ParserError(f"Ran out of tokens after {self.previous.kind}.", self.previous))
raise (Parser.ParserError(f"No tokens after {self.previous.kind}.", self.previous))
return self.tokens[self.token_index]

@property
Expand Down Expand Up @@ -107,8 +107,10 @@ def parse_print(self, line_id: int) -> PrintStatement:
printables.append(expression)
last_col = expression.col_end
else:
raise Parser.ParserError("Only strings and numeric expressions allowed in print list.", self.current)
if not self.out_of_tokens and self.current.kind is TokenType.COMMA: # Comma means there's more
raise Parser.ParserError("Only strings and numeric expressions "
"allowed in print list.", self.current)
# Comma means there's more to print
if not self.out_of_tokens and self.current.kind is TokenType.COMMA:
self.consume(TokenType.COMMA)
continue
break
Expand Down Expand Up @@ -168,8 +170,8 @@ def parse_boolean_expression(self) -> BooleanExpression:
return BooleanExpression(line_num=left.line_num,
col_start=left.col_start, col_end=right.col_end,
operator=operator.kind, left_expr=left, right_expr=right)
raise Parser.ParserError(f"Expected boolean operator inside boolean expression but found {self.current.kind}.",
self.current)
raise Parser.ParserError(f"Expected boolean operator but found "
f"{self.current.kind}.", self.current)

def parse_numeric_expression(self) -> NumericExpression:
left = self.parse_term()
Expand All @@ -180,15 +182,15 @@ def parse_numeric_expression(self) -> NumericExpression:
if self.current.kind is TokenType.PLUS:
self.consume(TokenType.PLUS)
right = self.parse_term()
left = BinaryOperation(line_num=left.line_num,
col_start=left.col_start, col_end=right.col_end,
operator=TokenType.PLUS, left_expr=left, right_expr=right)
left = BinaryOperation(line_num=left.line_num, col_start=left.col_start,
col_end=right.col_end, operator=TokenType.PLUS,
left_expr=left, right_expr=right)
elif self.current.kind is TokenType.MINUS:
self.consume(TokenType.MINUS)
right = self.parse_term()
left = BinaryOperation(line_num=left.line_num,
col_start=left.col_start, col_end=right.col_end,
operator=TokenType.MINUS, left_expr=left, right_expr=right)
left = BinaryOperation(line_num=left.line_num, col_start=left.col_start,
col_end=right.col_end, operator=TokenType.MINUS,
left_expr=left, right_expr=right)
else:
break # No more, must be end of expression
return left
Expand All @@ -202,15 +204,15 @@ def parse_term(self) -> NumericExpression:
if self.current.kind is TokenType.MULTIPLY:
self.consume(TokenType.MULTIPLY)
right = self.parse_factor()
left = BinaryOperation(line_num=left.line_num,
col_start=left.col_start, col_end=right.col_end,
operator=TokenType.MULTIPLY, left_expr=left, right_expr=right)
left = BinaryOperation(line_num=left.line_num, col_start=left.col_start,
col_end=right.col_end, operator=TokenType.MULTIPLY,
left_expr=left, right_expr=right)
elif self.current.kind is TokenType.DIVIDE:
self.consume(TokenType.DIVIDE)
right = self.parse_factor()
left = BinaryOperation(line_num=left.line_num,
col_start=left.col_start, col_end=right.col_end,
operator=TokenType.DIVIDE, left_expr=left, right_expr=right)
left = BinaryOperation(line_num=left.line_num, col_start=left.col_start,
col_end=right.col_end, operator=TokenType.DIVIDE,
left_expr=left, right_expr=right)
else:
break # No more, must be end of expression
return left
Expand All @@ -230,7 +232,7 @@ def parse_factor(self) -> NumericExpression:
self.consume(TokenType.OPEN_PAREN)
expression = self.parse_numeric_expression()
if self.current.kind is not TokenType.CLOSE_PAREN:
raise Parser.ParserError("Expected matching closing parenthesis.", self.current)
raise Parser.ParserError("Expected matching close parenthesis.", self.current)
self.consume(TokenType.CLOSE_PAREN)
return expression
elif self.current.kind is TokenType.MINUS:
Expand All @@ -239,4 +241,4 @@ def parse_factor(self) -> NumericExpression:
return UnaryOperation(line_num=minus.line_num,
col_start=minus.col_start, col_end=expression.col_end,
operator=TokenType.MINUS, expr=expression)
raise Parser.ParserError("Couldn't parse numeric expression, unexpected token.", self.current)
raise Parser.ParserError("Unexpected token in numeric expression.", self.current)
6 changes: 4 additions & 2 deletions NanoBASIC/tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def tokenize(text_file: TextIO) -> list[Token]:
if found:
col_end: int = col_start + found.end() - 1
# Store tokens other than comments and whitespace
if possibility is not TokenType.WHITESPACE and possibility is not TokenType.COMMENT:
if (possibility is not TokenType.WHITESPACE
and possibility is not TokenType.COMMENT):
associated_value: str | int | None = None
if possibility.has_associated_value:
if possibility is TokenType.NUMBER:
Expand All @@ -93,7 +94,8 @@ def tokenize(text_file: TextIO) -> list[Token]:
associated_value = found.group()
elif possibility is TokenType.STRING: # Remove quote characters
associated_value = found.group(0)[1:-1]
tokens.append(Token(possibility, line_num, col_start, col_end, associated_value))
tokens.append(Token(possibility, line_num, col_start, col_end,
associated_value))
# Continue search from place in line after token
line = line[found.end():]
col_start = col_end + 1
Expand Down
20 changes: 11 additions & 9 deletions RetroDither/macpaint.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

# Convert an array of bytes where each byte is 0 or 255
# to an array of bits where each byte that is 0 becomes a 1
# and each bit that is 255 becomes a 0
# and each byte that is 255 becomes a 0
def bytes_to_bits(original: array) -> array:
bits_array = array('B')

Expand Down Expand Up @@ -65,7 +65,8 @@ def run_length_encode(original_data: array) -> array:
# Find how many of the same bytes are in a row from *start*
def take_same(source: array, start: int) -> int:
count = 0
while start + count + 1 < len(source) and source[start + count] == source[start + count + 1]:
while (start + count + 1 < len(source)
and source[start + count] == source[start + count + 1]):
count += 1
return count + 1 if count > 0 else 0

Expand All @@ -76,7 +77,8 @@ def take_same(source: array, start: int) -> int:
index = 0
while index < len(data):
not_same = 0
while ((same := take_same(data, index + not_same)) == 0) and (index + not_same < len(data)):
while (((same := take_same(data, index + not_same)) == 0)
and (index + not_same < len(data))):
not_same += 1
if not_same > 0:
rle_data.append(not_same - 1)
Expand All @@ -92,13 +94,13 @@ def take_same(source: array, start: int) -> int:
def macbinary_header(outfile: str, data_size: int) -> array:
macbinary = array('B', [0] * MACBINARY_LENGTH)
filename = Path(outfile).stem
filename = filename[:63] if len(filename) > 63 else filename # limit to 63 characters maximum
filename = filename[:63] if len(filename) > 63 else filename # limit to 63 characters max
macbinary[1] = len(filename) # file name length
macbinary[2:(2 + len(filename))] = array("B", filename.encode("mac_roman")) # file name
macbinary[65:69] = array("B", "PNTG".encode("mac_roman")) # file type
macbinary[69:73] = array("B", "MPNT".encode("mac_roman")) # file creator
macbinary[83:87] = array("B", data_size.to_bytes(4, byteorder='big')) # size of data fork
timestamp = int((datetime.now() - datetime(1904, 1, 1)).total_seconds()) # Mac timestamps are seconds since 1904
timestamp = int((datetime.now() - datetime(1904, 1, 1)).total_seconds()) # Mac timestamp
macbinary[91:95] = array("B", timestamp.to_bytes(4, byteorder='big')) # creation stamp
macbinary[95:99] = array("B", timestamp.to_bytes(4, byteorder='big')) # modification stamp
return macbinary
Expand All @@ -109,15 +111,15 @@ def write_macpaint_file(data: array, out_file: str, width: int, height: int):
bits_array = prepare(data, width, height)
rle = run_length_encode(bits_array)
data_size = len(rle) + HEADER_LENGTH # header requires this
output_array = macbinary_header(out_file, data_size) + array('B', [0] * HEADER_LENGTH) + rle
output_array[MACBINARY_LENGTH + 3] = 2 # Data Fork Header Signature
output = macbinary_header(out_file, data_size) + array('B', [0] * HEADER_LENGTH) + rle
output[MACBINARY_LENGTH + 3] = 2 # Data Fork Header Signature
# macbinary format requires that there be padding of 0s up to a
# multiple of 128 bytes for the data fork
padding = 128 - (data_size % 128)
if padding > 0:
output_array += array('B', [0] * padding)
output += array('B', [0] * padding)
with open(out_file + ".bin", "wb") as fp:
output_array.tofile(fp)
output.tofile(fp)

# Alternative version of run_length_encode that doesn't use the helper function
# # https://en.wikipedia.org/wiki/PackBits
Expand Down
21 changes: 11 additions & 10 deletions StainedGlass/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,25 @@
if __name__ == "__main__":
# Parse the file argument
argument_parser = ArgumentParser("StainedGlass")
argument_parser.add_argument("image_file", help="An image file to paint a stained glass equivalent of.")
argument_parser.add_argument("image_file", help="The input image to be painted.")
argument_parser.add_argument("output_file", help="The final resulting abstract art image.")
argument_parser.add_argument('-t', '--trials', type=int, default=10000,
help='The number of trials to run (default 10000).')
argument_parser.add_argument('-m', '--method', choices=['random', 'average', 'common'], default='average',
help='The method for determining shape colors (default average).')
argument_parser.add_argument('-s', '--shape', choices=['ellipse', 'triangle', 'quadrilateral', 'line'],
default='ellipse',
argument_parser.add_argument('-m', '--method', choices=['random', 'average', 'common'],
default='average',
help='Shape color determination method (default average).')
argument_parser.add_argument('-s', '--shape', choices=['ellipse', 'triangle',
'quadrilateral', 'line'], default='ellipse',
help='The shape type to use (default ellipse).')
argument_parser.add_argument('-l', '--length', type=int, default=256,
help='The length (height) of the final image in pixels (default 256).')
help='The length of the final image in pixels (default 256).')
argument_parser.add_argument('-v', '--vector', default=False, action='store_true',
help='Create vector output. A SVG file will also be output.')
argument_parser.add_argument('-a', '--animate', type=int, default=0,
help='If a number greater than 0 is provided, will create an animated '
'GIF with the number of milliseconds per frame provided.')
help='If greater than 0, will create an animated GIF '
'with the number of milliseconds per frame provided.')
arguments = argument_parser.parse_args()
method = ColorMethod[arguments.method.upper()]
shape_type = ShapeType[arguments.shape.upper()]
StainedGlass(arguments.image_file, arguments.output_file, arguments.trials, method, shape_type, arguments.length,
arguments.vector, arguments.animate)
StainedGlass(arguments.image_file, arguments.output_file, arguments.trials, method,
shape_type, arguments.length, arguments.vector, arguments.animate)
Loading

0 comments on commit 01f5cb5

Please sign in to comment.