summaryrefslogtreecommitdiff
path: root/chapter-sccp/src/test/java/com/seaofnodes/simple/progs
diff options
context:
space:
mode:
Diffstat (limited to 'chapter-sccp/src/test/java/com/seaofnodes/simple/progs')
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/arg_count.c10
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/arg_count.smp6
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/array1.smp9
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c18
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/c_returns.c28
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/fib.c16
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/funptr.c15
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/jig.smp16
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/loop2.c7
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/newtonFloat.c16
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp12
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/no_stack_arg_count.smp6
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person.c34
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person21.c34
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person21.smp9
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/sieve.c19
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/sort.c28
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_10x.c13
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_11x.c13
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_12x.c13
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_13x.c13
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_9x.c13
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash.c30
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash.smp30
-rw-r--r--chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash21.smp31
25 files changed, 439 insertions, 0 deletions
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/arg_count.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/arg_count.c
new file mode 100644
index 00000000..e247e28a
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/arg_count.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+__attribute__ ((CALL_CONV))
+extern double addAll( long long i0, double f1, long long i2, double f3, long long i4, double f5, long long i6, double f7, long long i8, double f9, long long i10, double f11, long long i12, double f13, long long i14, double f15, long long i16, double f17, long long i18, double f19 );
+
+int main() {
+ double result = addAll( 0, 1.1, 2, 3.1, 4, 5.1, 6, 7.1, 8, 9.1, 10, 11.1, 12, 13.1, 14, 15.1, 16, 17.1, 18, 19.1 );
+ printf("%f\n", result);
+ return 0;
+}
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/arg_count.smp b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/arg_count.smp
new file mode 100644
index 00000000..6b6bc0ae
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/arg_count.smp
@@ -0,0 +1,6 @@
+// -*- mode: java; -*-
+val addAll = { int i0, flt f1, int i2, flt f3, int i4, flt f5, int i6, flt f7, int x8, flt f9, int i10, flt f11, int i12, flt f13, int i14, flt f15, int x16, flt f17 int x18, flt f19 ->
+ return
+ i0 + f1+ i2+ f3+ i4+ f5+ i6+ f7+ x8 +f9 +
+ i10+f11+i12+f13+i14+f15+x16+f17+x18+f19 ;
+};
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/array1.smp b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/array1.smp
new file mode 100644
index 00000000..6b10f92c
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/array1.smp
@@ -0,0 +1,9 @@
+// -*- mode: java; -*-
+int[] !ary = new int[arg];
+// Fill [0,1,2,3,4,...]
+for( int i=0; i<ary#; i++ )
+ ary[i] = i;
+// Fill [0,1,3,6,10,...]
+for( int i=0; i<ary#-1; i++ )
+ ary[i+1] += ary[i];
+return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c
new file mode 100644
index 00000000..127cbe73
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+typedef struct AryInt {
+ unsigned int len;
+ unsigned char data[];
+} AryInt;
+
+__attribute__ ((CALL_CONV))
+extern AryInt* brain_fuck();
+
+int main() {
+ AryInt* ps = brain_fuck();
+
+ printf("%.*s", ps->len, ps->data);
+
+ return 0;
+}
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/c_returns.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/c_returns.c
new file mode 100644
index 00000000..6d0ff2fe
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/c_returns.c
@@ -0,0 +1,28 @@
+#include <stdint.h>
+#include <stdio.h>
+
+uint64_t c_bits;
+// Legal narrow C returns: unused RAX bits deliberately contain garbage.
+#define RET(name) __asm__(".text\n.globl " #name "\n" #name ":\nmovq c_bits(%rip), %rax\nret\n");
+RET(c_i8) RET(c_u8) RET(c_i16) RET(c_u16) RET(c_i32) RET(c_u32) RET(c_i64)
+#define DECL(name) extern int64_t __attribute__((CALL_CONV)) name(void);
+DECL(test_i8) DECL(test_u8) DECL(test_i16) DECL(test_u16)
+DECL(test_i32) DECL(test_u32) DECL(test_i64) DECL(test_cmp)
+
+int main(void) {
+ uint64_t values[] = {0xa5a5a5a500000000ULL, 0xa5a5a5a50000007fULL,
+ 0xa5a5a5a500000080ULL, 0xa5a5a5a500007fffULL, 0xa5a5a5a500008000ULL,
+ 0xa5a5a5a57fffffffULL, 0xa5a5a5a580000000ULL, 0xa5a5a5a5ffffffffULL};
+ for(unsigned i=0; i<sizeof(values)/sizeof(values[0]); i++) {
+ c_bits=values[i];
+ int64_t actual[]={test_i8(),test_u8(),test_i16(),test_u16(),test_i32(),test_u32(),test_i64(),test_cmp()};
+ int64_t expected[]={(int8_t)c_bits,(uint8_t)c_bits,(int16_t)c_bits,(uint16_t)c_bits,
+ (int32_t)c_bits,(uint32_t)c_bits,(int64_t)c_bits,(int32_t)c_bits==-1};
+ for(unsigned j=0; j<8; j++)
+ if(actual[j]!=expected[j]) {
+ printf("case %u type %u: %lld != %lld\n",i,j,(long long)actual[j],(long long)expected[j]);
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/fib.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/fib.c
new file mode 100644
index 00000000..263d2f13
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/fib.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+
+__attribute__ ((CALL_CONV))
+extern int fib(int x);
+
+int main() {
+ printf("[");
+ for (int i = 0; i < 10; i++) {
+ printf("%d", fib(i));
+ if (i < 9) printf(", ");
+ }
+ printf("]");
+ return 0;
+} \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/funptr.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/funptr.c
new file mode 100644
index 00000000..2abe6e74
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/funptr.c
@@ -0,0 +1,15 @@
+#include <assert.h>
+#include <stdint.h>
+
+typedef int64_t (*Function)(void);
+typedef int64_t (*Printer)(void *, void *);
+extern Function factory(int64_t);
+extern Printer printer(void);
+
+int main(void) {
+ assert(factory(1)() == 42);
+ assert(factory(0)() == 43);
+ struct { uint32_t length; char data[2]; } text = {2, {'o','k'}};
+ printer()(0, &text); // Unused class receiver, then the byte array.
+ return 0;
+}
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/jig.smp b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/jig.smp
new file mode 100644
index 00000000..29987d8e
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/jig.smp
@@ -0,0 +1,16 @@
+// -*- mode: java; -*-
+val _fib = {int n ->
+ int temp=0;
+ int f1=1;
+ int f2=1;
+ int i=n;
+ while( i>1 ){
+ temp = f1+f2;
+ f1=f2;
+ f2=temp;
+ i=i-1;
+ }
+ return f2;
+};
+
+_fib(10);
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/loop2.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/loop2.c
new file mode 100644
index 00000000..934f2d89
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/loop2.c
@@ -0,0 +1,7 @@
+
+__attribute__ ((CALL_CONV))
+extern int loop2();
+
+int main() {
+ return loop2();
+}
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/newtonFloat.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/newtonFloat.c
new file mode 100644
index 00000000..7e7e796d
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/newtonFloat.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+extern double test_sqrt(double);
+
+int main( int argc, char** argv ) {
+ for( int i=0; i<10; i++ ) {
+ double d = test_sqrt((double)i), expect = sqrt((double)i);
+ double delta = fabs(d-expect);
+ printf("%d %f (%g)\n",i,d,delta);
+ if( delta > 1e-15 )
+ return 1;
+ }
+ return 0;
+}
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp
new file mode 100644
index 00000000..be2dffec
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp
@@ -0,0 +1,12 @@
+// -*- mode: java; -*-
+// Newtons approximation to the square root
+val test_sqrt = { flt x ->
+ flt epsilon = 1e-15;
+ flt guess = x;
+ while( 1 ) {
+ flt next = (x/guess + guess)/2;
+ if( guess-epsilon <= next & next <= guess+epsilon ) return guess;
+ //if( guess==next ) return guess;
+ guess = next;
+ }
+};
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/no_stack_arg_count.smp b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/no_stack_arg_count.smp
new file mode 100644
index 00000000..20a05445
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/no_stack_arg_count.smp
@@ -0,0 +1,6 @@
+// -*- mode: java; -*-
+val addAll = { int i0, flt f1, int i2, flt f3, int i4, flt f5, int i6, flt f7, int x8, flt f9, int i10, flt f11, int i12, flt f13, int i14, flt f15 ->
+ return
+ i0 + f1+ i2+ f3+ i4+ f5+ i6+ f7+ x8 +f9 +
+ i10+f11+i12+f13+i14+f15;
+};
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person.c
new file mode 100644
index 00000000..df95e1ca
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+typedef struct Person {
+ int age;
+} Person;
+
+typedef struct PersonArray {
+ unsigned int length;
+ int pad;
+ Person* data[];
+} PersonArray;
+
+__attribute__ ((CALL_CONV))
+extern void fcn(PersonArray* people, int index);
+
+int main() {
+ Person base[5] = {{25},{1},{18},{45},{60}};
+ unsigned char buf[8+8*5];
+ PersonArray* people_array = (PersonArray*)buf;
+ people_array->length=5;
+ for (int i=0; i<people_array->length; i++) people_array->data[i] = &base[i];
+
+ fcn(people_array, 1);
+ fcn(people_array, 1);
+ fcn(people_array, 1);
+ fcn(people_array, 1);
+ fcn(people_array, 1);
+
+ printf("%d\n", people_array->data[1]->age); // expected: 6
+
+ return 0;
+} \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person21.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person21.c
new file mode 100644
index 00000000..df95e1ca
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person21.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+typedef struct Person {
+ int age;
+} Person;
+
+typedef struct PersonArray {
+ unsigned int length;
+ int pad;
+ Person* data[];
+} PersonArray;
+
+__attribute__ ((CALL_CONV))
+extern void fcn(PersonArray* people, int index);
+
+int main() {
+ Person base[5] = {{25},{1},{18},{45},{60}};
+ unsigned char buf[8+8*5];
+ PersonArray* people_array = (PersonArray*)buf;
+ people_array->length=5;
+ for (int i=0; i<people_array->length; i++) people_array->data[i] = &base[i];
+
+ fcn(people_array, 1);
+ fcn(people_array, 1);
+ fcn(people_array, 1);
+ fcn(people_array, 1);
+ fcn(people_array, 1);
+
+ printf("%d\n", people_array->data[1]->age); // expected: 6
+
+ return 0;
+} \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person21.smp b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person21.smp
new file mode 100644
index 00000000..b5e6ee90
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/person21.smp
@@ -0,0 +1,9 @@
+// -*-java-*-
+struct Person {
+ int age;
+};
+
+val fcn = { !Person?[] ps, int x ->
+ if( ps[x] )
+ ps[x].age++;
+}; \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/sieve.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/sieve.c
new file mode 100644
index 00000000..cac4cfa3
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/sieve.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+typedef struct AryInt {
+ unsigned int len;
+ unsigned int data[];
+} AryInt;
+
+__attribute__ ((CALL_CONV))
+extern AryInt *sieve(int N);
+
+int main() {
+ AryInt* ps = sieve(100);
+ printf("%d[",ps->len);
+ for( int i=0; i<ps->len; i++ )
+ printf("%d, ",ps->data[i]);
+ printf("]");
+ return 0;
+}
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/sort.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/sort.c
new file mode 100644
index 00000000..ad76cc7f
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/sort.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+// Test wrapper to call `sort.smp`
+
+typedef struct AryInt {
+ unsigned int len;
+ long long data[];
+} AryInt;
+
+__attribute__ ((CALL_CONV))
+extern AryInt* merge_sort(AryInt*);
+
+
+long long primes[] = { 25, 97, 89, 83, 79, 73, 71, 67, 61, 59, 53, 47, 43, 41, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2 };
+
+int main() {
+ AryInt *as = (AryInt*)primes;
+
+ merge_sort(as);
+
+ printf("%d[",as->len);
+ for( int i=0; i<as->len; i++ )
+ printf("%d, ",as->data[i]);
+ printf("]");
+
+ return 0;
+} \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_10x.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_10x.c
new file mode 100644
index 00000000..d44d5387
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_10x.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+__attribute__ ((CALL_CONV))
+extern int stack10(int x);
+
+int main() {
+int result = stack10(0);
+
+printf("%d", result);
+return 0;
+} \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_11x.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_11x.c
new file mode 100644
index 00000000..d71979d1
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_11x.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+__attribute__ ((CALL_CONV))
+extern int stack11(int x);
+
+int main() {
+int result = stack11(1);
+
+printf("%d", result);
+return 0;
+} \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_12x.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_12x.c
new file mode 100644
index 00000000..a4e425cb
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_12x.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+__attribute__ ((CALL_CONV))
+extern int stack12(int x);
+
+int main() {
+int result = stack12(0);
+
+printf("%d", result);
+return 0;
+} \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_13x.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_13x.c
new file mode 100644
index 00000000..a3a51d0e
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_13x.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+__attribute__ ((CALL_CONV))
+extern int stack13(int x);
+
+int main() {
+int result = stack13(0);
+
+printf("%d", result);
+return 0;
+} \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_9x.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_9x.c
new file mode 100644
index 00000000..4f93ba24
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stacked_r_9x.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+__attribute__ ((CALL_CONV))
+extern int stack9(int x);
+
+int main() {
+int result = stack9(0);
+
+printf("%d", result);
+return 0;
+} \ No newline at end of file
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash.c b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash.c
new file mode 100644
index 00000000..2c6d0fa9
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+typedef struct ArrayU8 {
+ unsigned int length;
+ unsigned char data[];
+} ArrayU8;
+typedef struct String {
+ ArrayU8 * cs;
+ long long _hashCode;
+} String;
+
+
+__attribute__ ((CALL_CONV))
+extern bool equals(String*st1, String*st2);
+
+int main() {
+ String test1 = {.cs=(ArrayU8*)"\x04\x00\x00\x00test"};
+ String test2 = {.cs=(ArrayU8*)"\x05\x00\x00\x00test1"};
+
+ if( equals(&test1, &test2) ) {
+ printf("Expected test1 and test2 unequal");
+ return 1;
+ }
+ if( !equals(&test2, &test2) ) {
+ printf("Expected test2 and test2 equal");
+ return 1;
+ }
+ return 0;
+}
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash.smp b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash.smp
new file mode 100644
index 00000000..7344fcdd
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash.smp
@@ -0,0 +1,30 @@
+// -*- mode: java; -*-
+struct String {
+ u8[] cs;
+ int _hashCode;
+};
+
+// Compare two Strings
+val equals = { !String !self, !String s ->
+ if( self == s ) return true;
+ if( self.cs# != s.cs# ) return false;
+ for( int i=0; i< self.cs#; i++ )
+ if( self.cs[i] != s.cs[i] )
+ return false;
+ return true;
+};
+
+// Return the String hashCode (cached, and never 0)
+val hashCode = { !String self ->
+ self._hashCode
+ ? self._hashCode
+ : (self._hashCode = _hashCodeString(self));
+};
+
+val _hashCodeString = { !String self ->
+ int hash=0;
+ for( int i=0; i< self.cs#; i++ )
+ hash = hash*31 + self.cs[i];
+ if( !hash ) hash = 123456789;
+ return hash;
+};
diff --git a/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash21.smp b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash21.smp
new file mode 100644
index 00000000..257f79f9
--- /dev/null
+++ b/chapter-sccp/src/test/java/com/seaofnodes/simple/progs/stringHash21.smp
@@ -0,0 +1,31 @@
+// -*- mode: java; -*-
+struct String {
+ u8[] cs;
+ int _hashCode;
+};
+
+// Compare two Strings
+val equals = { !String !self, !String s ->
+ if( self == s ) return true;
+ if( self.cs# != s.cs# ) return false;
+ for( int i=0; i< self.cs#; i++ )
+ if( self.cs[i] != s.cs[i] )
+ return false;
+ return true;
+};
+
+// Return the String hashCode (cached, and never 0)
+val hashCode = { !String self ->
+ self._hashCode
+ ? self._hashCode
+ : (self._hashCode = _hashCodeString(self));
+};
+
+val _hashCodeString = { !String self ->
+ int hash=0;
+ if( self.cs )
+ for( int i=0; i< self.cs#; i++ )
+ hash = hash*31 + self.cs[i];
+ if( !hash ) hash = 123456789;
+ return hash;
+};