Added support for integers
authorDavid Kerkeslager <kerkeslager@gmail.com>
Fri, 4 Aug 2017 15:26:32 +0000 (11:26 -0400)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Fri, 4 Aug 2017 15:26:32 +0000 (11:26 -0400)
examples/02_the_answer_to_the_ultimate_question.fur [new file with mode: 0644]
examples/02_the_answer_to_the_ultimate_question.fur.output.txt [new file with mode: 0644]
generation.py
parsing.py
templates/program.c
tokenization.py
transformation.py

diff --git a/examples/02_the_answer_to_the_ultimate_question.fur b/examples/02_the_answer_to_the_ultimate_question.fur
new file mode 100644 (file)
index 0000000..517b47d
--- /dev/null
@@ -0,0 +1 @@
+print(42)
diff --git a/examples/02_the_answer_to_the_ultimate_question.fur.output.txt b/examples/02_the_answer_to_the_ultimate_question.fur.output.txt
new file mode 100644 (file)
index 0000000..f70d7bb
--- /dev/null
@@ -0,0 +1 @@
+42
\ No newline at end of file
index 9962bf3..56bd0a5 100644 (file)
@@ -1,12 +1,17 @@
 import jinja2
 
+import transformation
+
 ENV = jinja2.Environment(
     autoescape=jinja2.select_autoescape([]),
     loader=jinja2.FileSystemLoader('templates'),
     trim_blocks=True,
 )
 
-def generate_argument(c_string_literal):
+def generate_integer_literal(c_integer_literal):
+    return 'integerLiteral({})'.format(c_integer_literal.value)
+
+def generate_string_literal(c_string_literal):
     def c_escape(ch):
         return {
             '\n': r'\n',
@@ -18,6 +23,12 @@ def generate_argument(c_string_literal):
         ''.join(c_escape(ch for ch in c_string_literal.value)),
     )
 
+def generate_argument(c_argument):
+    return {
+        transformation.CIntegerLiteral: generate_integer_literal,
+        transformation.CStringLiteral: generate_string_literal,
+    }[type(c_argument)](c_argument)
+
 def generate_statement(c_function_call_statement):
     return '{}({});'.format(
         c_function_call_statement.name,
index 62ac92f..6b11745 100644 (file)
@@ -1,5 +1,12 @@
 import collections
 
+IntegerLiteral = collections.namedtuple(
+    'IntegerLiteral',
+    [
+        'value',
+    ],
+)
+
 StringLiteral = collections.namedtuple(
     'StringLiteral',
     [
@@ -7,6 +14,16 @@ StringLiteral = collections.namedtuple(
     ],
 )
 
+def _integer_literal_parser(index, tokens):
+    failure = (False, index, None)
+
+    if tokens[index].type != 'integer_literal':
+        return failure
+    value = int(tokens[index].match)
+    index += 1
+
+    return True, index, IntegerLiteral(value=value)
+
 def _string_literal_parser(index, tokens):
     failure = (False, index, None)
 
@@ -17,6 +34,17 @@ def _string_literal_parser(index, tokens):
 
     return True, index, StringLiteral(value=value)
 
+def _argument_parser(index, tokens):
+    failure = (False, index, None)
+
+    for parser in [_integer_literal_parser, _string_literal_parser]:
+        success, index, value = parser(index, tokens)
+
+        if success:
+            return (success, index, value)
+
+    return failure
+
 
 FunctionCall = collections.namedtuple(
     'FunctionCall',
@@ -38,7 +66,7 @@ def _function_call_parser(index, tokens):
         return failure
     index += 1
 
-    success, index, argument = _string_literal_parser(index, tokens)
+    success, index, argument = _argument_parser(index, tokens)
 
     if not success:
         return failure
index d027c52..ecabb17 100644 (file)
@@ -1,3 +1,6 @@
+#include <assert.h>
+#include <inttypes.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -7,6 +10,12 @@
 
 struct String;
 typedef struct String String;
+enum Type;
+typedef enum Type Type;
+union Instance;
+typedef union Instance Instance;
+struct Object;
+typedef struct Object Object;
 struct Runtime;
 typedef struct Runtime Runtime;
 
@@ -16,6 +25,24 @@ struct String
   char* characters;
 };
 
+enum Type
+{
+  INTEGER,
+  STRING
+};
+
+union Instance
+{
+  int32_t integer;
+  String* string;
+};
+
+struct Object
+{
+  Type type;
+  Instance instance;
+};
+
 struct Runtime
 {
   size_t permanentStringsLength;
@@ -64,21 +91,45 @@ void Runtime_addPermanentString(Runtime* self, String* string)
   self->permanentStringsLength++;
 }
 
-String* stringLiteral(Runtime* runtime, const char* literal)
+Object integerLiteral(int32_t literal)
 {
-  String* result = malloc(sizeof(String));
-  result->length = strlen(literal);
-  result->characters = malloc(result->length);
-  memcpy(result->characters, literal, result->length);
-  Runtime_addPermanentString(runtime, result);
+  Object result;
+  result.type = INTEGER;
+  result.instance.integer = literal;
+  return result;
+}
+
+Object stringLiteral(Runtime* runtime, const char* literal)
+{
+  String* resultString = malloc(sizeof(String));
+  resultString->length = strlen(literal);
+  resultString->characters = malloc(resultString->length);
+  memcpy(resultString->characters, literal, resultString->length);
+  Runtime_addPermanentString(runtime, resultString);
+
+  Object result;
+  result.type = STRING;
+  result.instance.string = resultString;
   return result;
 }
 
 {% if 'print' in builtins %}
-void builtin$print(String* output)
+void builtin$print(Object output)
 {
-  // Using fwrite instead of printf to handle size_t length
-  fwrite(output->characters, 1, output->length, stdout);
+  switch(output.type)
+  {
+    case INTEGER:
+      printf("%" PRId32, output.instance.integer);
+      break;
+
+    case STRING:
+      // Using fwrite instead of printf to handle size_t length
+      fwrite(output.instance.string->characters, 1, output.instance.string->length, stdout);
+      break;
+
+    default:
+      assert(false);
+  }
 }
 {% endif %}
 
index c1b30df..10ed80f 100644 (file)
@@ -29,6 +29,7 @@ def _make_token_matcher(definition):
 _TOKEN_MATCHERS = [
     ('open_parenthese',                 r'\('),
     ('close_parenthese',                r'\)'),
+    ('integer_literal',                 r'-?\s*\d+'),
     ('symbol',                          r'[a-z]+'),
     ('single_quoted_string_literal',    r"'.*?'"),
 ]
index 9ba0c0a..ef4e9bf 100644 (file)
@@ -2,6 +2,13 @@ import collections
 
 import parsing
 
+CIntegerLiteral = collections.namedtuple(
+    'CIntegerLiteral',
+    [
+        'value',
+    ],
+)
+
 CStringLiteral = collections.namedtuple(
     'CStringLiteral',
     [
@@ -31,10 +38,10 @@ BUILTINS = {
 }
 
 def transform_argument(builtin_dependencies, argument):
-    if isinstance(argument, parsing.StringLiteral):
-        return CStringLiteral(value=argument.value)
-
-    raise Exception()
+    return {
+        parsing.IntegerLiteral: CIntegerLiteral,
+        parsing.StringLiteral: CStringLiteral,
+    }[type(argument)](value=argument.value)
 
 def transform_function_call_statement(builtin_dependencies, function_call):
     if function_call.name in BUILTINS.keys():