6 python stutter.py stutter_code.stt > c_code.c
15 def is_integer(s_expression):
16 return isinstance(s_expression, int) \
17 and not s_expression is True \
18 and not s_expression is False
25 def undelimit_string(s):
29 assert delimiter == '"' # This is temporary, " is currently the only delimiter
30 assert s[-1] == delimiter
32 escape_characters = dict(ESCAPE_CHARACTERS)
33 escape_characters[delimiter] = delimiter
46 # TODO Handle when it's not a valid escape character
47 ch = escape_characters[s[index]]
57 assert isinstance(string, str)
59 def indent_line(line):
65 return ' ' * TAB_WIDTH + line
67 return '\n'.join(indent_line(line) for line in string.splitlines())
69 # String to s-expressions
72 def __init__(self, string):
75 def __eq__(self, other):
76 return self.string == other.string
78 TOKEN = re.compile(r'\s*({})'.format('|'.join('(?P<{}>{})'.format(*token) for token in [
79 ('open_parenthese', r'\('),
80 ('close_parenthese', r'\)'),
81 ('identifier', r'[a-z]+'), # We can expand this as needed
82 ('integer_literal', r'\d+'),
83 ('string_literal', r'"(\\"|[^"])*"'),
84 ('unexpected_character', r'.'),
87 def parse_all(source):
91 for token in TOKEN.finditer(source):
92 if token.group('open_parenthese'):
96 elif token.group('close_parenthese'):
98 raise Exception('Parenthese closed but not opened')
100 stack[-1].append(tuple(items))
103 elif token.group('identifier'):
104 items.append(Symbol(token.group('identifier')))
106 elif token.group('integer_literal'):
107 items.append(int(token.group('integer_literal')))
109 elif token.group('string_literal'):
110 items.append(undelimit_string(token.group('string_literal')))
112 elif token.group('unexpected_character'):
113 raise Exception('Unexpected character {}'.format(
114 token.group('unexpected_character'),
121 raise Exception('Parenthese opened but not closed')
128 def __init__(self, name):
131 class CPointerType(CType):
132 def __init__(self, pointer_to):
133 self.pointer_to = pointer_to
135 class CArgumentDeclaration(object):
136 def __init__(self, type, name):
137 assert isinstance(type, CType)
141 class CExpression(object):
144 class CIntegerLiteralExpression(CExpression):
145 def __init__(self, integer):
146 assert is_integer(integer)
147 self.integer = integer
149 def __eq__(self, other):
150 assert isinstance(other, CIntegerLiteralExpression)
151 return self.integer == other.integer
153 class CStringLiteralExpression(CExpression):
154 def __init__(self, string):
155 assert isinstance(string, str)
158 def __eq__(self, other):
159 assert isinstance(other, CStringLiteralExpression)
160 return self.string == other.string
162 class CVariableExpression(CExpression):
163 def __init__(self, name):
164 assert isinstance(name, str)
167 def __eq__(self, other):
168 assert isinstance(other, CVariableExpression)
169 return self.name == other.name
171 class CFunctionCallExpression(CExpression):
172 def __init__(self, name, arguments):
173 assert all(isinstance(argument, CExpression) for argument in arguments)
175 self.arguments = arguments
177 def __eq__(self, other):
178 assert isinstance(other, CFunctionCallExpression)
179 return self.name == other.name and self.arguments == other.arguments
181 class CStatement(object):
184 class CExpressionStatement(CStatement):
185 def __init__(self, expression):
186 self.expression = expression
188 class CReturnStatement(CStatement):
189 def __init__(self, expression):
190 self.expression = expression
192 class CFunctionBody(object):
193 def __init__(self, statements):
194 statements = list(statements)
195 assert all(isinstance(s, CStatement) for s in statements)
196 self.statements = statements
198 class CFunctionDeclaration(object):
199 def __init__(self, return_type, name, argument_declaration_list, body):
200 assert isinstance(return_type, CType)
201 assert isinstance(argument_declaration_list, list)
202 assert all(isinstance(ad, CArgumentDeclaration) for ad in argument_declaration_list)
203 assert isinstance(body, CFunctionBody)
205 self.return_type = return_type
207 self.argument_declaration_list = argument_declaration_list
210 # BEGIN S-expression to C AST layer
212 def quote_to_c(s_expression):
213 if is_integer(s_expression):
214 return CFunctionCallExpression(
215 'makeObjectPointerFromInteger',
216 [CIntegerLiteralExpression(s_expression)],
219 if isinstance(s_expression, str):
220 return CFunctionCallExpression(
221 'makeObjectPointerFromString',
222 [CStringLiteralExpression(s_expression)],
225 raise Exception('Not implemented')
227 def evaluate_application_arguments_to_c(
229 quote_to_c = quote_to_c,
232 if len(arguments) == 0:
233 return CVariableExpression('NULL')
235 return CFunctionCallExpression(
238 quote_to_c(arguments[0]),
239 evaluate_application_arguments_to_c(arguments[1:]),
243 def evaluate_application_to_c(
245 evaluate_application_arguments_to_c = evaluate_application_arguments_to_c,
248 assert isinstance(s_expression, tuple)
249 if isinstance(s_expression[0], Symbol):
250 return CFunctionCallExpression(
251 s_expression[0].string,
252 (evaluate_application_arguments_to_c(s_expression[1:]),),
255 raise Exception('Not implemented')
259 evaluate_application_to_c = evaluate_application_to_c,
262 if isinstance(s_expression, tuple):
263 return evaluate_application_to_c(s_expression)
265 if is_integer(s_expression):
266 return CIntegerLiteralExpression(s_expression)
268 if isinstance(s_expression, str):
269 return CStringLiteralExpression(s_expression)
271 raise Exception('Unable to evaluate expression {} to C'.format(s_expression))
273 def evaluate_all_to_c(s_expressions):
274 c_expressions = list(map(evaluate_to_c, s_expressions))
276 return CFunctionBody(itertools.chain(
277 map(CExpressionStatement, c_expressions[:-1]),
278 [CReturnStatement(c_expressions[-1])],
281 # BEGIN C AST to C source layer
283 def generate_pointer_type(pointer_type):
284 assert isinstance(pointer_type, CPointerType)
285 return '{}*'.format(generate_type(pointer_type.pointer_to))
289 generate_pointer_type = generate_pointer_type):
290 assert isinstance(type, CType)
292 if isinstance(type, CPointerType):
293 return generate_pointer_type(type)
297 def generate_argument_declaration(argument_declaration):
298 assert isinstance(argument_declaration, CArgumentDeclaration)
299 return '{} {}'.format(generate_type(argument_declaration.type), argument_declaration.name)
301 def generate_argument_declaration_list(argument_declarations):
302 return ', '.join(generate_argument_declaration(ad) for ad in argument_declarations)
304 def generate_integer_literal_expression(expression):
305 assert isinstance(expression, CIntegerLiteralExpression)
306 return str(expression.integer)
308 C_ESCAPE_SEQUENCES = {
309 # Taken from https://en.wikipedia.org/wiki/Escape_sequences_in_C
323 def generate_string_literal_expression(expression):
324 assert isinstance(expression, CStringLiteralExpression)
328 for ch in expression.string:
329 result += C_ESCAPE_SEQUENCES.get(ch, ch)
335 def generate_variable_expression(expression):
336 assert isinstance(expression, CVariableExpression)
337 return expression.name
339 def generate_function_call_expression(expression):
340 assert isinstance(expression, CFunctionCallExpression)
341 return '{}({})'.format(
343 ', '.join(generate_expression(e) for e in expression.arguments),
346 def generate_expression(
348 generate_integer_literal_expression = generate_integer_literal_expression,
349 generate_string_literal_expression = generate_string_literal_expression,
350 generate_variable_expression = generate_variable_expression,
351 generate_function_call_expression = generate_function_call_expression,
354 if isinstance(expression, CIntegerLiteralExpression):
355 return generate_integer_literal_expression(expression)
357 if isinstance(expression, CStringLiteralExpression):
358 return generate_string_literal_expression(expression)
360 if isinstance(expression, CVariableExpression):
361 return generate_variable_expression(expression)
363 if isinstance(expression, CFunctionCallExpression):
364 return generate_function_call_expression(expression)
366 raise Exception('Expression type {} not implemented'.format(type(expression)))
368 def generate_expression_statement(statement):
369 return '{};'.format(generate_expression(statement.expression))
371 def generate_return_statement(statement):
372 return 'return {};'.format(generate_expression(statement.expression))
374 def generate_statement(
376 generate_expression_statement = generate_expression_statement,
377 generate_return_statement = generate_return_statement):
379 if isinstance(statement, CExpressionStatement):
380 return generate_expression_statement(statement)
382 if isinstance(statement, CReturnStatement):
383 return generate_return_statement(statement)
385 raise Exception('Handling for statements of type {} not implemented'.format(type(statement.type)))
387 def generate_function_body(function_body):
388 assert isinstance(function_body, CFunctionBody)
389 return '\n'.join(generate_statement(s) for s in function_body.statements)
391 FUNCTION_DEFINITION_TEMPLATE = string.Template(
393 $return_type $name($argument_declaration_list)
399 def generate_function_declaration(function_declaration):
400 assert isinstance(function_declaration, CFunctionDeclaration)
401 return FUNCTION_DEFINITION_TEMPLATE.substitute(
402 return_type = generate_type(function_declaration.return_type),
403 name = function_declaration.name,
404 argument_declaration_list = generate_argument_declaration_list(function_declaration.argument_declaration_list),
405 body = indent(generate_function_body(function_declaration.body)),
408 PROGRAM_TEMPLATE = string.Template(
415 typedef struct Object Object;
422 typedef enum Type Type;
425 typedef struct Cell Cell;
437 typedef union Instance Instance;
439 Instance makeInstanceFromCell(Cell cell)
446 Instance makeInstanceFromString(char* string)
449 result.string = string;
459 Object makeObject(Type t, Instance i)
467 Object makeObjectFromCell(Cell cell)
469 return makeObject(CELL, makeInstanceFromCell(cell));
472 Object makeObjectFromString(char* string)
474 return makeObject(STRING, makeInstanceFromString(string));
477 Object* makeObjectPointerFromObject(Object o)
479 Object* result = malloc(sizeof(Object));
484 Object* makeObjectPointerFromCell(Cell cell)
486 return makeObjectPointerFromObject(makeObjectFromCell(cell));
489 Object* makeObjectPointerFromString(char* string)
491 return makeObjectPointerFromObject(makeObjectFromString(string));
494 Cell makeCell(Object* left, Object* right)
498 result.right = right;
502 Object* c_cons(Object* left, Object* right)
504 Cell cell = makeCell(left, right);
505 return makeObjectPointerFromCell(cell);
508 void c_print(Object* stutter_string)
510 assert(stutter_string->type == STRING);
511 char* c_string = stutter_string->instance.string;
512 printf("%s", c_string);
515 int countArgs(Object* args)
517 if(args == NULL) return 0;
519 assert(args->type == CELL);
520 return 1 + countArgs(args->instance.cell.right);
523 Object* getArg(int index, Object* args)
525 if(index == 0) return args->instance.cell.left;
527 return getArg(index - 1, args->instance.cell.right);
530 void print(Object* args)
532 assert(countArgs(args) == 1);
533 Object* stutter_string = getArg(0, args);
534 c_print(stutter_string);
537 int main(int argc, char** argv)
543 def generate_program(body):
544 return PROGRAM_TEMPLATE.substitute(
548 if __name__ == '__main__':
550 source_file_name = sys.argv[1]
552 with open(source_file_name, 'r') as source_file:
553 source = source_file.read()
555 result = generate_program(
556 indent(generate_function_body(evaluate_all_to_c(parse_all(source)))),