diff --git a/src/js/trove/global.js b/src/js/trove/global.js index 72c42b2ae..225bb8e03 100644 --- a/src/js/trove/global.js +++ b/src/js/trove/global.js @@ -23,9 +23,18 @@ "tve": ["tid", "e"], "Equality": { tag: "name", origin: { "import-type": "uri", uri: "builtin://equality" }, - name: "EqualityResult" } + name: "EqualityResult" }, + "Row": { tag: "name", + origin: { "import-type": "uri", uri: "builtin://global" }, + name: "Row" }, + "Table": { tag: "name", + origin: { "import-type": "uri", uri: "builtin://global" }, + name: "Table" }, + "Col": "tany" }, values: { + "table-from-column": ["arrow", ["Col", ["List", "Col"]], "Table"], + "print": ["forall", "a", ["arrow", ["tva"], "tva"]], "test-print": ["forall", "a", ["arrow", ["tva"], "tva"]], "print-error": ["forall", "a", ["arrow", ["tva"], "tva"]], @@ -523,10 +532,69 @@ "_greaterthan": ["arrow", ["String"], "Boolean"], "_greaterequal": ["arrow", ["String"], "Boolean"] }], + // Issues and things that make me uncomfortable: + // * sometimes order matters and we can't enforce it + // * sometimes column names must match and we can't enforce it + // * sometimes we want to ensure a column being passed in exists in the schema and we can't enforce it + // * would be nice to have a way to express column uniqueness (i.e. add-column) + // * Col is an any (even though we do have the type info available), so: + // * when passing in functions, these functions cannot really be typed + // * when returning from these methods we lose type information + // + // Things I do like about this: + // * thus far it "feels right" to return Table and Row. These types are cognitively simple to understand. + // "Table": ["data", "Table", [], [], { - "length": ["arrow", [], "Number"] + "length": ["arrow", [], "Number"], + "add-column": ["arrow", ["String", ["List", "Col"]], "Table"], + "row-n": ["arrow", ["Number"], "Row"], + "column": ["arrow", ["String"], ["List", "Col"]], + "select-columns": ["arrow", [["List", "String"]], "Table"], + "all-columns": ["arrow", [], ["List", ["List", "Col"]]], + "all-rows": ["arrow", [], ["List", "Row"]], + "column-names": ["arrow", [], ["List", "String"]], + "build-column": ["arrow", ["String", ["arrow", ["Row"], "Col"]], "Table"], + "increasing-by": ["arrow", ["String"], "Table"], + "decreasing-by": ["arrow", ["String"], "Table"], + "order-by": ["arrow", ["String", "Boolean"], "Table"], + // incorrect: column names must all match, order does not matter + "stack": ["arrow", ["Table"], "Table"], + "empty": ["arrow", [], "Table"], + "drop": ["arrow", ["String"], "Table"], + "rename-column": ["arrow", ["String", "String"], "Table"], + "column-n": ["arrow", ["Number"], "Col"], + "filter": ["arrow", [["arrow", ["Col"], "Boolean"]], "Table"], + "filter-by": ["arrow", ["String", ["arrow", ["Col"], "Boolean"]], "Table"], + // incorrect: column names must all match and order matters + "add-row": ["arrow", ["Row"], "Table"], + + // TODO: figure out how to properly type these variadic function + // row + // new-row + + // TODO: finish implementing types for these + // order-by-columns - how to type a Tuple? + // multi-order - how to type an array of two element arrays? + // reduce - how to type a Reducer? + // transform-column + + // TODO: implement types for internals + // _column-index + // _no-column + // _equals + // _output + + // TODO: constructors + // raw-row + }], + "Row": ["data", "Row", [], [], { + "get-column-names": ["arrow", [], ["List", "String"]], + "get-value": ["arrow", ["String"], "Col"], + + // TODO: implement types for internals + // _output + // _equals }], - "Row": ["data", "Row", [], [], { }], "Function": ["data", "Function", [], [], {}], "Boolean": ["data", "Boolean", [], [], {}], "Object": ["data", "Object", [], [], {}], diff --git a/tests/type-check/bad/table.arr b/tests/type-check/bad/table.arr new file mode 100644 index 000000000..d5e41731a --- /dev/null +++ b/tests/type-check/bad/table.arr @@ -0,0 +1,10 @@ +email :: Table = + table: sender, subject + row: "Matthias", "hi" + row: "Kathi", "foo" + row: "Joe", "bar" + row: "Matthias", "bye" + end + +# select-columns :: List -> Table +all-columns-tbl-selected = tbl.select-columns([list: 10, 11]) diff --git a/tests/type-check/good/table.arr b/tests/type-check/good/table.arr index c55648c58..7a00f7d13 100644 --- a/tests/type-check/good/table.arr +++ b/tests/type-check/good/table.arr @@ -1,13 +1,88 @@ -email :: Table = - table: sender, subject - row: "Matthias", "hi" - row: "Kathi", "foo" - row: "Joe", "bar" - row: "Matthias", "bye" - end +import tables as T + +#=============== Set Up ================== # tbl = table: name, age row: "Bob", 12 row: "Alice", 15 row: "Eve", 13 -end \ No newline at end of file +end + +tbl-2 = table: name, age + row: "Rob", 14 +end + +fun allTrue(x) -> Boolean: + true +end + +#=============== Table ================== # + +# length :: () -> Number +tbl.length() + +# add-column :: (String, List) -> Table +tbl.add-column("gender", [list: "man", "lady", "lady"]) + +# row-n :: Number -> Row +row-1 = tbl.row-n(1) + +# column :: (String) -> List +age-column = tbl.column("age") + +# select-columns :: (List) -> Table +tbl.select-columns([list: "name", "age"]) + +# all-columns :: () -> List> +tbl.all-columns() + +# all-rows :: () -> List +tbl.all-rows() + +# column-names :: () -> List +tbl.column-names() + +# build-column :: (String, (Row -> Col)) -> Table +tbl.build-column("is-cool", allTrue) + +# increasing-by :: (String) -> Table +tbl.increasing-by("age") + +# decreasing-by :: (String) -> Table +tbl.decreasing-by("age") + +# order-by :: (String, Boolean) -> Table +tbl.order-by("age", false) + +# stack :: (Table) -> Table +tbl.stack(tbl-2) + +# empty :: () -> Table +tbl.empty() + +# drop :: (String) -> Table +tbl.drop("age") + +# rename-column :: (String, String) -> Table +tbl.rename-column("age", "years-old") + +# column-n :: (Number) -> Col +tbl.column-n(1) + +# filter :: (Col -> Boolean) -> Table +tbl.filter(allTrue) + +# filter-by :: (String, (Col -> Boolean)) -> Table +tbl.filter-by("age", allTrue) + +# TODO: after fix raw-row, use a uniquely constructed row here +# add-row :: Row -> Table +tbl.add-row(row-1) + +#=============== Row ================== # + +# get-column-names :: () -> List +row-1-column-names = row-1.get-column-names() + +# get-value :: (String) -> Col +row-1.get-value("age")