writer.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. from math import ceil
  2. TABSIZE = 4 # Size in spaces of a single tab
  3. INLINE_COMMENT_LEVEL = 6 # Number of tabs to inline commment level
  4. COMMAND_SIZE = 8 # Default length of a command name, used for
  5. # indenting
  6. ADD_COMMENT_BLOCKS = True # Wether to add newlines before and after
  7. # non-inline comment
  8. ADD_ARGUMENT_SPACE = False # Wether to add a space between command arguments
  9. # and the previous comma
  10. def write_statements(statements):
  11. """Write a list of statements to valid assembly code."""
  12. out = ''
  13. indent_level = 0
  14. prev_comment = False
  15. for i, s in enumerate(statements):
  16. current_comment = False
  17. if s.is_label():
  18. line = s.name + ':'
  19. indent_level = 1
  20. elif s.is_comment():
  21. line = '\t' * indent_level + '#' + s.name
  22. current_comment = s.options.get('block', True)
  23. elif s.is_directive():
  24. line = '\t' + s.name
  25. elif s.is_command():
  26. line = '\t' + s.name
  27. # If there are arguments, add tabs until the 8 character limit has
  28. # been reached. If the command name is 8 or more characers long,
  29. # add a single space
  30. if len(s):
  31. l = len(s.name)
  32. if l < COMMAND_SIZE:
  33. line += '\t' * int(ceil((COMMAND_SIZE - l)
  34. / float(TABSIZE)))
  35. else:
  36. line += ' '
  37. delim = ', ' if ADD_ARGUMENT_SPACE else ','
  38. line += delim.join(map(str, s))
  39. else:
  40. raise Exception('Unsupported statement type "%s"' % s.stype)
  41. # Add the inline comment, if there is any
  42. if s.has_inline_comment():
  43. start = INLINE_COMMENT_LEVEL * TABSIZE
  44. diff = start - len(line.expandtabs(TABSIZE))
  45. # The comment must not be directly adjacent to the command itself
  46. tabs = int(ceil(diff / float(TABSIZE))) + 1 if diff > 0 else 1
  47. line += '\t' * tabs + '#' + s.options['comment']
  48. # Add newline at end of command
  49. line += '\n'
  50. if ADD_COMMENT_BLOCKS:
  51. if prev_comment ^ current_comment:
  52. out += '\n'
  53. out += line
  54. prev_comment = current_comment
  55. return out
  56. def write_to_file(filename, statements):
  57. """Convert a list of statements to valid assembly code and write it to a
  58. file."""
  59. s = write_statements(statements)
  60. f = open(filename, 'w+')
  61. f.write(s)
  62. f.close()