]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
added recognition of method call syntax for functions
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 11 Aug 2018 17:54:40 +0000 (13:54 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 11 Aug 2018 17:54:40 +0000 (13:54 -0400)
example.src
source/lexer.l
source/parser.c
source/rt/gc.c
spec/parser_spec.rb
spec/spec_helper.rb

index 02b3cf164f728c45ddd6afcc8a4ae9ffb80570dc..2b1dcd77bff4a3f8fd8b0cbc7980f05719316651 100644 (file)
@@ -44,5 +44,5 @@ fun main(args string[]) int {
     fun main(args string[]) int {
         123
     }
+    foo.bar()
 }
-
index ce19730461d5052fa1b847cea4969a6c5a77ab6c..e5a45873822e80d9046da0d59371cd89b3f6d730 100644 (file)
@@ -53,6 +53,7 @@ NOSPACE [^ \t\r\n]
 "]"    { return ']';    }
 "{"    { return '{';    }
 "}"    { return '}';    }
+"."    { return '.';    }
 ","    { return ',';    }
 "'"    { return '\'';   }
 ":"    { return ':';    }
index 98ef30f31ba03b7a42a66129d1a7f07125e93831..99ce7fed6f8ce5d8781579b0c88ea007e744c553 100644 (file)
@@ -161,13 +161,24 @@ static AST* expression(Parser* p) {
         expression_block(p);
     } else if (matches(p, T_IF)) {
         if_expression(p);
+//    } else if (matches(p, T_ID)) {
+//        identifier(p);
+//        if (matches(p, '('))
+//            func_expr_list(p);
     } else if (matches(p, T_ID)) {
         identifier(p);
-        if (matches(p, '('))
-            func_expr_list(p);
     } else {
         constant(p);
     }
+
+    /* determine if this is a function call */
+    if (matches(p, '(')) {
+        func_expr_list(p);
+    } else if (accept(p, '.')) {
+        identifier(p);
+        func_expr_list(p);
+    }
+
     return NULL;
 }
 
