ref: 1dbebd5fe59f27106a4dfa553c9ee8b893d6008e
parent: a609ffb20226eba3d4dc628d7b4d284eddd1c114
author: seh <henesy.dev@gmail.com>
date: Sun Mar 17 22:44:37 EDT 2019
add ADT example
--- /dev/null
+++ b/ADTs/README.md
@@ -1,0 +1,51 @@
+# ADT's
+
+Limbo supports Abstract Data Types (ADT's). These are analogous, but not equivocal to, structs in C and Go.
+
+For further reading on ADT's and how they compose in different contexts, see [Modules](../Modules) and [Generics](../Generics).
+
+## Source
+
+### adts.b:12,16
+
+The type `Person` is an ADT declared within a module definition possessing an integer, string, and function reference member.
+
+The function is named stringify and takes an argument named `p` which is a reference to the adt variable instance which called the function. This function could be thought as being analogous to a method.
+
+Method-like function references declared with `self` as a keyword for an argument are not required to be called with said argument being passed.
+
+Note: Modules are a form of ADT with some special rules associated with them that differentiates them from a normal ADT.
+
+### adts.b:19,23
+
+The type `Town` is an ADT declared outside of a module definition possessing an array of references to Person ADT's, a string, and a function reference.
+
+### adts.b:28,29
+
+The variable `p` is created as a reference to an instance of a `Person` type which is instantiated using constructor-like syntax. The `Person` element `name` is then printed.
+
+Note: Although the syntax used to instantiate the `Person` type instance appears to be a function, it is closer to a tuple being passed into an instance of a `Person`, but used in an in-line fashion. That is, the tuple must contain all non-function reference types contained within the ADT.
+
+### adts.b:31,36
+
+The variable `t` is created as an instance of a `Town` ADT. The non-function reference elements are then initialized manually. Note that the `ref Person(...)` instantiation can be used as a valid variable instance.
+
+### adts.b:41,52
+
+The method-like function references are declared with a bit of special syntax. That is, the function name takes the form of `ADT.func()`.
+
+## Demo
+
+ ; adts
+ Spike
+ Name: Mars
+ Size: 2
+ Members:
+ → Spike
+ → Ed
+ ;
+
+## Exercises
+
+- Can you instantiate an ADT via its constructor without all its non-function reference members?
+- How would you format the constructor-style instantiation of a `ref Town`?
--- /dev/null
+++ b/ADTs/adts.b
@@ -1,0 +1,52 @@
+implement ADTs;
+
+include "sys.m";
+include "draw.m";
+
+sys: Sys;
+print: import sys;
+
+ADTs: module {
+ init: fn(nil: ref Draw->Context, nil: list of string);
+
+ Person: adt {
+ age: int;
+ name: string;
+ stringify: fn(p: self ref Person): string;
+ };
+};
+
+Town: adt {
+ pop: array of ref Person;
+ name: string;
+ stringify: fn(t: self ref Town): string;
+};
+
+init(nil: ref Draw->Context, nil: list of string) {
+ sys = load Sys Sys->PATH;
+
+ p := ref Person(27, "Spike");
+ print("%s\n", p.name);
+
+ t: Town;
+ t.pop = array[] of {p, ref Person(13, "Ed")};
+ t.name = "Mars";
+
+ town := ref t;
+ print("%s\n", town.stringify());
+
+ exit;
+}
+
+Person.stringify(p: self ref Person): string {
+ return p.name;
+}
+
+Town.stringify(t: self ref Town): string {
+ s := "Name: " + t.name + "\nSize: " + string len t.pop + "\nMembers:";
+
+ for(i := 0; i < len t.pop; i++)
+ s += "\n→ " + t.pop[i].stringify();
+
+ return s;
+}
--- a/README.md
+++ b/README.md
@@ -38,6 +38,7 @@
- [Slices](./Slices)
- [Functions](./Functions)
- [Function References](./Function-Refs)
+- [Abstract Data Types](./ADTs)
- [Generics, Picks, and Interfaces (kind of)](./Generics)
- [Exceptions](./Exceptions)