ref: eac284d17b14eb4602387eb47c644fcf4f6e86c0
parent: b6a2e83b6a1464cd4dad074c20c460b075dbbe61
author: seh <henesy.dev@gmail.com>
date: Mon Mar 11 00:09:58 EDT 2019
add beginnings of a generics example
--- /dev/null
+++ b/Generics/README.md
@@ -1,0 +1,22 @@
+# Generics
+
+
+
+Warning: This is an example about an undocumented feature of Limbo. All assertions or explanations provided are considered conjecture until proven otherwise.
+
+## Source
+
+###
+
+## Demo
+
+## Exercises
+
+- Can you find a way to make the eq() function do a deep comparison of Int's?
+- Try removing the `.String` from the `words` definition, what happens?
+- Try removing `ref anywhere, see what happens.
+
+## References
+
+- https://github.com/caerwynj/inferno-lab/blob/master/27/sexprs.b
+- https://github.com/caerwynj/inferno-lab/blob/master/78/README.md
--- /dev/null
+++ b/Generics/generics.b
@@ -1,0 +1,116 @@
+implement Generics;
+
+include "sys.m";
+include "draw.m";
+include "bufio.m";
+
+sys: Sys;
+print: import sys;
+
+bufio: Bufio;
+Iobuf: import bufio;
+
+Generics: module {
+ init: fn(nil: ref Draw->Context, nil: list of string);
+};
+
+Rd: adt[T] {
+ t: ref Iobuf;
+ ws: fn(rd: self ref Rd[T]): int;
+};
+
+# Polymorphic type
+Word: adt[T] {
+ w: T;
+
+ pick {
+ String =>
+ s: string;
+ }
+
+ eq: fn(a, b: ref Word): int;
+};
+
+Integer: adt {
+ d: int;
+};
+
+Int: type ref Integer;
+
+init(nil: ref Draw->Context, nil: list of string) {
+ sys = load Sys Sys->PATH;
+ bufio = load Bufio Bufio->PATH;
+
+ in := bufio->open("/fd/0", bufio->OREAD);
+
+ rd := ref Rd[ref Iobuf](in);
+
+ print("Type something: ");
+
+ c := rd.ws();
+ print("Broke on '%c'\n", c);
+
+ words: list of ref Word[Int].String;
+
+ smiley := "☺";
+ frowny := ":(";
+
+ sword := ref Word[Int].String(Int(5), smiley);
+
+ # Format is: Adt[Type].PickTag(fields...)
+ words = sword :: words;
+ words = ref Word[Int].String(Int(7), frowny) :: words;
+
+ if(ismember(sword, words))
+ print("Found %d!\n", sword.w.d);
+
+ exit;
+}
+
+# Skip white space
+Rd[T].ws(rd: self ref Rd[T]): int {
+ while(isspace(c := rd.t.getb()))
+ {}
+
+ return c;
+}
+
+Word[T].eq(a, b: ref Word): int
+{
+ return a.w == b.w; # This is a shallow comparison, don't rely on this
+}
+
+# Matches whitespace characters
+isspace(c: int): int {
+ return c == ' ' || c == '\r' || c == '\t' || c == '\n';
+}
+
+# Checks if x is a member of l
+ismember[T](x: T, l: list of T): int
+ for {
+ T => eq: fn(a, b: T): int;
+ }
+{
+ for(; l != nil; l = tl l)
+ if(T.eq(x, hd l))
+ return 1;
+
+ return 0;
+}
+
+# Pairs two lists of separate types(?)
+pair[T1, T2](l1: list of T1, l2: list of T2): list of (T1, T2) {
+ if(l1 == nil && l2 == nil)
+ return nil;
+
+ return (hd l1, hd l2) :: pair(tl l1, tl l2);
+}
+
+# Reverse a list
+rev[T](l: list of T): list of T {
+ r: list of T;
+ for(; l != nil; l = tl l)
+ r = hd l :: r;
+
+ return r;
+}