Add support for nested functions with the same name in different contexts
authorDavid Kerkeslager <kerkeslager@gmail.com>
Sat, 6 Jan 2018 20:12:55 +0000 (15:12 -0500)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Sat, 6 Jan 2018 20:12:55 +0000 (15:12 -0500)
examples/31_nested_functions_same_name.fur [new file with mode: 0644]
examples/31_nested_functions_same_name.fur.stdout.txt [new file with mode: 0644]
generation.py
templates/function_definition.c
transformation.py

diff --git a/examples/31_nested_functions_same_name.fur b/examples/31_nested_functions_same_name.fur
new file mode 100644 (file)
index 0000000..3cbeb0c
--- /dev/null
@@ -0,0 +1,18 @@
+def get_incrementer(n) do
+  def foo(m) do
+    m + n
+  end
+
+  foo
+end
+
+def get_multiplier(n) do
+  def foo(m) do
+    m * n
+  end
+
+  foo
+end
+
+print(get_incrementer(2)(3), '\n')
+print(get_multiplier(2)(3), '\n')
diff --git a/examples/31_nested_functions_same_name.fur.stdout.txt b/examples/31_nested_functions_same_name.fur.stdout.txt
new file mode 100644 (file)
index 0000000..6613b56
--- /dev/null
@@ -0,0 +1,2 @@
+5
+6
index 74a3fa5..e167f25 100644 (file)
@@ -34,8 +34,9 @@ def generate_structure_literal_expression(expression):
     )
 
 def generate_lambda_expression(expression):
-    return '(Object){{ CLOSURE, (Instance)(Closure){{ environment, user${}$implementation }} }}'.format(
+    return '(Object){{ CLOSURE, (Instance)(Closure){{ environment, user${}${}$implementation }} }}'.format(
         expression.name,
+        expression.index,
     )
 
 def generate_list_construct_expression(expression):
@@ -165,6 +166,7 @@ def generate_function_definition(definition):
     template = ENV.get_template('function_definition.c')
     return template.render(
         name=definition.name,
+        index=definition.index,
         argument_name_list=definition.argument_name_list,
         statement_list=list(generate_statement(s) for s in definition.statement_list),
     )
index 034a2af..ccf3e75 100644 (file)
@@ -1,5 +1,5 @@
 
-Object user${{name}}$implementation(
+Object user${{name}}${{index}}$implementation(
     EnvironmentPool* environmentPool,
     Environment* environment,
     size_t argc,
index 6f46d43..a9cad95 100644 (file)
@@ -122,6 +122,7 @@ CFunctionDefinition = collections.namedtuple(
     'CFunctionDefinition',
     [
         'name',
+        'index',
         'argument_name_list',
         'statement_list',
     ],
@@ -192,6 +193,7 @@ CLambdaExpression = collections.namedtuple(
     'CLambdaExpression',
     (
         'name',
+        'index',
     ),
 )
 
@@ -211,24 +213,25 @@ def transform_structure_literal_expression(accumulators, expression):
     )
 
 def transform_lambda_expression(accumulators, expression):
-    # TODO This function feels hacky
-    if len(accumulators.lambda_number_list) == 0:
-        accumulators.lambda_number_list.append(0)
-    else:
-        accumulators.lambda_number_list.append(accumulators.lambda_number_list[-1] + 1)
-
     if expression.name is None:
-        name = '__lambda_{}'.format(accumulators.lambda_number_list[-1])
+        name = '__lambda'
     else:
         name = expression.name
 
+    index = accumulators.function_name_iterators.get(name, 0)
+    accumulators.function_name_iterators[name] = index + 1
+
     accumulators.function_definition_list.append(CFunctionDefinition(
         name=name,
+        index=index,
         argument_name_list=expression.argument_name_list,
         statement_list=tuple(transform_statement(accumulators, s) for s in expression.statement_list),
     ))
 
-    return CLambdaExpression(name=name)
+    return CLambdaExpression(
+        name=name,
+        index=index,
+    )
 
 
 def transform_list_construct_expression(accumulators, expression):
@@ -347,7 +350,7 @@ Accumulators = collections.namedtuple(
     [
         'builtin_set',
         'function_definition_list',
-        'lambda_number_list',
+        'function_name_iterators',
         'operator_set',
         'symbol_list',
         'string_literal_list',
@@ -358,7 +361,7 @@ def transform(program):
     accumulators = Accumulators(
         builtin_set=set(),
         function_definition_list=[],
-        lambda_number_list=[],
+        function_name_iterators={},
         operator_set=set(),
         symbol_list=[],
         string_literal_list=[],