Author: Remi Meier <[email protected]>
Branch: c8-private-pages
Changeset: r1549:81b95867774a
Date: 2015-01-19 16:07 +0100
http://bitbucket.org/pypy/stmgc/changeset/81b95867774a/

Log:    add c8 version of duhton

diff too long, truncating to 2000 out of 3255 lines

diff --git a/duhton-c8/Makefile b/duhton-c8/Makefile
new file mode 100644
--- /dev/null
+++ b/duhton-c8/Makefile
@@ -0,0 +1,23 @@
+
+C8SOURCES = ../c8/stmgc.c ../c8/stm/*.c
+
+C8HEADERS = ../c8/stmgc.h ../c8/stm/*.h
+
+COMMON = -pthread -lrt -g -Wall
+
+
+all: duhton_debug duhton duhton_release
+
+duhton: *.c *.h $(C8SOURCES) $(C8HEADERS)
+       clang $(COMMON) -O2 -o duhton *.c ../c8/stmgc.c
+
+duhton_release: *.c *.h $(C8SOURCES) $(C8HEADERS)
+       clang $(COMMON) -DNDEBUG -O2 -o duhton_release *.c ../c8/stmgc.c
+
+
+duhton_debug: *.c *.h $(C8SOURCES) $(C8HEADERS)
+       clang -DSTM_DEBUGPRINT $(COMMON) -DDu_DEBUG -o duhton_debug *.c 
../c8/stmgc.c
+
+
+clean:
+       rm -f duhton duhton_debug duhton_release
diff --git a/duhton-c8/ceval.c b/duhton-c8/ceval.c
new file mode 100644
--- /dev/null
+++ b/duhton-c8/ceval.c
@@ -0,0 +1,13 @@
+#include "duhton.h"
+
+
+DuObject *Du_Eval(DuObject *ob, DuObject *locals)
+{
+    eval_fn fn = Du_TYPE(ob)->dt_eval;
+    if (fn) {
+        return fn(ob, locals);
+    }
+    else {
+        return ob;
+    }
+}
diff --git a/duhton-c8/compile.c b/duhton-c8/compile.c
new file mode 100644
--- /dev/null
+++ b/duhton-c8/compile.c
@@ -0,0 +1,114 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "duhton.h"
+
+
+DuObject *_Du_Parse(FILE *f, int level, int stop_after_newline)
+{
+    DuObject *cons, *list;
+    int c, i;
+
+    list = DuList_New();
+    if (level == 0) {
+        _du_save1(list);
+        DuObject *item = DuSymbol_FromString("progn");
+        _du_restore1(list);
+        _du_save1(list);
+        DuList_Append(list, item);
+        _du_restore1(list);
+    }
+    c = fgetc(f);
+    while (1) {
+        DuObject *item;
+
+        switch (c) {
+
+        case EOF:
+            if (level > 0)
+                Du_FatalError("more '(' than ')'");
+            if (stop_after_newline) {
+                return NULL;
+            }
+            goto done;
+
+        case '(':
+            _du_save1(list);
+            item = _Du_Parse(f, level + 1, 0);
+            _du_restore1(list);
+            c = fgetc(f);
+            break;
+
+        case ')':
+            if (level == 0)
+                Du_FatalError("more ')' than '('");
+            goto done;
+
+        case '\n':
+            if (stop_after_newline)
+                goto done;
+            c = fgetc(f);
+            continue;
+
+        case ';':
+            while (c != '\n' && c != EOF)
+                c = fgetc(f);
+            continue;
+
+        default:
+            if (isspace(c)) {
+                c = fgetc(f);
+                continue;
+            }
+            else {
+                char token[201];
+                char *p = token;
+                char *end;
+                int number;
+                do {
+                    *p++ = c;
+                    c = fgetc(f);
+                } while (!(isspace(c) || c == '(' || c == ')' || c == EOF));
+                *p = '\0';
+                number = strtol(token, &end, 0);
+                _du_save1(list);
+                if (*end == '\0') {
+                    item = DuInt_FromInt(number);
+                }
+                else {
+                    item = DuSymbol_FromString(token);
+                }
+                _du_restore1(list);
+                break;
+            }
+        }
+        _du_save1(list);
+        DuList_Append(list, item);
+        _du_restore1(list);
+    }
+
+ done:
+    cons = Du_None;
+    for (i = DuList_Size(list) - 1; i >= 0; i--) {
+        DuObject *item = DuList_GetItem(list, i);
+        _du_save1(list);
+        cons = DuCons_New(item, cons);
+        _du_restore1(list);
+    }
+    return cons;
+}
+
+
+DuObject *Du_Compile(char *filename, int stop_after_newline)
+{
+    FILE *f;
+    if (strcmp(filename, "-") == 0)
+        f = stdin;
+    else
+        f = fopen(filename, "r");
+    if (!f) Du_FatalError("cannot open '%s'", filename);
+    DuObject *cons = _Du_Parse(f, 0, stop_after_newline);
+    if (f != stdin)
+        fclose(f);
+    return cons;
+}
diff --git a/duhton-c8/consobject.c b/duhton-c8/consobject.c
new file mode 100644
--- /dev/null
+++ b/duhton-c8/consobject.c
@@ -0,0 +1,93 @@
+#include "duhton.h"
+
+
+void cons_trace(struct DuConsObject_s *ob, void visit(object_t **))
+{
+    visit((object_t **)&ob->car);
+    visit((object_t **)&ob->cdr);
+}
+
+void cons_print(DuConsObject *ob)
+{
+    DuObject *p;
+    printf("( ");
+    while (1) {
+        /* _du_read1(ob); IMMUTABLE */
+        _du_save1(ob);
+        Du_Print(ob->car, 0);
+        _du_restore1(ob);
+        p = ob->cdr;
+        if (!DuCons_Check(p))
+            break;
+        ob = (DuConsObject *)p;
+        printf(" ");
+    }
+    if (p != Du_None) {
+        printf(" . ");
+        Du_Print(p, 0);
+    }
+    printf(" )");
+}
+
+
+
+DuObject *cons_eval(DuConsObject *ob, DuObject *locals)
+{
+    /* _du_read1(ob); IMMUTABLE */
+    return _DuFrame_EvalCall(locals, ob->car, ob->cdr, 1);
+}
+
+DuType DuCons_Type = {
+    "cons",
+    DUTYPE_CONS,
+    sizeof(DuConsObject),
+    (trace_fn)cons_trace,
+    (print_fn)cons_print,
+    (eval_fn)cons_eval,
+};
+
+DuObject *DuCons_New(DuObject *car, DuObject *cdr)
+{
+    _du_save2(car, cdr);
+    DuConsObject *ob = (DuConsObject *)DuObject_New(&DuCons_Type);
+    _du_restore2(car, cdr);
+    ob->car = car;
+    ob->cdr = cdr;
+    return (DuObject *)ob;
+}
+
+DuObject *DuCons_Car(DuObject *cons)
+{
+    DuCons_Ensure("DuCons_Car", cons);
+    /* _du_read1(cons); IMMUTABLE */
+    return ((DuConsObject *)cons)->car;
+}
+
+DuObject *DuCons_Cdr(DuObject *cons)
+{
+    DuCons_Ensure("DuCons_Cdr", cons);
+    /* _du_read1(cons); IMMUTABLE */
+    return ((DuConsObject *)cons)->cdr;
+}
+
+DuObject *_DuCons_CAR(DuObject *cons)
+{
+    assert(DuCons_Check(cons));
+    return ((DuConsObject *)cons)->car;
+}
+
+DuObject *_DuCons_NEXT(DuObject *cons)
+{
+    assert(DuCons_Check(cons));
+    DuObject *result = ((DuConsObject *)cons)->cdr;
+    if (result != Du_None && !DuCons_Check(cons))
+        Du_FatalError("_DuCons_NEXT: not a well-formed cons list");
+    return result;
+}
+
+void DuCons_Ensure(char *where, DuObject *ob)
+{
+    if (!DuCons_Check(ob))
+        Du_FatalError("%s: expected 'cons' argument, got '%s'",
+                      where, Du_TYPE(ob)->dt_name);
+}
diff --git a/duhton-c8/containerobject.c b/duhton-c8/containerobject.c
new file mode 100644
--- /dev/null
+++ b/duhton-c8/containerobject.c
@@ -0,0 +1,61 @@
+#include "duhton.h"
+
+typedef TLPREFIX struct DuContainerObject_s {
+    DuOBJECT_HEAD1
+    DuObject *ob_reference;
+} DuContainerObject;
+
+
+void container_trace(struct DuContainerObject_s *ob, void visit(object_t **))
+{
+    visit((object_t **)&ob->ob_reference);
+}
+
+void container_print(DuContainerObject *ob)
+{
+    printf("<container ");
+    Du_Print(ob->ob_reference, 0);
+    printf(">");
+}
+
+DuObject *DuContainer_GetRef(DuObject *ob)
+{
+    DuContainer_Ensure("DuContainer_GetRef", ob);
+
+    _du_read1(ob);
+    return ((DuContainerObject *)ob)->ob_reference;
+}
+
+void DuContainer_SetRef(DuObject *ob, DuObject *x)
+{
+    DuContainer_Ensure("DuContainer_SetRef", ob);
+
+    _du_write1(ob);
+    ((DuContainerObject *)ob)->ob_reference = x;
+}
+
+DuType DuContainer_Type = {
+    "container",
+    DUTYPE_CONTAINER,
+    sizeof(DuContainerObject),
+    (trace_fn)container_trace,
+    (print_fn)container_print,
+};
+
+DuObject *DuContainer_New(DuObject *x)
+{
+    _du_save1(x);
+    DuContainerObject *ob =                                     \
+        (DuContainerObject *)DuObject_New(&DuContainer_Type);
+    _du_restore1(x);
+
+    ob->ob_reference = x;
+    return (DuObject *)ob;
+}
+
+void DuContainer_Ensure(char *where, DuObject *ob)
+{
+    if (!DuContainer_Check(ob))
+        Du_FatalError("%s: expected 'container' argument, got '%s'",
+                      where, Du_TYPE(ob)->dt_name);
+}
diff --git a/duhton-c8/demo/container_transaction.duh 
b/duhton-c8/demo/container_transaction.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/container_transaction.duh
@@ -0,0 +1,20 @@
+
+(setq c (container 0))
+
+(defun g (thread n)
+    (set c (+ (get c) 1))
+    (if (> (get c) 20000)
+        (print (quote overflow) (get c))
+      (if (< n 10000)
+          (transaction f thread (+ n 1))
+        (if (< (get c) 20000)
+            (print (quote not-enough))
+          (print (quote ok))))))
+
+(defun f (thread n)
+    (print (quote <) thread n (quote >))
+    (g thread n))
+
+(transaction f (quote t1) 1)
+(transaction f (quote t2) 1)
+(transaction f (quote t3) 1)
diff --git a/duhton-c8/demo/list_transaction.duh 
b/duhton-c8/demo/list_transaction.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/list_transaction.duh
@@ -0,0 +1,17 @@
+
+(setq lst (list 0))
+(defun g (n)
+    (set lst 0 (+ (get lst 0) 1))
+    (if (< n 10)
+        (transaction f (+ n 1))
+      (sleepms 20)
+      (if (< (get lst 0) 20)
+          (print (quote not-enough))
+        (print (quote ok)))))
+(defun f (n)
+  (if (defined? marker)
+      (print (quote marker-already-defined)))
+  (setq marker 0)
+  (g n))
+(transaction f 1)
+(transaction f 1)
diff --git a/duhton-c8/demo/many_square_roots.duh 
b/duhton-c8/demo/many_square_roots.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/many_square_roots.duh
@@ -0,0 +1,17 @@
+
+
+(defun square-root (n)
+  (setq i 0)
+  (while (< (* i i) n)
+    (setq i (+ i 1)))
+  i)
+
+(defun show-square-root (n)
+  (setq s (square-root n))
+  (print (quote square-root-of) n (quote is) s))
+
+
+(setq n 0)
+(while (< n 200)
+  (transaction show-square-root (+ 1000000000 (* n 100000)))
+  (setq n (+ n 1)))
diff --git a/duhton-c8/demo/micro_transactions.duh 
b/duhton-c8/demo/micro_transactions.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/micro_transactions.duh
@@ -0,0 +1,27 @@
+
+
+
+;;(setq c (container 0))
+
+
+(defun increment ()
+  )
+
+
+(defun big_transactions ()
+  (setq n 0)
+  (while (< n 20000)
+    (transaction increment)
+    (setq n (+ n 1))
+    )
+  )
+
+(setq n 0)
+(while (< n 800)
+  (transaction big_transactions)
+  (setq n (+ n 1))
+  )
+
+(setq timer (time))
+(run-transactions)
+(print (quote TIME_IN_PARALLEL:) (- (time) timer))
diff --git a/duhton-c8/demo/minimal.duh b/duhton-c8/demo/minimal.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/minimal.duh
@@ -0,0 +1,3 @@
+
+(print (+ 40 2))
+(print (- 45 3))
diff --git a/duhton-c8/demo/nqueens.duh b/duhton-c8/demo/nqueens.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/nqueens.duh
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+(defun abs (i)
+  (if (<= 0 i)
+      i
+    (- 0 i)))
+
+(defun clean_list (n)
+  (setq i n)
+  (setq res (list))
+  (while (> i 0)
+    (append res 0)
+    (setq i (- i 1))
+    )
+  res
+  )
+
+(defun copy_list (xs)
+  (setq res (list))
+  (setq idx 0)
+  (while (< idx (len xs))
+    (append res (get xs idx))
+    (setq idx (+ idx 1))
+    )
+  res
+  )
+
+
+(defun attacks (hist col i j)
+  (|| (== (get hist j) i)
+      (== (abs (- (get hist j) i))
+          (- col j)))
+  )
+
+(defun print_solution (hist n)
+  (print (quote solution) n)
+  (setq i 0)
+  (while (< i n)
+    (setq line (list))
+    (setq j 0)
+    (while (< j n)
+      (if (== j (get hist i))
+          (append line (quote Q))
+        (if (== 0 (% (+ i j) 2))
+            (append line (quote .))
+          (append line (quote ,))
+          )
+        )
+      (setq j (+ j 1))
+      )
+
+    (print line)
+    (setq i (+ i 1))
+    )
+  )
+
+(defun solve (n col hist count)
+  (if (== col n)
+      (progn
+        (set count (+ (get count) 1))
+        ;; (print_solution hist n)
+        )
+
+    ;; else
+    (setq i 0)
+    (while (< i n)
+      (setq j 0)
+      (while (&& (< j col)
+                 (not (attacks hist col i j)))
+        (setq j (+ j 1))
+        )
+
+      (if (>= j col)
+          (progn
+            (set hist col i)
+            (solve n (+ col 1) hist count)
+            ))
+      
+      (setq i (+ i 1))
+      )
+    )
+  )
+
+
+(defun solve_parallel (n col hist count)
+  (if (== col n)
+      (progn
+        (set count (+ (get count) 1))
+        ;; (print_solution hist n)
+        )
+
+    ;; else
+    (setq i 0)
+    (setq transaction-limit 1)
+    (if (== col transaction-limit)
+        (setq counts (list)))
+    
+    (while (< i n)
+      (setq j 0)
+      (while (&& (< j col)
+                 (not (attacks hist col i j)))
+        (setq j (+ j 1))
+        )
+
+      (if (>= j col)
+          (progn
+            (set hist col i)
+            (if (== col transaction-limit)
+                (progn
+                  (setq new_cont (container 0))
+                  (append counts new_cont)
+                  (transaction solve n (+ col 1) (copy_list hist) new_cont)
+                  )
+              (solve_parallel n (+ col 1) hist count)
+              )
+            )
+        )
+      ;; iterator
+      (setq i (+ i 1))
+      )
+    
+    (if (== col transaction-limit)
+        (progn
+          (run-transactions)
+          (setq i 0)
+          (while (< i (len counts))
+            (set count (+ (get count) (get (get counts i))))
+            (setq i (+ i 1))
+            )
+          )
+      )
+    )
+  )
+
+
+
+
+
+(setq count (container 0))
+
+(setq n 11)
+(solve_parallel n 0 (clean_list n) count)
+(print (quote solutions:) (get count))
+
diff --git a/duhton-c8/demo/run_transactions.duh 
b/duhton-c8/demo/run_transactions.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/run_transactions.duh
@@ -0,0 +1,25 @@
+
+(setq c (container 0))
+
+(defun g (n)
+  (setq i n)
+  (while (< 0 i)
+    (set c (+ (get c) 1))
+    (setq i (- i 1))
+    )
+  )
+
+(defun f (thread n)
+  (g n)
+  )
+
+(transaction f (quote t1) 10000)
+(transaction f (quote t2) 20000)
+(transaction f (quote t3) 10002)
+(run-transactions)
+(transaction f (quote t1) 15)
+(transaction f (quote t2) 15)
+(run-transactions)
+(print (quote result) (get c))
+(print (quote finished))
+
diff --git a/duhton-c8/demo/simple_transaction.duh 
b/duhton-c8/demo/simple_transaction.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/simple_transaction.duh
@@ -0,0 +1,10 @@
+
+
+(defun do_stuff (i)
+  (if (> (* i i) 10)
+    (print i)))
+
+(setq i 0)
+(while (< i 10)
+  (transaction do_stuff i)
+  (setq i (+ i 1)))
diff --git a/duhton-c8/demo/sort.duh b/duhton-c8/demo/sort.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/sort.duh
@@ -0,0 +1,197 @@
+
+
+
+
+(setq c (container (list 1 2 3 4)))
+
+
+(setq _rand (container (list 133542157 362436069 521288629 88675123)))
+(defun xor128 ()
+  (setq lst (get _rand))
+  (setq x (get lst 0))
+  (setq y (get lst 1))
+  (setq z (get lst 2))
+  (setq w (get lst 3))
+  
+  (setq t (^ x (<< x 11)))
+  (setq x y)
+  (setq y z)
+  (setq z w)
+
+  (setq w (^ w (^ (>> w 19) (^ t (>> t 8)))))
+  (set lst 0 x)
+  (set lst 1 y)
+  (set lst 2 z)
+  (set lst 3 w)
+  w
+  )
+
+
+(defun random_list (n)
+  (setq i n)
+  (setq res (list))
+  (while (> i 0)
+    (append res (% (xor128) 10))
+    (setq i (- i 1))
+    )
+  res
+  )
+
+
+
+(defun merge_lists (as bs)
+  ;; merges the two lists and returns a new one
+  (setq res (list))
+  (setq idxa 0)
+  (setq idxb 0)
+  (while (&& (< idxa (len as))
+             (< idxb (len bs)))
+    (if (> (get as idxa) (get bs idxb))
+        (progn
+          (append res (get bs idxb))
+          (setq idxb (+ idxb 1))
+          )
+      (append res (get as idxa))
+      (setq idxa (+ idxa 1))
+      )
+    )
+
+  (if (< idxa (len as))
+      (progn
+        (setq xs as)
+        (setq idxx idxa)
+        )
+    (setq xs bs)
+    (setq idxx idxb))
+  
+  (while (< idxx (len xs))
+    (append res (get xs idxx))
+    (setq idxx (+ idxx 1)))
+  
+  res
+  )
+
+
+(defun split_list (xs)
+  ;; empties xs and fills 2 new lists to be returned
+  (setq half_len (/ (len xs) 2))
+  (setq first (list))
+  (setq second (list))
+  (setq xidx 0)
+  
+  (while (< xidx (len xs))
+    (if (< xidx half_len)
+        (append first (get xs xidx))
+      (append second (get xs xidx))
+      )
+    (setq xidx (+ xidx 1))
+    )
+
+  (list first second)
+  )
+
+
+
+(defun merge_sort (xs)
+  (if (<= (len xs) 1)                   ; 1 elem
+      xs
+    (progn                              ; many elems
+      (setq lists (split_list xs))
+      
+      (setq left (merge_sort (get lists 0)))
+      (setq right (merge_sort (get lists 1)))
+      ;; (print left right)
+      (merge_lists left right)
+      )
+    )
+  )
+
+(defun merge_sort_transaction (xs res-cont)
+  (set res-cont (merge_sort xs))
+  )
+
+(defun merge_sort_parallel (xs)
+  (if (<= (len xs) 1)                   ; 1 elem
+      xs
+    (progn                              ; many elems
+      (setq lists (split_list xs))
+      (setq left-c (container None))
+      (setq right-c (container None))
+      
+      (transaction merge_sort_transaction
+                   (get lists 0) left-c)
+      (transaction merge_sort_transaction
+                   (get lists 1) right-c)
+      
+      (setq current (time))
+      (print (quote before-parallel))
+      (run-transactions)
+      (print (quote time-parallel:) (- (time) current))
+      
+      (setq left (get left-c))
+      (setq right (get right-c))
+      (assert (<= (len left) (+ (len right) 2)))
+      (assert (<= (len right) (+ (len left) 2)))
+      ;; (print left right)
+      (merge_lists left right)
+      )
+    )
+  )
+
+
+(defun copy_list (xs)
+  (setq res (list))
+  (setq idx 0)
+  (while (< idx (len xs))
+    (append res (get xs idx))
+    (setq idx (+ idx 1))
+    )
+  res
+  )
+
+(defun print_list (xs)
+  (print (quote len:) (len xs) (quote ->) xs)
+  )
+
+(defun is_sorted (xs)
+  (setq idx 0)
+  (while (< idx (- (len xs) 1))
+    (assert (<=
+             (get xs idx)
+             (get xs (+ idx 1))))
+    (setq idx (+ idx 1))
+    )
+  (quote true)
+  )
+
+
+;; (setq as (random_list 20))
+;; (setq bs (random_list 20))
+;; (print as)
+;; (print bs)
+;; (print (split_list as))
+
+(setq current (time))
+(print (quote before-random))
+(setq cs (random_list 300000))
+(print (quote time-random:) (- (time) current))
+
+;; (print_list cs)
+
+;; (setq res (container None))
+;; (transaction merge_sort_transaction cs res)
+;; (run-transactions)
+;; (print (is_sorted (get res)))
+
+(setq current (time))
+(print (quote before-sorting))
+(setq sorted (merge_sort_parallel cs))
+(print (quote time-sorting:) (- (time) current))
+
+
+(setq current (time))
+(print (quote before-check))
+(print (quote sorted:) (is_sorted sorted))
+(print (quote time-check:) (- (time) current))
+
+
diff --git a/duhton-c8/demo/square_root.duh b/duhton-c8/demo/square_root.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/square_root.duh
@@ -0,0 +1,9 @@
+
+
+(defun square_root (n)
+  (setq i 0)
+  (while (< (* i i) n)
+    (setq i (+ i 1)))
+  i)
+
+(print (square_root 1000000000))
diff --git a/duhton-c8/demo/synth.duh b/duhton-c8/demo/synth.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/synth.duh
@@ -0,0 +1,98 @@
+
+
+
+(defun clean_list (n)
+  (setq i n)
+  (setq res (list))
+  (while (> i 0)
+    (append res 0)
+    (setq i (- i 1))
+    )
+  res
+  )
+
+
+(setq _rand (container (list 133542157 362436069 521288629 88675123)))
+(defun xor128 ()
+  (setq lst (get _rand))
+  (setq x (get lst 0))
+  (setq y (get lst 1))
+  (setq z (get lst 2))
+  (setq w (get lst 3))
+  
+  (setq t (^ x (<< x 11)))
+  (setq x y)
+  (setq y z)
+  (setq z w)
+
+  (setq w (^ w (^ (>> w 19) (^ t (>> t 8)))))
+  (set lst 0 x)
+  (set lst 1 y)
+  (set lst 2 z)
+  (set lst 3 w)
+  w
+  )
+
+
+(defun random_list (n max)
+  (setq i n)
+  (setq res (list))
+  (while (> i 0)
+    (append res (% (xor128) max))
+    (setq i (- i 1))
+    )
+  res
+  )
+
+
+
+
+(defun worker (shared private)
+  (setq i 1)
+  (while (< i 10000)
+    ;; every 200th modification is on 'shared'
+    (if (== (% i 200) 0)
+        (set shared (+ (get shared) 1))
+      (set private (+ (get private) 1))
+      )
+    
+    (setq i (+ i 1))
+    )
+  )
+
+
+
+(setq N 1000)
+;; CONFL_IF_BELOW / RAND_MAX == ratio of conflicting transactions
+;;                              to non conflicting ones
+(setq RAND_MAX 8)
+(setq CONFL_IF_BELOW 1)
+
+(print (quote N:) N)
+(print (quote RAND_MAX:) RAND_MAX)
+(print (quote CONFL_IF_BELOW:) CONFL_IF_BELOW)
+
+(setq timer (time))
+(print (quote setup-transactions:) timer)
+
+(setq shared (container 0))
+(setq rand-list (random_list N RAND_MAX))
+(setq i 0)
+(while (< i N)
+  (setq private (container 0))
+  (if (< (get rand-list i) CONFL_IF_BELOW)
+      ;; conflicting transaction
+      (transaction worker shared private)
+    ;; else non-conflicting
+    (transaction worker private private)
+    )
+
+  (setq i (+ i 1))
+  )
+
+(print (quote setup-time-diff:) (- (time) timer))
+(setq timer (time))
+(run-transactions)
+(print (quote run-time-diff:) (- (time) timer))
+(print (quote shared) (get shared))
+
diff --git a/duhton-c8/demo/trees.duh b/duhton-c8/demo/trees.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/trees.duh
@@ -0,0 +1,18 @@
+
+(defun create-tree (n)
+   (if (== n 0) 1 (cons (create-tree (- n 1)) (create-tree (- n 1))))
+)
+
+(defun walk-tree (tree)
+   (if (pair? tree)
+      (+ (walk-tree (car tree)) (walk-tree (cdr tree)))
+         1
+   )
+)
+
+(setq tree (create-tree 10))
+(print (walk-tree tree))
+(setq n 0)
+(while (< n 1000)
+   (transaction walk-tree tree)
+   (setq n (+ n 1)))
diff --git a/duhton-c8/demo/trees2.duh b/duhton-c8/demo/trees2.duh
new file mode 100644
--- /dev/null
+++ b/duhton-c8/demo/trees2.duh
@@ -0,0 +1,21 @@
+
+
+(defun create-tree (n)
+   (if (== n 0) 1 (cons (create-tree (- n 1)) (create-tree (- n 1))))
+)
+
+(defun walk-tree (tree)
+   (if (pair? tree)
+      (+ (walk-tree (car tree)) (walk-tree (cdr tree)))
+         1
+   )
+)
+
+(defun lookup-tree ()
+   (walk-tree (create-tree 10))
+)
+
+(setq n 0)
+(while (< n 1000)
+   (transaction lookup-tree)
+   (setq n (+ n 1)))
diff --git a/duhton-c8/duhton.c b/duhton-c8/duhton.c
new file mode 100644
--- /dev/null
+++ b/duhton-c8/duhton.c
@@ -0,0 +1,70 @@
+#include <string.h>
+#include "duhton.h"
+
+
+int main(int argc, char **argv)
+{
+    char *filename = NULL;
+    int interactive = 1;
+       int i;
+       int num_threads = STM_NB_SEGMENTS;
+
+       for (i = 1; i < argc; ++i) {
+               if (strcmp(argv[i], "--help") == 0) {
+                       printf("Duhton: a simple lisp-like language with STM 
support\n\n");
+                       printf("Usage: duhton [--help] [--num-threads no] 
[filename]\n");
+                       printf("  --help: this help\n");
+                       printf("  --num-threads <number>: number of threads 
(default 4)\n\n");
+                       exit(0);
+               } else if (strcmp(argv[i], "--num-threads") == 0) {
+                       if (i == argc - 1) {
+                               printf("ERROR: --num-threads requires a 
parameter\n");
+                               exit(1);
+                       }
+                       num_threads = atoi(argv[i + 1]);
+                       i++;
+               } else if (strncmp(argv[i], "--", 2) == 0) {
+                       printf("ERROR: unrecognized parameter %s\n", argv[i]);
+               } else {
+                       filename = argv[i];
+                       interactive = 0;
+               }
+       }
+    if (!filename) {
+        filename = "-";   /* stdin */
+       }
+
+    Du_Initialize(num_threads);
+
+    while (1) {
+        if (interactive) {
+            printf("))) ");
+            fflush(stdout);
+        }
+        stm_start_inevitable_transaction(&stm_thread_local);
+        DuObject *code = Du_Compile(filename, interactive);
+
+        if (code == NULL) {
+            printf("\n");
+            break;
+        }
+
+        DuObject *res = Du_Eval(code, Du_Globals);
+        if (interactive) {
+            Du_Print(res, 1);
+        }
+
+        //_du_save1(stm_thread_local_obj);
+        //stm_collect(0);   /* hack... */
+        //_du_restore1(stm_thread_local_obj);
+
+        stm_commit_transaction();
+
+        Du_TransactionRun();
+        if (!interactive)
+            break;
+    }
+
+    Du_Finalize();
+    return 0;
+}
diff --git a/duhton-c8/duhton.h b/duhton-c8/duhton.h
new file mode 100644
--- /dev/null
+++ b/duhton-c8/duhton.h
@@ -0,0 +1,213 @@
+#ifndef _DUHTON_H_
+#define _DUHTON_H_
+
+/* #undef USE_GIL */            /* forces "gil-c7" instead of "c7" */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "../c8/stmgc.h"
+
+
+
+extern __thread stm_thread_local_t stm_thread_local;
+
+struct DuObject_s {
+    struct object_s header;
+    uint32_t type_id;
+};
+typedef TLPREFIX struct DuObject_s DuObject;
+
+
+#define DuOBJECT_HEAD1   struct DuObject_s ob_base;
+
+
+#ifdef __GNUC__
+#  define NORETURN  __attribute__((noreturn))
+#else
+#  define NORETURN  /* nothing */
+#endif
+
+
+typedef void(*trace_fn)(struct DuObject_s *, void visit(object_t **));
+typedef size_t(*bytesize_fn)(struct DuObject_s *);
+typedef void(*print_fn)(DuObject *);
+typedef DuObject *(*eval_fn)(DuObject *, DuObject *);
+typedef int(*len_fn)(DuObject *);
+
+typedef struct {
+    const char *dt_name;
+    int dt_typeindex;
+    int dt_size;
+    trace_fn dt_trace;
+    print_fn dt_print;
+    eval_fn dt_eval;
+    len_fn dt_is_true;
+    len_fn dt_length;
+    bytesize_fn dt_bytesize;
+} DuType;
+
+/* keep this list in sync with object.c's Du_Types[] */
+#define DUTYPE_INVALID       0
+#define DUTYPE_NONE          1
+#define DUTYPE_INT           2
+#define DUTYPE_SYMBOL        3
+#define DUTYPE_CONS          4
+#define DUTYPE_LIST          5
+#define DUTYPE_TUPLE         6
+#define DUTYPE_FRAME         7
+#define DUTYPE_FRAMENODE     8
+#define DUTYPE_CONTAINER     9
+#define _DUTYPE_TOTAL       10
+
+extern DuType DuNone_Type;
+extern DuType DuInt_Type;
+extern DuType DuSymbol_Type;
+extern DuType DuCons_Type;
+extern DuType DuList_Type;
+extern DuType DuTuple_Type;
+extern DuType DuFrame_Type;
+extern DuType DuFrameNode_Type;
+extern DuType DuContainer_Type;
+
+extern DuType *Du_Types[_DUTYPE_TOTAL];
+
+#define ROUND_UP(size)  ((size) < 16 ? 16 : ((size) + 7) & ~7)
+
+
+DuObject *DuObject_New(DuType *tp);
+int DuObject_IsTrue(DuObject *ob);
+int DuObject_Length(DuObject *ob);
+
+
+extern DuObject *Du_None;
+
+#define _DuObject_TypeNum(ob) (((DuObject*)(ob))->type_id)
+#define Du_TYPE(ob)           (Du_Types[_DuObject_TypeNum(ob)])
+#define DuInt_Check(ob)       (_DuObject_TypeNum(ob) == DUTYPE_INT)
+#define DuSymbol_Check(ob)    (_DuObject_TypeNum(ob) == DUTYPE_SYMBOL)
+#define DuCons_Check(ob)      (_DuObject_TypeNum(ob) == DUTYPE_CONS)
+#define DuList_Check(ob)      (_DuObject_TypeNum(ob) == DUTYPE_LIST)
+#define DuFrame_Check(ob)     (_DuObject_TypeNum(ob) == DUTYPE_FRAME)
+#define DuContainer_Check(ob) (_DuObject_TypeNum(ob) == DUTYPE_CONTAINER)
+
+void DuType_Ensure(char *where, DuObject *ob);
+void DuInt_Ensure(char *where, DuObject *ob);
+void DuList_Ensure(char *where, DuObject *ob);
+void DuContainer_Ensure(char *where, DuObject *ob);
+void DuCons_Ensure(char *where, DuObject *ob);
+void DuSymbol_Ensure(char *where, DuObject *ob);
+void DuFrame_Ensure(char *where, DuObject *ob);
+
+DuObject *DuInt_FromInt(int value);
+int DuInt_AsInt(DuObject *ob);
+
+DuObject *DuList_New(void);
+void DuList_Append(DuObject *list, DuObject *item);
+int DuList_Size(DuObject *list);
+DuObject *DuList_GetItem(DuObject *list, int index);
+void DuList_SetItem(DuObject *list, int index, DuObject *newobj);
+DuObject *DuList_Pop(DuObject *list, int index);
+
+DuObject *DuContainer_New(DuObject *obj);
+DuObject *DuContainer_GetRef(DuObject *container);
+void DuContainer_SetRef(DuObject *container, DuObject *newobj);
+
+DuObject *DuSymbol_FromString(const char *name);
+char *DuSymbol_AsString(DuObject *ob);
+int DuSymbol_Id(DuObject *ob);
+
+typedef TLPREFIX struct DuConsObject_s {
+    DuOBJECT_HEAD1
+    DuObject *car, *cdr;
+} DuConsObject;
+
+DuObject *DuCons_New(DuObject *car, DuObject *cdr);
+DuObject *DuCons_Car(DuObject *cons);
+DuObject *DuCons_Cdr(DuObject *cons);
+DuObject *_DuCons_CAR(DuObject *cons);
+DuObject *_DuCons_NEXT(DuObject *cons);
+
+void Du_FatalError(char *msg, ...) NORETURN;
+DuObject *Du_Compile(char *filename, int stop_after_newline);
+void Du_Print(DuObject *ob, int newline);
+
+DuObject *Du_Eval(DuObject *ob, DuObject *locals);
+DuObject *Du_Progn(DuObject *cons, DuObject *locals);
+
+DuObject *DuFrame_New();
+DuObject *DuFrame_Copy(DuObject *frame);
+DuObject *DuFrame_GetSymbol(DuObject *frame, DuObject *symbol);
+void DuFrame_SetSymbol(DuObject *frame, DuObject *symbol, DuObject *value);
+void DuFrame_SetSymbolStr(DuObject *frame, char *name, DuObject *value);
+void DuFrame_SetBuiltinMacro(DuObject *frame, char *name, eval_fn func);
+void DuFrame_SetUserFunction(DuObject *frame, DuObject *symbol,
+                             DuObject *arglist, DuObject *progn);
+DuObject *_DuFrame_EvalCall(DuObject *frame, DuObject *symbol,
+                            DuObject *rest, int execute_now);
+
+void Du_Initialize(int);
+void Du_Finalize(void);
+extern DuObject *Du_Globals;
+
+void Du_TransactionAdd(DuObject *code, DuObject *frame);
+void Du_TransactionRun(void);
+
+
+#define _du_save1(p1)           (_push_root((DuObject *)(p1)))
+#define _du_save2(p1,p2)        (_push_root((DuObject *)(p1)),  \
+                                 _push_root((DuObject *)(p2)))
+#define _du_save3(p1,p2,p3)     (_push_root((DuObject *)(p1)),  \
+                                 _push_root((DuObject *)(p2)),  \
+                                 _push_root((DuObject *)(p3)))
+#define _du_save4(p1,p2,p3,p4)  (_push_root((DuObject *)(p1)), \
+                                 _push_root((DuObject *)(p2)),          \
+                                 _push_root((DuObject *)(p3)),          \
+                                 _push_root((DuObject *)(p4)))
+
+
+#define _du_restore1(p1)        (p1 = (typeof(p1))_pop_root())
+#define _du_restore2(p1,p2)     (p2 = (typeof(p2))_pop_root(),  \
+                                 p1 = (typeof(p1))_pop_root())
+#define _du_restore3(p1,p2,p3)  (p3 = (typeof(p3))_pop_root(),  \
+                                 p2 = (typeof(p2))_pop_root(),  \
+                                 p1 = (typeof(p1))_pop_root())
+#define _du_restore4(p1,p2,p3,p4)(p4 = (typeof(p4))_pop_root(), \
+                                  p3 = (typeof(p3))_pop_root(),         \
+                                  p2 = (typeof(p2))_pop_root(),         \
+                                  p1 = (typeof(p1))_pop_root())
+
+
+#define _du_read1(p1)           stm_read((object_t *)(p1))
+#define _du_write1(p1)          stm_write((object_t *)(p1))
+
+#define INIT_PREBUILT(p)       ((typeof(p))stm_setup_prebuilt((object_t *)(p)))
+
+
+#ifndef NDEBUG
+# define _check_not_free(ob)                                    \
+    assert(_DuObject_TypeNum(ob) > DUTYPE_INVALID && \
+           _DuObject_TypeNum(ob) < _DUTYPE_TOTAL)
+#endif
+
+static inline void _push_root(DuObject *ob) {
+    #ifndef NDEBUG
+    if (ob) _check_not_free(ob);
+    #endif
+    STM_PUSH_ROOT(stm_thread_local, ob);
+}
+static inline object_t *_pop_root(void) {
+    object_t *ob;
+    STM_POP_ROOT(stm_thread_local, ob);
+    #ifndef NDEBUG
+    if (ob) _check_not_free(ob);
+    #endif
+    return ob;
+}
+
+extern pthread_t *all_threads;
+extern int all_threads_count;
+
+//extern __thread DuObject *stm_thread_local_obj;  /* XXX temp */
+#endif  /* _DUHTON_H_ */
diff --git a/duhton-c8/frame.c b/duhton-c8/frame.c
new file mode 100644
--- /dev/null
+++ b/duhton-c8/frame.c
@@ -0,0 +1,366 @@
+#include "duhton.h"
+#include <string.h>
+#include <stdint.h>
+
+typedef TLPREFIX struct dictentry_s {
+    int symbol_id;
+    DuObject *symbol;
+    DuObject *value;
+    eval_fn builtin_macro;
+    DuObject *func_arglist;
+    DuObject *func_progn;
+} dictentry_t;
+
+typedef TLPREFIX struct DuFrameNodeObject_s {
+    DuOBJECT_HEAD1
+    int ob_count;
+    struct dictentry_s ob_items[1];
+} DuFrameNodeObject;
+
+
+void framenode_trace(struct DuFrameNodeObject_s *ob, void visit(object_t **))
+{
+    int i;
+    for (i=ob->ob_count-1; i>=0; i--) {
+        struct dictentry_s *e = &ob->ob_items[i];
+        visit((object_t **)&e->symbol);
+        visit((object_t **)&e->value);
+        visit((object_t **)&e->func_arglist);
+        visit((object_t **)&e->func_progn);
+    }
+}
+
+size_t framenode_bytesize(struct DuFrameNodeObject_s *ob)
+{
+    return (sizeof(DuFrameNodeObject) +
+            (ob->ob_count - 1) * sizeof(struct dictentry_s));
+}
+
+
+typedef TLPREFIX struct DuFrameObject_s {
+    DuOBJECT_HEAD1
+    DuFrameNodeObject *ob_nodes;
+} DuFrameObject;
+
+DuObject *Du_Globals;
+static DuFrameNodeObject *du_empty_framenode;
+
+void init_prebuilt_frame_objects(void)
+{
+    static DuFrameNodeObject empty_framenode = { {.type_id=DUTYPE_FRAMENODE} };
+    static DuFrameObject g = { {.type_id=DUTYPE_FRAME},
+                               .ob_nodes=&empty_framenode };
+
+    du_empty_framenode = INIT_PREBUILT(&empty_framenode);
+    Du_Globals = (DuObject *)INIT_PREBUILT(&g);
+}
+
+DuObject *DuFrame_New()
+{
+    DuFrameObject *ob = (DuFrameObject *)DuObject_New(&DuFrame_Type);
+    ob->ob_nodes = du_empty_framenode;
+    return (DuObject *)ob;
+}
+
+#if 0
+DuObject *DuFrame_Copy(DuObject *frame)
+{
+    XXX fix or kill
+    DuFrame_Ensure("DuFrame_Copy", frame);
+    int i;
+    DuFrameObject *src = (DuFrameObject *)frame;
+    DuFrameObject *dst = (DuFrameObject *)DuFrame_New();
+    dst->entry_count = src->entry_count;
+    dst->entries = malloc(sizeof(struct dictentry) * src->entry_count);
+    assert(dst->entries);
+    for (i=0; i<src->entry_count; i++) {
+        struct dictentry *e = &src->entries[i];
+        Du_INCREF(e->symbol);
+        if (e->value        != NULL) Du_INCREF(e->value       );
+        if (e->func_arglist != NULL) Du_INCREF(e->func_arglist);
+        if (e->func_progn   != NULL) Du_INCREF(e->func_progn  );
+        dst->entries[i] = *e;
+    }
+    return (DuObject *)dst;
+}
+#endif
+
+void frame_trace(struct DuFrameObject_s *ob, void visit(object_t **))
+{
+    visit((object_t **)&ob->ob_nodes);
+}
+
+void frame_print(DuFrameObject *ob)
+{
+    printf("<frame>");
+}
+
+static void _copy(dictentry_t *dst, dictentry_t *src)
+{
+    /* workaround for a bug in clang-3.4: cannot do "*dst = *src;" */
+    memcpy(_stm_real_address((object_t *)dst),
+           _stm_real_address((object_t *)src),
+           sizeof(dictentry_t));
+}
+
+static void _clear(dictentry_t *dst)
+{
+    /* workaround for a bug in clang-3.4: many "dst->field = NULL;"
+       turn into a single memset() call */
+    memset(_stm_real_address((object_t *)dst), 0,
+           sizeof(dictentry_t));
+}
+
+static dictentry_t *
+find_entry(DuFrameObject *frame, DuObject *symbol, int write_mode)
+{
+    /* only allocates if write_mode = 1 */
+    _du_read1(frame);
+    DuFrameNodeObject *ob = frame->ob_nodes;
+
+    _du_read1(ob);
+    int left = 0;
+    int right = ob->ob_count;
+    dictentry_t *entries = ob->ob_items;
+    int search_id = DuSymbol_Id(symbol);
+
+#if 0
+#ifdef _GC_DEBUG
+    int j;
+    for (j = 0; j < right; j++) {
+        dprintf(("\t%d\n", entries[j].symbol_id));
+    }
+#endif
+#endif
+
+    while (right > left) {
+        int middle = (left + right) / 2;
+        int found_id = entries[middle].symbol_id;
+        if (search_id < found_id)
+            right = middle;
+        else if (search_id == found_id) {
+            if (write_mode) {
+                _du_write1(ob);
+                entries = ob->ob_items;
+            }
+            return entries + middle;
+        }
+        else
+            left = middle + 1;
+    }
+
+    if (!write_mode) {
+        return NULL;
+    }
+    else {
+        int i;
+        size_t size = (sizeof(DuFrameNodeObject) +
+                       (ob->ob_count + 1 - 1)*sizeof(dictentry_t));
+        DuFrameNodeObject *newob;
+
+        _du_save3(ob, symbol, frame);
+        newob = (DuFrameNodeObject *)stm_allocate(size);
+        newob->ob_base.type_id = DUTYPE_FRAMENODE;
+        _du_restore3(ob, symbol, frame);
+
+        newob->ob_count = ob->ob_count + 1;
+        dictentry_t *newentries = newob->ob_items;
+        entries = ob->ob_items;
+
+        for (i=0; i<left; i++)
+            _copy(&newentries[i], &entries[i]);
+
+        DuSymbol_Ensure("find_entry", symbol);
+#ifdef _GC_DEBUG
+        dprintf(("NEW ENTRY ADDED WITH search_id = %d\n", search_id));
+#endif
+        _clear(&newentries[left]);
+        newentries[left].symbol_id = search_id;
+        newentries[left].symbol = symbol;
+
+        for (i=left+1; i<newob->ob_count; i++)
+            _copy(&newentries[i], &entries[i-1]);
+
+        _du_write1(frame);
+        frame->ob_nodes = newob;
+
+        return newentries + left;
+    }
+}
+
+void DuFrame_SetBuiltinMacro(DuObject *frame, char *name, eval_fn func)
+{
+    DuFrame_Ensure("DuFrame_SetBuiltinMacro", frame);
+
+    _du_save1(frame);
+    DuObject *sym = DuSymbol_FromString(name);
+    _du_restore1(frame);
+
+    _du_save1(frame);
+    dictentry_t *e = find_entry((DuFrameObject *)frame, sym, 1);
+    _du_restore1(frame);
+
+    _du_write1(frame);          /* e is part of frame or a new object */
+    e->builtin_macro = func;
+}
+
+static void
+_parse_arguments(DuObject *symbol, DuObject *arguments,
+                 DuObject *formallist, DuObject *caller, DuObject *callee)
+{
+    while (DuCons_Check(formallist)) {
+        if (!DuCons_Check(arguments))
+            Du_FatalError("call to '%s': not enough arguments",
+                          DuSymbol_AsString(symbol));
+
+        /* _du_read1(arguments); IMMUTABLE */
+        DuObject *arg = _DuCons_CAR(arguments);
+        DuObject *argumentsnext = _DuCons_NEXT(arguments);
+
+        _du_save3(symbol, argumentsnext, caller);
+        _du_save2(formallist, callee);
+        DuObject *obj = Du_Eval(arg, caller);
+        _du_restore2(formallist, callee);
+
+        /* _du_read1(formallist); IMMUTABLE */
+        DuObject *sym = _DuCons_CAR(formallist);
+        DuObject *formallistnext = _DuCons_NEXT(formallist);
+
+        _du_save2(formallistnext, callee);
+        DuFrame_SetSymbol(callee, sym, obj);
+        _du_restore2(formallistnext, callee);
+        _du_restore3(symbol, argumentsnext, caller);
+
+        formallist = formallistnext;
+        arguments = argumentsnext;
+    }
+    if (arguments != Du_None)
+        Du_FatalError("call to '%s': too many arguments",
+                      DuSymbol_AsString(symbol));
+}
+
+DuObject *_DuFrame_EvalCall(DuObject *frame, DuObject *symbol,
+                            DuObject *rest, int execute_now)
+{
+    dictentry_t *e;
+    DuFrame_Ensure("_DuFrame_EvalCall", frame);
+
+    /* find_entry not in write_mode will not collect */
+    e = find_entry((DuFrameObject *)frame, symbol, 0);
+    if (!e) {
+        e = find_entry((DuFrameObject *)Du_Globals, symbol, 0);
+        if (!e) {
+            if (!DuSymbol_Check(symbol)) {
+                printf("_DuFrame_EvalCall: ");
+                Du_Print(symbol, 1);
+                Du_FatalError("expected a symbol to execute");
+            }
+            else
+                goto not_defined;
+        }
+    }
+    if (e->func_progn) {
+        DuObject *func = e->func_progn;
+        DuObject *func_arglist = e->func_arglist;
+        _du_save1(func);
+        _du_save4(frame, symbol, rest, func_arglist);
+        DuObject *callee_frame = DuFrame_New();
+        _du_restore4(frame, symbol, rest, func_arglist);
+
+        _du_save1(callee_frame);
+        _parse_arguments(symbol, rest, func_arglist, frame, callee_frame);
+        _du_restore1(callee_frame);
+        _du_restore1(func);
+
+        if (execute_now) {
+            return Du_Progn(func, callee_frame);
+        }
+        else {
+            Du_TransactionAdd(func, callee_frame);
+            return NULL;
+        }
+    }
+    if (e->builtin_macro) {
+        if (!execute_now)
+            Du_FatalError("symbol refers to a macro: '%s'",
+                          DuSymbol_AsString(symbol));
+        return e->builtin_macro(rest, frame);
+    }
+ not_defined:
+    Du_FatalError("symbol not defined as a function: '%s'",
+                  DuSymbol_AsString(symbol));
+}
+
+DuObject *DuFrame_GetSymbol(DuObject *frame, DuObject *symbol)
+{
+    dictentry_t *e;
+    DuFrame_Ensure("DuFrame_GetSymbol", frame);
+
+    e = find_entry((DuFrameObject *)frame, symbol, 0);
+    /* find_entry does the read_barrier */
+    return e ? e->value : NULL;
+}
+
+void DuFrame_SetSymbol(DuObject *frame, DuObject *symbol, DuObject *value)
+{
+    dictentry_t *e;
+    DuFrame_Ensure("DuFrame_SetSymbol", frame);
+
+    _du_save2(value, frame);
+    e = find_entry((DuFrameObject *)frame, symbol, 1);
+    _du_restore2(value, frame);
+
+    _du_write1(frame);          /* e is new or part of frame */
+    e->value = value;
+}
+
+void DuFrame_SetSymbolStr(DuObject *frame, char *name, DuObject *value)
+{
+    _du_save2(frame, value);
+    DuObject *sym = DuSymbol_FromString(name);
+    _du_restore2(frame, value);
+
+    DuFrame_SetSymbol(frame, sym, value);
+}
+
+void DuFrame_SetUserFunction(DuObject *frame, DuObject *symbol,
+                             DuObject *arglist, DuObject *progn)
+{
+    dictentry_t *e;
+    DuFrame_Ensure("DuFrame_SetUserFunction", frame);
+
+    _du_save3(arglist, progn, frame);
+    e = find_entry((DuFrameObject *)frame, symbol, 1);
+    _du_restore3(arglist, progn, frame);
+
+    _du_write1(frame);          /* e is part of frame or new */
+    e->func_arglist = arglist;
+    e->func_progn = progn;
+}
+
+void DuFrame_Ensure(char *where, DuObject *ob)
+{
+    if (!DuFrame_Check(ob))
+        Du_FatalError("%s: expected 'frame' argument, got '%s'",
+                      where, Du_TYPE(ob)->dt_name);
+}
+
+DuType DuFrameNode_Type = {    /* internal type */
+    "framenode",
+    DUTYPE_FRAMENODE,
+    0,    /* dt_size */
+    (trace_fn)framenode_trace,
+    (print_fn)NULL,
+    (eval_fn)NULL,
+    (len_fn)NULL,
+    (len_fn)NULL,
+    (bytesize_fn)framenode_bytesize,
+};
+
+DuType DuFrame_Type = {
+    "frame",
+    DUTYPE_FRAME,
+    sizeof(DuFrameObject),
+    (trace_fn)frame_trace,
+    (print_fn)frame_print,
+};
diff --git a/duhton-c8/glob.c b/duhton-c8/glob.c
new file mode 100644
--- /dev/null
+++ b/duhton-c8/glob.c
@@ -0,0 +1,867 @@
+#include "duhton.h"
+#include <sys/select.h>
+#include <sys/time.h>
+
+pthread_t *all_threads;
+int all_threads_count;
+
+static void _du_getargs1(const char *name, DuObject *cons, DuObject *locals,
+                         DuObject **a)
+{
+    DuObject *expr1, *obj1;
+
+    if (cons == Du_None) goto error;
+
+    /* _du_read1(cons); IMMUTABLE */
+    expr1 = _DuCons_CAR(cons);
+    cons = _DuCons_NEXT(cons);
+    if (cons != Du_None) goto error;
+
+    obj1 = Du_Eval(expr1, locals);
+    *a = obj1;
+    return;
+
+ error:
+    Du_FatalError("%s: expected one argument", name);
+}
+
+static void _du_getargs2(const char *name, DuObject *cons, DuObject *locals,
+                         DuObject **a, DuObject **b)
+{
+    DuObject *expr1, *expr2, *obj1, *obj2;
+
+    if (cons == Du_None) goto error;
+
+    /* _du_read1(cons); IMMUTABLE */
+    expr1 = _DuCons_CAR(cons);
+    cons = _DuCons_NEXT(cons);
+    if (cons == Du_None) goto error;
+
+    /* _du_read1(cons); IMMUTABLE */
+    expr2 = _DuCons_CAR(cons);
+    cons = _DuCons_NEXT(cons);
+    if (cons != Du_None) goto error;
+
+    _du_save2(expr2, locals);
+    obj1 = Du_Eval(expr1, locals);
+    _du_restore2(expr2, locals);
+
+    _du_save1(obj1);
+    obj2 = Du_Eval(expr2, locals);
+    _du_restore1(obj1);
+
+    *a = obj1;
+    *b = obj2;
+    return;
+
+ error:
+    Du_FatalError("%s: expected two arguments", name);
+}
+
+/************************************************************/
+
+
+DuObject *Du_Progn(DuObject *cons, DuObject *locals)
+{
+    DuObject *result = Du_None;
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *expr = _DuCons_CAR(cons);
+        DuObject *next = _DuCons_NEXT(cons);
+        _du_save2(next, locals);
+        result = Du_Eval(expr, locals);
+        _du_restore2(next, locals);
+        cons = next;
+    }
+    return result;
+}
+
+DuObject *du_setq(DuObject *cons, DuObject *locals)
+{
+    DuObject *result = Du_None;
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *symbol = _DuCons_CAR(cons);
+        cons = _DuCons_NEXT(cons);
+        if (cons == Du_None)
+            Du_FatalError("setq: number of arguments is odd");
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *expr = _DuCons_CAR(cons);
+        DuObject *next = _DuCons_NEXT(cons);
+
+        _du_save3(symbol, next, locals);
+        DuObject *obj = Du_Eval(expr, locals);
+        _du_restore3(symbol, next, locals);
+
+        _du_save3(next, locals, obj);
+        DuFrame_SetSymbol(locals, symbol, obj);
+        _du_restore3(next, locals, obj);
+
+        result = obj;
+        cons = next;
+    }
+    return result;
+}
+
+DuObject *du_print(DuObject *cons, DuObject *locals)
+{
+    _du_save2(cons, locals);
+    DuObject *lst = DuList_New();
+    _du_restore2(cons, locals);
+
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *expr = _DuCons_CAR(cons);
+        DuObject *next = _DuCons_NEXT(cons);
+
+        _du_save3(lst, next, locals);
+        DuObject *obj = Du_Eval(expr, locals);
+        _du_restore3(lst, next, locals);
+
+        _du_save3(lst, next, locals);
+        DuList_Append(lst, obj);
+        _du_restore3(lst, next, locals);
+
+        cons = next;
+    }
+
+    _du_save1(lst);
+    stm_become_inevitable(&stm_thread_local, "print");
+    _du_restore1(lst);
+
+    int i;
+    for (i=0; i<DuList_Size(lst); i++) {
+        if (i > 0) printf(" ");
+        _du_save1(lst);
+        Du_Print(DuList_GetItem(lst, i), 0);
+        _du_restore1(lst);
+    }
+
+    printf("\n");
+    return Du_None;
+}
+
+DuObject *du_xor(DuObject *cons, DuObject *locals)
+{
+    int result = 0;
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *expr = _DuCons_CAR(cons);
+        DuObject *next = _DuCons_NEXT(cons);
+
+        _du_save2(next, locals);
+        DuObject *obj = Du_Eval(expr, locals);
+        result ^= DuInt_AsInt(obj);
+        _du_restore2(next, locals);
+
+        cons = next;
+    }
+
+    return DuInt_FromInt(result);
+}
+
+DuObject *du_lshift(DuObject *cons, DuObject *locals)
+{
+    int result = 0;
+    /* _du_read1(cons); IMMUTABLE */
+    DuObject *expr = _DuCons_CAR(cons);
+    DuObject *next = _DuCons_NEXT(cons);
+
+    _du_save2(next, locals);
+    DuObject *obj = Du_Eval(expr, locals);
+    result = DuInt_AsInt(obj);
+    _du_restore2(next, locals);
+
+    cons = next;
+
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        expr = _DuCons_CAR(cons);
+        next = _DuCons_NEXT(cons);
+
+        _du_save2(next, locals);
+        obj = Du_Eval(expr, locals);
+        result <<= DuInt_AsInt(obj);
+        _du_restore2(next, locals);
+
+        cons = next;
+    }
+
+    return DuInt_FromInt(result);
+}
+
+DuObject *du_rshift(DuObject *cons, DuObject *locals)
+{
+    int result = 0;
+    /* _du_read1(cons); IMMUTABLE */
+    DuObject *expr = _DuCons_CAR(cons);
+    DuObject *next = _DuCons_NEXT(cons);
+
+    _du_save2(next, locals);
+    DuObject *obj = Du_Eval(expr, locals);
+    result = DuInt_AsInt(obj);
+    _du_restore2(next, locals);
+
+    cons = next;
+
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        expr = _DuCons_CAR(cons);
+        next = _DuCons_NEXT(cons);
+
+        _du_save2(next, locals);
+        obj = Du_Eval(expr, locals);
+        result >>= DuInt_AsInt(obj);
+        _du_restore2(next, locals);
+
+        cons = next;
+    }
+
+    return DuInt_FromInt(result);
+}
+
+DuObject *du_add(DuObject *cons, DuObject *locals)
+{
+    int result = 0;
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *expr = _DuCons_CAR(cons);
+        DuObject *next = _DuCons_NEXT(cons);
+
+        _du_save2(next, locals);
+        DuObject *obj = Du_Eval(expr, locals);
+        result += DuInt_AsInt(obj);
+        _du_restore2(next, locals);
+
+        cons = next;
+    }
+    return DuInt_FromInt(result);
+}
+
+DuObject *du_sub(DuObject *cons, DuObject *locals)
+{
+    int result = 0;
+    int sign = 1;
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *expr = _DuCons_CAR(cons);
+        DuObject *next = _DuCons_NEXT(cons);
+
+        _du_save2(next, locals);
+        DuObject *obj = Du_Eval(expr, locals);
+        result += sign * DuInt_AsInt(obj);
+        _du_restore2(next, locals);
+
+        sign = -1;
+        cons = next;
+    }
+    return DuInt_FromInt(result);
+}
+
+DuObject *du_mul(DuObject *cons, DuObject *locals)
+{
+    int result = 1;
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *expr = _DuCons_CAR(cons);
+        DuObject *next = _DuCons_NEXT(cons);
+
+        _du_save2(next, locals);
+        DuObject *obj = Du_Eval(expr, locals);
+        result *= DuInt_AsInt(obj);
+        _du_restore2(next, locals);
+
+        cons = next;
+    }
+    return DuInt_FromInt(result);
+}
+
+DuObject *du_div(DuObject *cons, DuObject *locals)
+{
+    int result = 0;
+    int first = 1;
+
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *expr = _DuCons_CAR(cons);
+        DuObject *next = _DuCons_NEXT(cons);
+
+        _du_save2(next, locals);
+        DuObject *obj = Du_Eval(expr, locals);
+        if (first) {
+            result = DuInt_AsInt(obj);
+            first = 0;
+        } else {
+            result /= DuInt_AsInt(obj);
+        }
+        _du_restore2(next, locals);
+
+        cons = next;
+    }
+    return DuInt_FromInt(result);
+}
+
+DuObject *du_mod(DuObject *cons, DuObject *locals)
+{
+    int result = 0;
+    int first = 1;
+
+    while (cons != Du_None) {
+        /* _du_read1(cons); IMMUTABLE */
+        DuObject *expr = _DuCons_CAR(cons);
+        DuObject *next = _DuCons_NEXT(cons);
+
+        _du_save2(next, locals);
+        DuObject *obj = Du_Eval(expr, locals);
+        if (first) {
+            result = DuInt_AsInt(obj);
+            first = 0;
+        } else {
+            result %= DuInt_AsInt(obj);
+        }
+        _du_restore2(next, locals);
+
+        cons = next;
+    }
+    return DuInt_FromInt(result);
+}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to