index c4f0b9a323f5efd22b155b9c4d1d33c64606a073..3dec0eddd346e5586e1f7e98c7d2e556f59e404c 100644 (file)
@@ -58,3 +58,121 @@ void gc_setref(void** ref, void* val) {
 void* gc_getref(void** ref) {
     return (void*)((uintptr_t)*ref & ~DIRTY_BIT);
 }
+
+/*****************************************************************************/
+
+typedef struct hash_entry_t {
+    struct hash_entry_t* next;
+    uintptr_t hash;
+} hash_entry_t;
+
+typedef struct {
+    size_t size;
+    size_t bktid;
+    hash_entry_t** buckets;
+} hash_t;
+
+static void hash_set(hash_t* hash, hash_entry_t* entry);
+
+#define NUM_PRIMES (sizeof(Primes)/sizeof(unsigned int))
+
+static unsigned int Primes[] = {
+    5, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
+    49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
+    12582917, 25165843, 50331653, 100663319, 201326611, 402653189,
+    805306457, 1610612741
+};
+
+static void hash_init(hash_t* hash) {
+    hash->size = 0;
+    hash->bktid = 0;
+    hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), Primes[hash->bktid]);
+}
+
+static void find_entry(hash_entry_t** parent, hash_entry_t** current, hash_entry_t* entry) {
+    while(*current != NULL) {
+        if (((*current)->hash == entry->hash) &&
+            ((*current)->object == entry->object))
+            break;
+        *parent  = *current;
+        *current = (*current)->next;
+    }
+}
+
+static void rehash(hash_t* hash) {
+    unsigned int oldcount, i;
+    hash_entry_t** oldbuckets;
+    hash_entry_t *node, *entry;
+    if ((hash->bktid + 1) < NUM_PRIMES) {
+        oldcount = hash->bktid++;
+        oldbuckets = hash->buckets;
+        hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), Primes[hash->bktid]);
+        hash->size = 0;
+        /* Iterate over all of the old buckets */
+        for (i = 0; i < Primes[oldcount]; i++) {
+            node = oldbuckets[i];
+            /* re-insert all entries in the bucket into the new bucket table */
+            while (node != NULL) {
+                entry = node;
+                node = entry->next;
+                hash_set(hash, entry);
+            }
+        }
+        /* Free the old bucket table */
+        free(oldbuckets);
+    }
+}
+
+static uint64_t hash64(uint64_t key) {
+    key = (~key) + (key << 21);
+    key = key ^ (key >> 24);
+    key = (key + (key << 3)) + (key << 8);
+    key = key ^ (key >> 14);
+    key = (key + (key << 2)) + (key << 4);
+    key = key ^ (key >> 28);
+    key = key + (key << 31);
+    return key;
+}
+
+static void hash_set(hash_t* hash, hash_entry_t* entry) {
+    unsigned int index;
+    hash_entry_t *parent, *node, *deadite;
+    if (hash->size >= Primes[hash->bktid])
+        rehash(hash);
+    entry->hash = hash64((uint64_t)(entry->object));
+    index   = (entry->hash % Primes[hash->bktid]);
+    parent  = NULL;
+    node    = hash->buckets[index];
+    deadite = NULL;
+    find_entry(&parent, &node, entry);
+    if ((parent == NULL) && (node == NULL)) {
+        hash->buckets[index] = entry;
+        entry->next = NULL;
+        hash->size++;
+    } else if (node == NULL) {
+        parent->next = entry;
+        entry->next = NULL;
+        hash->size++;
+    }
+}
+
+static hash_entry_t* hash_del(hash_t* hash, hash_entry_t* entry) {
+    unsigned int index;
+    hash_entry_t *parent, *node, *ret = NULL;
+    entry->hash = hash64((uint64_t)(entry->object));
+    index = (entry->hash % Primes[hash->bktid]);
+    parent = NULL;
+    node = hash->buckets[index];
+    find_entry(&parent, &node, entry);
+    if (node != NULL) {
+        ret = node;
+        node = node->next;
+        if (parent != NULL)
+            parent->next = node;
+        else
+            hash->buckets[index] = node;
+        hash->size--;
+    }
+    return ret;
+}
+
index 0452253fafbae53075caa218fe275c2e1704266d..ec3807eab63604dde25b1d2754b907c8dc36aa2d 100644 (file)
@@ -1,9 +1,9 @@
 require 'open3'
 
 describe "sclpl grammar" do
-#  context "definitions" do
+  context "definitions" do
 #    it "should parse a value definition with type annotation" do
-#      expect(ast('def foo int 123;')).to eq([ ['def', 'foo', 'T_INT:123'] ])
+#      expect(ast('123')).to eq([ ['def', 'foo', 'T_INT:123'] ])
 #    end
 #
 #    it "should parse a function definition with return type annotation" do
@@ -48,7 +48,7 @@ describe "sclpl grammar" do
 #        ['def', 'foo', ['fn', ['T_ID:a', 'T_ID:b', 'T_ID:c'],
 #          ["let", ["$:0", "T_INT:123"], "$:0"]]]])
 #    end
-#  end
+  end
 #
 #  context "literals" do
 #    it "should parse a string" do
index 142c88f15a9b1941b2aa17e083c4697be373fb16..37828ae43c27b60c3677b5f7944012fb5299ee9d 100644 (file)
@@ -30,7 +30,7 @@ def re_structure( token_array, offset = 0 )
 end
 
 def ast(input, pass="ast")
-  out = cli(["-A#{pass}"], input)
+  out = cli(["-A#{pass}"], "fun test() int { #{input} }")
   # Prep the parens for reading
   out.gsub!(/([()])|tree/,' \1 ')
   # Replace string literals so we can tokenize on spaces