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 CReferenceExpression(CExpression):
172 def __init__(self, referee):
173 assert isinstance(referee, CVariableExpression)
174 self.referee = referee
176 class CFunctionCallExpression(CExpression):
177 def __init__(self, name, arguments):
178 assert all(isinstance(argument, CExpression) for argument in arguments)
180 self.arguments = arguments
182 def __eq__(self, other):
183 assert isinstance(other, CFunctionCallExpression)
184 return self.name == other.name and self.arguments == other.arguments
186 class CStatement(object):
189 class CExpressionStatement(CStatement):
190 def __init__(self, expression):
191 self.expression = expression
193 class CReturnStatement(CStatement):
194 def __init__(self, expression):
195 self.expression = expression
197 class CDefinitionStatement(CStatement):
198 def __init__(self, _type, name, definition):
199 assert isinstance(_type, CType)
200 assert isinstance(name, str)
201 assert isinstance(definition, CExpression)
205 self.definition = definition
207 class CFunctionBody(object):
208 def __init__(self, statements):
209 statements = list(statements)
210 assert all(isinstance(s, CStatement) for s in statements)
211 self.statements = statements
213 class CFunctionDeclaration(object):
214 def __init__(self, return_type, name, argument_declaration_list, body):
215 assert isinstance(return_type, CType)
216 assert isinstance(argument_declaration_list, list)
217 assert all(isinstance(ad, CArgumentDeclaration) for ad in argument_declaration_list)
218 assert isinstance(body, CFunctionBody)
220 self.return_type = return_type
222 self.argument_declaration_list = argument_declaration_list
225 # BEGIN S-expression to C AST layer
227 def quote_to_c(s_expression):
228 if is_integer(s_expression):
229 return CFunctionCallExpression(
230 'makeObjectPointerFromInteger',
231 [CIntegerLiteralExpression(s_expression)],
234 if isinstance(s_expression, str):
235 return CFunctionCallExpression(
236 'makeObjectPointerFromString',
237 [CStringLiteralExpression(s_expression)],
240 if isinstance(s_expression, Symbol):
241 return CFunctionCallExpression(
243 [CStringLiteralExpression(s_expression.string)],
246 raise Exception('Not implemented for type {}'.format(type(s_expression)))
248 def evaluate_application_arguments_to_c(
250 quote_to_c = quote_to_c,
253 if len(arguments) == 0:
254 return CVariableExpression('NULL')
256 return CFunctionCallExpression(
259 quote_to_c(arguments[0]),
260 evaluate_application_arguments_to_c(arguments[1:]),
264 def evaluate_application_to_c(
266 evaluate_application_arguments_to_c = evaluate_application_arguments_to_c,
269 assert isinstance(s_expression, tuple)
270 if isinstance(s_expression[0], Symbol):
271 return CFunctionCallExpression(
272 s_expression[0].string,
274 CReferenceExpression(CVariableExpression('env')),
275 evaluate_application_arguments_to_c(s_expression[1:]),
279 raise Exception('Not implemented')
283 evaluate_application_to_c = evaluate_application_to_c,
286 if isinstance(s_expression, tuple):
287 return evaluate_application_to_c(s_expression)
289 if is_integer(s_expression):
290 return CIntegerLiteralExpression(s_expression)
292 if isinstance(s_expression, str):
293 return CStringLiteralExpression(s_expression)
295 raise Exception('Unable to evaluate expression {} to C'.format(s_expression))
297 def evaluate_all_to_c(s_expressions):
298 c_expressions = list(map(evaluate_to_c, s_expressions))
300 return CFunctionBody(itertools.chain(
301 [CDefinitionStatement(
302 CPointerType(CType('Environment')),
304 CVariableExpression('NULL'),
306 map(CExpressionStatement, c_expressions[:-1]),
307 [CReturnStatement(c_expressions[-1])],
310 # BEGIN C AST to C source layer
312 def generate_pointer_type(pointer_type):
313 assert isinstance(pointer_type, CPointerType)
314 return '{}*'.format(generate_type(pointer_type.pointer_to))
318 generate_pointer_type = generate_pointer_type):
319 assert isinstance(type, CType)
321 if isinstance(type, CPointerType):
322 return generate_pointer_type(type)
326 def generate_argument_declaration(argument_declaration):
327 assert isinstance(argument_declaration, CArgumentDeclaration)
328 return '{} {}'.format(
329 generate_type(argument_declaration._type),
330 argument_declaration.name,
333 def generate_argument_declaration_list(argument_declarations):
334 return ', '.join(generate_argument_declaration(ad) for ad in argument_declarations)
336 def generate_integer_literal_expression(expression):
337 assert isinstance(expression, CIntegerLiteralExpression)
338 return str(expression.integer)
340 C_ESCAPE_SEQUENCES = {
341 # Taken from https://en.wikipedia.org/wiki/Escape_sequences_in_C
355 def generate_string_literal_expression(expression):
356 assert isinstance(expression, CStringLiteralExpression)
360 for ch in expression.string:
361 result += C_ESCAPE_SEQUENCES.get(ch, ch)
367 def generate_variable_expression(expression):
368 assert isinstance(expression, CVariableExpression)
369 return expression.name
371 def generate_reference_expression(expression):
372 assert isinstance(expression, CReferenceExpression)
373 return '&{}'.format(generate_variable_expression(expression.referee))
375 def generate_function_call_expression(expression):
376 assert isinstance(expression, CFunctionCallExpression)
377 return '{}({})'.format(
379 ', '.join(generate_expression(e) for e in expression.arguments),
382 def generate_expression(
384 generate_integer_literal_expression = generate_integer_literal_expression,
385 generate_string_literal_expression = generate_string_literal_expression,
386 generate_variable_expression = generate_variable_expression,
387 generate_reference_expression = generate_reference_expression,
388 generate_function_call_expression = generate_function_call_expression,
391 if isinstance(expression, CIntegerLiteralExpression):
392 return generate_integer_literal_expression(expression)
394 if isinstance(expression, CStringLiteralExpression):
395 return generate_string_literal_expression(expression)
397 if isinstance(expression, CVariableExpression):
398 return generate_variable_expression(expression)
400 if isinstance(expression, CReferenceExpression):
401 return generate_reference_expression(expression)
403 if isinstance(expression, CFunctionCallExpression):
404 return generate_function_call_expression(expression)
406 raise Exception('Expression type {} not implemented'.format(type(expression)))
408 def generate_expression_statement(statement):
409 return '{};'.format(generate_expression(statement.expression))
411 def generate_return_statement(statement):
412 return 'return {};'.format(generate_expression(statement.expression))
414 def generate_definition_statement(statement):
415 return '{} {} = {};'.format(
416 generate_type(statement._type),
418 generate_expression(statement.definition),
421 def generate_statement(
423 generate_expression_statement = generate_expression_statement,
424 generate_return_statement = generate_return_statement,
425 generate_definition_statement = generate_definition_statement):
427 if isinstance(statement, CExpressionStatement):
428 return generate_expression_statement(statement)
430 if isinstance(statement, CReturnStatement):
431 return generate_return_statement(statement)
433 if isinstance(statement, CDefinitionStatement):
434 return generate_definition_statement(statement)
436 raise Exception('Handling for statements of type {} not implemented'.format(type(statement)))
438 def generate_function_body(function_body):
439 assert isinstance(function_body, CFunctionBody)
440 return '\n'.join(generate_statement(s) for s in function_body.statements)
442 FUNCTION_DEFINITION_TEMPLATE = string.Template(
444 $return_type $name($argument_declaration_list)
450 def generate_function_declaration(function_declaration):
451 assert isinstance(function_declaration, CFunctionDeclaration)
452 return FUNCTION_DEFINITION_TEMPLATE.substitute(
453 return_type = generate_type(function_declaration.return_type),
454 name = function_declaration.name,
455 argument_declaration_list = generate_argument_declaration_list(function_declaration.argument_declaration_list),
456 body = indent(generate_function_body(function_declaration.body)),
459 PROGRAM_TEMPLATE = string.Template(
468 typedef struct Object Object;
476 typedef enum Type Type;
478 #define MAX_TYPE_STRING_LENGTH 7
480 void typeToString(Type type, char* target)
485 snprintf(target, MAX_TYPE_STRING_LENGTH, "CELL");
489 snprintf(target, MAX_TYPE_STRING_LENGTH, "STRING");
493 snprintf(target, MAX_TYPE_STRING_LENGTH, "%s", "SYMBOL");
497 fprintf(stderr, "ERROR: Unknown type");
503 typedef struct Cell Cell;
511 typedef struct Environment Environment;
519 Environment makeEnvironment(char* key, Object* value, Environment* next)
523 result.value = value;
528 Environment* makeEnvironmentPointerFromEnvironment(Environment env)
530 Environment* result = malloc(sizeof(Environment));
535 Environment* makeEnvironmentPointer(char* key, Object* value, Environment* next)
537 return makeEnvironmentPointerFromEnvironment(makeEnvironment(key, value, next));
546 typedef union Instance Instance;
548 Instance makeInstanceFromCell(Cell cell)
555 Instance makeInstanceFromString(char* string)
558 result.string = string;
562 Instance makeInstanceFromSymbol(char* symbol)
565 result.symbol = symbol;
575 Object makeObject(Type t, Instance i)
583 Object makeObjectFromCell(Cell cell)
585 return makeObject(CELL, makeInstanceFromCell(cell));
588 Object makeObjectFromString(char* string)
590 return makeObject(STRING, makeInstanceFromString(string));
593 Object makeObjectFromSymbol(char* symbol)
595 return makeObject(SYMBOL, makeInstanceFromSymbol(symbol));
598 Object* makeObjectPointerFromObject(Object o)
600 Object* result = malloc(sizeof(Object));
605 Object* makeObjectPointerFromCell(Cell cell)
607 return makeObjectPointerFromObject(makeObjectFromCell(cell));
610 Object* makeObjectPointerFromString(char* string)
612 return makeObjectPointerFromObject(makeObjectFromString(string));
615 Object* makeObjectPointerFromSymbol(char* symbol)
617 return makeObjectPointerFromObject(makeObjectFromSymbol(symbol));
620 Object* getSymbol(char* symbol)
622 // This will not always be how this is implemented
623 return makeObjectPointerFromSymbol(symbol);
626 Cell makeCell(Object* left, Object* right)
630 result.right = right;
634 Object* c_cons(Object* left, Object* right)
636 Cell cell = makeCell(left, right);
637 return makeObjectPointerFromCell(cell);
640 void c_print(Object* stutter_string)
642 if(stutter_string->type != STRING)
644 char typeName[MAX_TYPE_STRING_LENGTH];
645 typeToString(stutter_string->type, typeName);
646 fprintf(stderr, "ERROR: Expected type STRING, got type %s.", typeName);
650 char* c_string = stutter_string->instance.string;
651 printf("%s", c_string);
654 bool c_symbol_equal(char* left, char* right)
656 return strcmp(left, right) == 0;
659 Object* c_evaluate_symbol(Environment* env, Object* s)
663 fprintf(stderr, "ERROR: symbol %s not found.", s->instance.symbol);
667 if(c_symbol_equal(env->key, s->instance.symbol))
672 return c_evaluate_symbol(env->next, s);
675 Object* c_evaluate(Environment** env, Object* o)
683 return c_evaluate_symbol(*env, o);
689 char typeName[MAX_TYPE_STRING_LENGTH];
690 typeToString(o->type, typeName);
691 fprintf(stderr, "ERROR: Could not evaluate type %s.", typeName);
695 int countArgs(Object* args)
697 if(args == NULL) return 0;
699 assert(args->type == CELL);
700 return 1 + countArgs(args->instance.cell.right);
703 Object* getArg(int index, Object* args)
705 if(index == 0) return args->instance.cell.left;
707 return getArg(index - 1, args->instance.cell.right);
710 void print(Environment** parent, Object* args)
712 assert(countArgs(args) == 1);
713 Object* stutter_string = c_evaluate(parent, getArg(0, args));
714 c_print(stutter_string);
717 void define(Environment** parent, Object* args)
719 assert(countArgs(args) == 2);
720 Object* name = getArg(0, args);
721 Object* value = c_evaluate(parent, getArg(1, args));
723 assert(name->type == SYMBOL);
724 *parent = makeEnvironmentPointer(name->instance.symbol, value, *parent);
727 int main(int argc, char** argv)
733 def generate_program(body):
734 return PROGRAM_TEMPLATE.substitute(
738 if __name__ == '__main__':
740 source_file_name = sys.argv[1]
742 with open(source_file_name, 'r') as source_file:
743 source = source_file.read()
745 result = generate_program(
746 indent(generate_function_body(evaluate_all_to_c(parse_all(source)))),