Thun/implementations/C/convert_defs.py

129 lines
2.9 KiB
Python

'''
It's cheap, but it works.
Doesn't handle non-alnum names.
Because the strings are parsed at start time, rather than compile time,
it's basically the same as implementing an inscribe command
and using it to write a simple Joy script to load the defs:
for line in defs:
print(f'[{line}] inscribe')
Eh?
'''
import sys, unicodedata
def filt(name):
'''
Pass alphanumeric chars and underscores, convert other chars
to their Unicode names so they can work as (portions of) C
identifiers.
'''
alnum = True
for i, ch in enumerate(name):
if alnum:
if ch.isalnum() or ch == '_':
yield ch
else:
alnum = False
if i:
yield '_'
yield (
unicodedata
.name(ch)
.replace(' ', '_')
.replace('-', '_')
)
else:
if ch.isalnum() or ch == '_':
alnum = True
yield '_'
yield ch
else:
yield '_'
yield (
unicodedata
.name(ch)
.replace(' ', '_')
.replace('-', '_')
)
def convert_name(name):
return name if name.isidentifier() else ''.join(filt(name))
defs = [line.strip() for line in open('./defs.txt')]
print(f'''\
/*
Auto-generated file by {' '.join(sys.argv)}
Do not edit.
*/
''')
if sys.argv[-1] == '--header':
for line in defs:
name, body = line.split(None, 1)
name = convert_name(name)
print(f'void def_{name}(JoyListPtr stack, JoyListPtr expression);')
elif sys.argv[-1] == '--keywords':
sys.stdout.write(open('KEYWORDS.in').read())
for line in defs:
name, body = line.split(None, 1)
print(f'{name}, def_{convert_name(name)}')
else:
print('''\
#include "joy.h"
#include "definitions.h"
/*
Declare a bunch of list pointers to eventually hold the body expressions
of the definitions.
*/
''')
for line in defs:
name, body = line.split(None, 1)
name = convert_name(name)
print(f'JoyList def_{name}_body;')
print('''
/*
Next, we want an initializer function to fill out the body pointers.
*/
void
init_defs(void)
{
''')
for line in defs:
name, body = line.split(None, 1)
name = convert_name(name)
print(f'\tdef_{name}_body = text_to_expression("{body}");')
print('}')
print('''
/*
Last, a set of functions to go in the wordlist, one for each definition.
*/
''')
for line in defs:
name, body = line.split(None, 1)
name = convert_name(name)
print(f'void def_{name}(__attribute__((unused)) JoyListPtr stack, JoyListPtr expression) {{ push_quote_onto_expression(def_{name}_body, expression); }}')