Added variable-length args to function calls
authorDavid Kerkeslager <kerkeslager@gmail.com>
Tue, 8 Aug 2017 22:57:17 +0000 (18:57 -0400)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Tue, 8 Aug 2017 22:57:17 +0000 (18:57 -0400)
examples/15_varargs.fur [new file with mode: 0644]
examples/15_varargs.fur.output.txt [new file with mode: 0644]
generation.py
normalization.py
templates/program.c
transformation.py

diff --git a/examples/15_varargs.fur b/examples/15_varargs.fur
new file mode 100644 (file)
index 0000000..964ecfb
--- /dev/null
@@ -0,0 +1,2 @@
+print('Hello, world\n')
+print(42, '\n')
diff --git a/examples/15_varargs.fur.output.txt b/examples/15_varargs.fur.output.txt
new file mode 100644 (file)
index 0000000..ac2ea2c
--- /dev/null
@@ -0,0 +1,2 @@
+Hello, world
+42
index 149a5e2..1e1243a 100644 (file)
@@ -64,10 +64,12 @@ def generate_negation_expression(c_negation_expression):
         generate_expression(c_negation_expression.value)
     )
 
-def generate_function_call(c_function_call):
-    return '{}({})'.format(
-        c_function_call.name,
-        ', '.join(generate_expression(argument) for argument in c_function_call.arguments),
+def generate_function_call(function_call):
+    return '{}({}, {})'.format(
+        function_call.name,
+        function_call.argument_count,
+        # TODO This is just a single item containing a reference to the items list--make that clearer
+        generate_expression(function_call.argument_items),
     )
 
 def generate_expression_statement(statement):
@@ -81,6 +83,12 @@ def generate_symbol_assignment_statement(c_assignment_statement):
         generate_expression(c_assignment_statement.expression),
     )
 
+def generate_array_variable_initialization_statement(statement):
+    return 'Object {}[] = {{ {} }};'.format(
+        statement.variable,
+        ', '.join(generate_expression(i) for i in statement.items),
+    )
+
 def generate_variable_initialization_statement(statement):
     return 'Object {} = {};'.format(
         statement.variable,
@@ -110,6 +118,7 @@ def generate_statement(statement):
         transformation.CExpressionStatement: generate_expression_statement,
         transformation.CIfElseStatement: generate_if_else_statement,
         transformation.CSymbolAssignmentStatement: generate_symbol_assignment_statement,
+        transformation.CArrayVariableInitializationStatement: generate_array_variable_initialization_statement,
         transformation.CVariableInitializationStatement: generate_variable_initialization_statement,
         transformation.CVariableReassignmentStatement: generate_variable_reassignment_statement,
     }[type(statement)](statement)
index 1da6569..a41eb8d 100644 (file)
@@ -30,7 +30,16 @@ NormalFunctionCallExpression = collections.namedtuple(
     'NormalFunctionCallExpression',
     [
         'function',
-        'arguments',
+        'argument_count',
+        'argument_items',
+    ],
+)
+
+NormalArrayVariableInitializationStatement = collections.namedtuple(
+    'NormalArrayVariableInitializationStatement',
+    [
+        'variable',
+        'items',
     ],
 )
 
@@ -98,12 +107,21 @@ def normalize_function_call_expression(counter, expression):
         ))
         counter += 1
 
+    arguments_variable = '${}'.format(counter)
+    counter += 1
+
+    prestatements.append(NormalArrayVariableInitializationStatement(
+        variable=arguments_variable,
+        items=tuple(arguments),
+    ))
+
     return (
         counter,
         tuple(prestatements),
         NormalFunctionCallExpression(
-            expression.function, # TODO Normalize the function
-            arguments=tuple(arguments),
+            function=expression.function, # TODO Normalize the function
+            argument_count=len(arguments),
+            argument_items=NormalVariableExpression(variable=arguments_variable),
         ),
     )
 
index 8116e25..0c6f8f9 100644 (file)
@@ -272,8 +272,13 @@ Object builtin$or(Object left, Object right)
 }
 
 {% if 'pow' in builtins %}
-Object builtin$pow(Object base, Object exponent)
+Object builtin$pow(size_t argc, Object args[])
 {
+  assert(argc == 2);
+
+  Object base = args[0];
+  Object exponent = args[1];
+
   assert(base.type == INTEGER);
   assert(exponent.type == INTEGER);
 
@@ -285,25 +290,29 @@ Object builtin$pow(Object base, Object exponent)
 {% endif %}
 
 {% if 'print' in builtins %}
-void builtin$print(Object output)
+void builtin$print(size_t argc, Object args[])
 {
-  switch(output.type)
+  for(size_t i = 0; i < argc; i++)
   {
-    case BOOLEAN:
-      fputs(output.instance.boolean ? "true" : "false", stdout);
-      break;
+    Object output = args[i];
+    switch(output.type)
+    {
+      case BOOLEAN:
+        fputs(output.instance.boolean ? "true" : "false", stdout);
+        break;
 
-    case INTEGER:
-      printf("%" PRId32, output.instance.integer);
-      break;
+      case INTEGER:
+        printf("%" PRId32, output.instance.integer);
+        break;
 
-    case STRING:
-      // Using fwrite instead of printf to handle size_t length
-      printf("%s", output.instance.string);
-      break;
+      case STRING:
+        // Using fwrite instead of printf to handle size_t length
+        printf("%s", output.instance.string);
+        break;
 
-    default:
-      assert(false);
+      default:
+        assert(false);
+    }
   }
 }
 {% endif %}
index 4c1ef3b..ecfab9a 100644 (file)
@@ -60,7 +60,8 @@ CFunctionCallExpression = collections.namedtuple(
     'CFunctionCallExpression',
     [
         'name',
-        'arguments',
+        'argument_count',
+        'argument_items',
     ],
 )
 
@@ -73,6 +74,14 @@ CSymbolAssignmentStatement = collections.namedtuple(
     ],
 )
 
+CArrayVariableInitializationStatement = collections.namedtuple(
+    'CArrayVariableInitializationStatement',
+    [
+        'variable',
+        'items',
+    ],
+)
+
 CVariableInitializationStatement = collections.namedtuple(
     'CVariableInitializationStatement',
     [
@@ -257,17 +266,14 @@ def transform_negation_expression(accumulators, expression):
     )
 
 def transform_function_call_expression(accumulators, function_call):
-    # TODO Function should be a full expression
     if function_call.function.value in BUILTINS.keys():
         # TODO Check that the builtin is actually callable
         accumulators.builtin_set.add(function_call.function.value)
 
         return CFunctionCallExpression(
             name='builtin$' + function_call.function.value,
-            arguments=tuple(
-                transform_expression(accumulators, arg)
-                for arg in function_call.arguments
-            ),
+            argument_count=function_call.argument_count,
+            argument_items=transform_expression(accumulators, function_call.argument_items),
         )
 
     raise Exception()
@@ -289,6 +295,12 @@ def transform_if_else_statement(accumulators, statement):
         else_statements=tuple(transform_statement(accumulators, s) for s in statement.else_statements),
     )
 
+def transform_array_variable_initialization_statement(accumulators, statement):
+    return CArrayVariableInitializationStatement(
+        variable=statement.variable,
+        items=tuple(transform_expression(accumulators, i) for i in statement.items),
+    )
+
 def transform_variable_initialization_statement(accumulators, statement):
     return CVariableInitializationStatement(
         variable=statement.variable,
@@ -307,6 +319,7 @@ def transform_statement(accumulators, statement):
         parsing.FurExpressionStatement: transform_expression_statement,
         normalization.NormalExpressionStatement: transform_expression_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)