diff options
| author | seh <henesy.dev@gmail.com> | 2019-03-11 04:09:58 -0500 |
|---|---|---|
| committer | seh <henesy.dev@gmail.com> | 2019-03-11 04:09:58 -0500 |
| commit | eac284d17b14eb4602387eb47c644fcf4f6e86c0 (patch) | |
| tree | 0c7151250ea0235ca8e11ecb3b61cc9221e470fa | |
| parent | b6a2e83b6a1464cd4dad074c20c460b075dbbe61 (diff) | |
add beginnings of a generics example
| -rw-r--r-- | Generics/README.md | 22 | ||||
| -rw-r--r-- | Generics/generics.b | 116 |
2 files changed, 138 insertions, 0 deletions
diff --git a/Generics/README.md b/Generics/README.md new file mode 100644 index 0000000..c381e29 --- /dev/null +++ b/Generics/README.md @@ -0,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 diff --git a/Generics/generics.b b/Generics/generics.b new file mode 100644 index 0000000..f46b95c --- /dev/null +++ b/Generics/generics.b @@ -0,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; +} |
