--- /dev/null
+def get_answer() do
+ 42
+end
+
+print(get_answer())
--- /dev/null
+42
\ No newline at end of file
indent('\n'.join(generate_statement(s) for s in statement.else_statements)),
)
+def generate_function_declaration(statement):
+ return 'Environment_set(environment, "{}", user${});'.format(statement.name, statement.name)
+
def generate_statement(statement):
return {
transformation.CExpressionStatement: generate_expression_statement,
+ transformation.CFunctionDeclaration: generate_function_declaration,
transformation.CIfElseStatement: generate_if_else_statement,
transformation.CSymbolAssignmentStatement: generate_symbol_assignment_statement,
transformation.CArrayVariableInitializationStatement: generate_array_variable_initialization_statement,
def generate(program):
template = ENV.get_template('program.c')
return template.render(
- builtins=list(sorted(program.builtin_set)),
- statements=[generate_statement(statement) for statement in program.statements],
+ builtins=tuple(sorted(program.builtin_set)),
+ function_definition_list=program.function_definition_list,
+ generate_statement=generate_statement,
+ statements=program.statements,
standard_libraries=list(sorted(program.standard_libraries)),
string_literal_list=program.string_literal_list,
symbol_list=program.symbol_list,
import collections
import parsing
+import util
NormalVariableExpression = collections.namedtuple(
'NormalVariableExpression',
],
)
+NormalFunctionDefinitionStatement = collections.namedtuple(
+ 'NormalFunctionDefinitionStatement',
+ [
+ 'name',
+ 'statement_list',
+ ],
+)
+
NormalProgram = collections.namedtuple(
'NormalProgram',
[
],
)
+# TODO Get rid of this
def fake_normalization(counter, thing):
return (counter, (), thing)
def normalize_expression_statement(counter, statement):
counter, prestatements, normalized = {
parsing.FurFunctionCallExpression: normalize_function_call_expression,
+ parsing.FurIntegerLiteralExpression: normalize_expression,
}[type(statement.expression)](counter, statement.expression)
return (
NormalExpressionStatement(expression=normalized),
)
+def normalize_function_definition_statement(counter, statement):
+ return (
+ counter,
+ (),
+ NormalFunctionDefinitionStatement(
+ name=statement.name,
+ statement_list=normalize_statement_list(statement.statement_list),
+ ),
+ )
+
def normalize_statement(counter, statement):
return {
+ parsing.FurAssignmentStatement: fake_normalization, # TODO unfake this
parsing.FurExpressionStatement: normalize_expression_statement,
- parsing.FurAssignmentStatement: fake_normalization,
+ parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
}[type(statement)](counter, statement)
-def normalize(program):
+@util.force_generator(tuple)
+def normalize_statement_list(statement_list):
counter = 0
- statement_list = []
- for statement in program.statement_list:
+ for statement in statement_list:
counter, prestatements, normalized = normalize_statement(counter, statement)
for s in prestatements:
- statement_list.append(s)
- statement_list.append(normalized)
+ yield s
+ yield normalized
+
+def normalize(program):
return NormalProgram(
- statement_list=statement_list,
+ statement_list=normalize_statement_list(program.statement_list),
)
)(index, tokens)
def _comma_separated_list_parser(index, tokens):
- failure = (False, index, None)
+ start_index = index
expressions = []
if success:
expressions.append(expression)
else:
- return failure
+ return (True, start_index, ())
while success and index < len(tokens) and tokens[index].type == 'comma':
success = False
],
)
+FurFunctionDefinitionStatement = collections.namedtuple(
+ 'FurFunctionDefinitionStatement',
+ [
+ 'name',
+ 'statement_list',
+ ],
+)
+
FurProgram = collections.namedtuple(
'FurProgram',
[
return True, index, FurAssignmentStatement(target=target, expression=expression)
+def _function_definition_statement_parser(index, tokens):
+ failure = (False, index, None)
+
+ if tokens[index].type == 'keyword' and tokens[index].match == 'def':
+ index += 1
+ else:
+ return failure
+
+ if tokens[index].type == 'symbol':
+ name = tokens[index].match
+ index += 1
+ else:
+ raise Exception('Expected function name, found "{}" on line {}'.format(
+ tokens[index].match,
+ tokens[index].line,
+ ))
+
+ if tokens[index].type == 'open_parenthese':
+ index += 1
+ else:
+ raise Exception('Expected "(", found "{}" on line {}'.format(
+ tokens[index].match,
+ tokens[index].line,
+ ))
+
+ if tokens[index].type == 'close_parenthese':
+ index += 1
+ else:
+ raise Exception('Expected ")", found "{}" on line {}'.format(
+ tokens[index].match,
+ tokens[index].line,
+ ))
+
+ if tokens[index].type == 'symbol' and tokens[index].match == 'do':
+ index += 1
+ else:
+ return failure
+
+ success, index, statement_list = _zero_or_more_parser(tuple, _statement_parser)(index, tokens)
+
+ _, index, _ = consume_newlines(index, tokens)
+
+ if tokens[index].type == 'keyword' and tokens[index].match == 'end':
+ index += 1
+ else:
+ return failure
+
+ return True, index, FurFunctionDefinitionStatement(name=name, statement_list=statement_list)
+
def _statement_parser(index, tokens):
_, index, _ = consume_newlines(index, tokens)
return _or_parser(
_assignment_statement_parser,
_expression_statement_parser,
+ _function_definition_statement_parser,
)(index, tokens)
def _program_formatter(statement_list):
Object builtin$print = { CLOSURE, (Instance)builtin$print$implementation };
{% endif %}
+{% for function_definition in function_definition_list %}
+Object user${{function_definition.name}}$implementation(size_t argc, Object* args)
+{
+ Environment* environment = Environment_construct();
+
+ {% for statement in function_definition.statement_list %}
+ {{ generate_statement(statement) }}
+ {% endfor %}
+
+ Object result = {{ generate_statement(function_definition.statement_list[-1]) }}
+ Environment_destruct(environment);
+ return result;
+}
+
+Object user${{function_definition.name}} = { CLOSURE, (Instance)user${{function_definition.name}}$implementation };
+{% endfor %}
+
int main(int argc, char** argv)
{
Environment* environment = Environment_construct();
{% endfor %}
{% for statement in statements %}
- {{ statement }}
+ {{ generate_statement(statement) }}
{% endfor %}
Environment_destruct(environment);
return token_matcher
-
_TOKEN_MATCHERS = [
+ ('keyword', r'(def|end)(?![a-z_])'),
('open_parenthese', r'\('),
('close_parenthese', r'\)'),
('comma', r','),
('integer_literal', r'\d+'),
- ('symbol', r'[a-z]+'),
+ ('symbol', r'[a-z_]+'),
('single_quoted_string_literal', r"'.*?'"),
('comparison_level_operator', r'(<=|>=|==|!=|<|>)'),
('assignment_operator', r'='),
],
)
+CFunctionDeclaration = collections.namedtuple(
+ 'CFunctionDeclaration',
+ [
+ 'name',
+ ],
+)
+
+CFunctionDefinition = collections.namedtuple(
+ 'CFunctionDefinition',
+ [
+ 'name',
+ 'statement_list',
+ ],
+)
+
CProgram = collections.namedtuple(
'CProgram',
[
'builtin_set',
+ 'function_definition_list',
'statements',
'standard_libraries',
'string_literal_list',
# TODO Check that the builtin is actually callable
accumulators.builtin_set.add(function_call.function.value)
- # TODO Use the symbol from SYMBOL LIST
- return CFunctionCallExpression(
- name=function_call.function.value,
- argument_count=function_call.argument_count,
- argument_items=transform_expression(accumulators, function_call.argument_items),
- )
-
- raise Exception()
+ # TODO Use the symbol from SYMBOL LIST
+ return CFunctionCallExpression(
+ name=function_call.function.value,
+ argument_count=function_call.argument_count,
+ argument_items=transform_expression(accumulators, function_call.argument_items),
+ )
def transform_expression_statement(accumulators, statement):
expression = {
parsing.FurFunctionCallExpression: transform_function_call_expression,
+ parsing.FurIntegerLiteralExpression: transform_expression,
normalization.NormalFunctionCallExpression: transform_function_call_expression,
}[type(statement.expression)](accumulators, statement.expression)
expression=transform_expression(accumulators, statement.expression),
)
+def transform_function_definition_statement(accumulators, statement):
+ # TODO Allow defining the same function in different contexts
+ if any(fd.name == statement.name for fd in accumulators.function_definition_list):
+ raise Exception('A function with name "{}" already exists'.format(statement.name))
+
+ accumulators.function_definition_list.append(CFunctionDefinition(
+ name=statement.name,
+ statement_list=tuple(transform_statement(accumulators, s) for s in statement.statement_list)
+ ))
+
+ return CFunctionDeclaration(name=statement.name)
+
def transform_statement(accumulators, statement):
return {
parsing.FurAssignmentStatement: transform_symbol_assignment_statement,
parsing.FurExpressionStatement: transform_expression_statement,
+ normalization.NormalArrayVariableInitializationStatement: transform_array_variable_initialization_statement,
normalization.NormalExpressionStatement: transform_expression_statement,
+ normalization.NormalFunctionDefinitionStatement: transform_function_definition_statement,
normalization.NormalIfElseStatement: transform_if_else_statement,
- normalization.NormalArrayVariableInitializationStatement: transform_array_variable_initialization_statement,
normalization.NormalVariableInitializationStatement: transform_variable_initialization_statement,
normalization.NormalVariableReassignmentStatement: transform_variable_reassignment_statement,
}[type(statement)](accumulators, statement)
'Accumulators',
[
'builtin_set',
+ 'function_definition_list',
'symbol_list',
'string_literal_list',
],
def transform(program):
accumulators = Accumulators(
builtin_set=set(),
+ function_definition_list=[],
symbol_list=[],
string_literal_list=[],
)
return CProgram(
builtin_set=accumulators.builtin_set,
+ function_definition_list=accumulators.function_definition_list,
statements=statement_list,
standard_libraries=standard_library_set,
string_literal_list=accumulators.string_literal_list,