Skip to content

Instantly share code, notes, and snippets.

@milesrout
Last active March 18, 2018 10:57
Show Gist options
  • Save milesrout/e2a86e5716e287dfd150f228c8fca39b to your computer and use it in GitHub Desktop.
Save milesrout/e2a86e5716e287dfd150f228c8fca39b to your computer and use it in GitHub Desktop.
# to print an s-expression
#
# e.g.
# (macro-definition
# (id-expression name)
# (statements
# (...)
# (...)
# (...)))
#
# 1. Print opening bracket
# 2. Print first item in list directly
# 3. If the list contains any lists or the length condition holds
# a. Increment the indentation level
# b. For each item in the list:
# i. Print a newline
# ii. Print enough spaces to reach the current indentation level
# iii. Print the sub-expression
# 4. Otherwise
# a. For each item in the list:
# i. Print a space
# ii. Print the sub-expression *without considering the first branch of the if*
# 5. Print a closing bracket
#
# (Without the restriction on considering the first branch of the if, this is exponential complexity)
def to_sexpr(o, indent=None):
return fmt_sexpr(json.loads(MyJSONEncoder().encode(o)))
def fmt_sexpr(o, depth=1):
if isinstance(o, dict):
return fmt_sexpr(list(o.values()), depth)
if isinstance(o, tuple):
return fmt_sexpr(list(o), depth)
if isinstance(o, list):
if len(o) == 0:
return '()'
if len(o) == 1:
return fmt_sexpr(o[0], depth)
return fmt_sexpr_list(o, depth)
return str(o)
def fmt_sexpr_short(o, depth=1):
if isinstance(o, dict):
return fmt_sexpr_short(list(o.values()))
if isinstance(o, tuple):
return fmt_sexpr_short(list(o))
if isinstance(o, list):
if len(o) == 0:
return '()'
if len(o) == 1:
return fmt_sexpr_short(o[0])
return fmt_sexpr_list_short(o)
return str(o)
@compose(''.join)
def fmt_sexpr_list_long(o, depth):
yield '('
yield fmt_sexpr(o[0], depth + 1)
for item in o[1:]:
yield '\n'
yield (2 * depth * ' ')
yield fmt_sexpr(item, depth + 1)
yield ')'
@compose(''.join)
def fmt_sexpr_list_short(o):
yield '('
yield fmt_sexpr_short(o[0])
for item in o[1:]:
yield ' '
yield fmt_sexpr_short(item)
yield ')'
def fmt_sexpr_list(o, depth):
result = fmt_sexpr_list_short(o)
if max(map(len, result.splitlines())) > 80:
return fmt_sexpr_list_long(o, depth)
return result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment