def generate_string_literal(c_string_literal):
return 'stringLiteral(STRING_LITERAL_LIST[{}])'.format(c_string_literal.index)
-CONSTANT_EXPRESSION_MAPPING = {
- 'true': 'TRUE',
- 'false': 'FALSE',
-}
-
-def generate_constant_expression(c_constant_expression):
- return CONSTANT_EXPRESSION_MAPPING[c_constant_expression.value]
-
def generate_symbol_expression(symbol_expression):
return 'Environment_get(environment, SYMBOL_LIST[{}] /* symbol: {} */)'.format(
symbol_expression.symbol_list_index,
LITERAL_TYPE_MAPPING = {
transformation.CIntegerLiteral: generate_integer_literal,
transformation.CStringLiteral: generate_string_literal,
- transformation.CConstantExpression: generate_constant_expression,
transformation.CSymbolExpression: generate_symbol_expression,
}
)
def generate_expression_statement(statement):
- # TODO Do this at an earlier pass
- if isinstance(statement.expression, transformation.CVariableExpression):
- return '';
-
# TODO Do we need to garbage collect the results of arbitrary statements?
return '{};'.format(generate_expression(statement.expression))
transformation.CVariableReassignmentStatement: generate_variable_reassignment_statement,
}[type(statement)](statement)
+def generate_function_definition(definition):
+ template = ENV.get_template('function_definition.c')
+ return template.render(
+ name=definition.name,
+ argument_name_list=definition.argument_name_list,
+ statement_list=list(generate_statement(s) for s in definition.statement_list),
+ )
+ return definition
+
def generate(program):
template = ENV.get_template('program.c')
return template.render(
builtins=tuple(sorted(program.builtin_set)),
- function_definition_list=program.function_definition_list,
- generate_statement=generate_statement,
+ function_definition_list=list(generate_function_definition(fd) for fd in program.function_definition_list),
infix_declarations=program.operator_declarations,
- statements=program.statements,
+ statements=list(generate_statement(s) for s in program.statements),
standard_libraries=list(sorted(program.standard_libraries)),
string_literal_list=program.string_literal_list,
symbol_list=program.symbol_list,
)
def normalize_symbol_expression(counter, expression):
- # TODO Store this in a C variable
+ variable = '${}'.format(counter)
return (
- counter,
- (),
- NormalSymbolExpression(symbol=expression.symbol),
+ counter + 1,
+ (NormalVariableInitializationStatement(
+ variable=variable,
+ expression=NormalSymbolExpression(symbol=expression.symbol),
+ ),),
+ NormalVariableExpression(variable=variable),
)
def normalize_function_call_expression(counter, expression):
}[type(expression)](counter, expression)
def normalize_expression_statement(counter, statement):
+ # TODO Normalized will be a NormalVariableExpression, which will go unused
+ # for expression statements in every case except when it's a return
+ # statement. This cases warnings on C compilation. We should only generate
+ # this variable when it will be used on return.
counter, prestatements, normalized = normalize_expression(counter, statement.expression)
return (
yield normalized
def normalize(program):
-
return NormalProgram(
statement_list=normalize_statement_list(program.statement_list),
)
--- /dev/null
+
+Object user${{name}}$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Object* args)
+{
+ assert(argc == {{ argument_name_list|length }});
+
+ Environment* environment = EnvironmentPool_allocate(environmentPool);
+ Environment_initialize(environment, parent);
+
+ {% for argument_name in argument_name_list %}
+ Environment_set(environment, "{{ argument_name }}", args[{{ loop.index0 }}]);
+ {% endfor %}
+
+ {% for statement in statement_list[:-1] %}
+ {{ statement }}
+ {% endfor %}
+
+ Object result = {{ statement_list[-1] }}
+
+ Environment_setLive(environment, false);
+ return result;
+}
Instance instance;
};
-const Object TRUE = {
- BOOLEAN,
- { true }
-};
-
-const Object FALSE = {
- BOOLEAN,
- { false }
-};
+const Object builtin$true = { BOOLEAN, (Instance)(bool){ true } };
+const Object builtin$false = { BOOLEAN, (Instance)(bool){ false } };
struct EnvironmentNode
{
}
// TODO Return something better
- return FALSE;
+ return builtin$false;
}
Object builtin$print = { CLOSURE, (Instance)(Closure){ NULL, builtin$print$implementation } };
{% endif %}
-
{% for function_definition in function_definition_list %}
-Object user${{function_definition.name}}$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Object* args)
-{
- assert(argc == {{ function_definition.argument_name_list|length }});
-
- Environment* environment = EnvironmentPool_allocate(environmentPool);
- Environment_initialize(environment, parent);
-
- {% for argument_name in function_definition.argument_name_list %}
- Environment_set(environment, "{{ argument_name }}", args[{{ loop.index0 }}]);
- {% endfor %}
-
- {% for statement in function_definition.statement_list[:-1] %}
- {{ generate_statement(statement) }}
- {% endfor %}
-
- Object result = {{ generate_statement(function_definition.statement_list[-1]) }}
-
- Environment_setLive(environment, false);
- return result;
-}
-
+{{ function_definition }}
{% endfor %}
+
int main(int argc, char** argv)
{
EnvironmentPool* environmentPool = EnvironmentPool_construct();
{% endfor %}
{% for statement in statements %}
- {{ generate_statement(statement) }}
+ {{ statement }}
{% endfor %}
Environment_setLive(environment, false);
],
)
-CConstantExpression = collections.namedtuple(
- 'CConstantExpression',
- [
- 'value'
- ],
-)
-
CVariableExpression = collections.namedtuple(
'CVariableExpression',
[
return CStringLiteral(index=index, value=value)
def transform_symbol_expression(accumulators, expression):
- if expression.symbol in ['true', 'false']:
- return CConstantExpression(value=expression.symbol)
+ if expression.symbol in BUILTINS:
+ accumulators.builtin_set.add(expression.symbol)
try:
symbol_list_index = accumulators.symbol_list.index(expression.symbol)
)
def transform_function_call_expression(accumulators, function_call):
- if isinstance(function_call.function, normalization.NormalSymbolExpression):
- # TODO Move this check to transformation of symbol expressions so we can have builtins that aren't functions
- if function_call.function.symbol in BUILTINS.keys():
- # TODO Check that the builtin is actually callable
- accumulators.builtin_set.add(function_call.function.symbol)
-
# TODO Use the symbol from SYMBOL LIST
return CFunctionCallExpression(
name=transform_expression(accumulators, function_call.function),
transform_statement(accumulators, statement) for statement in program.statement_list
]
+ # This prevents warnings about normalized variables being entire C statements
+ last_statement = statement_list[-1]
+ if isinstance(last_statement, normalization.NormalExpressionStatement) and isinstance(last_statement.expression, normalization.NormalVariableExpression):
+ del statement_list[-1]
+
standard_library_set = set()
for builtin in accumulators.builtin_set:
for standard_library in BUILTINS[builtin]: