shithub: limbobyexample

Download patch

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

diff: cannot open b/Generics//null: file does not exist: 'b/Generics//null'
--- /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;
+}