From 27247101e359c50506cd6d292a5f84816934e674 Mon Sep 17 00:00:00 2001 From: mkolosick Date: Mon, 13 Nov 2017 21:48:27 -0500 Subject: [PATCH 1/3] Adding update and extend type support for data types --- src/arr/compiler/type-check.arr | 19 +++++++++++++------ .../bad/data-as-object-extend-missing.arr | 5 +++++ .../bad/data-as-object-extend-ref.arr | 5 +++++ .../bad/data-as-object-extend-wrong-type.arr | 5 +++++ .../bad/data-as-object-update-missing.arr | 5 +++++ .../bad/data-as-object-update-non-ref.arr | 5 +++++ .../bad/data-as-object-update-wrong.arr | 5 +++++ tests/type-check/good/data-as-object.arr | 6 ++++++ 8 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 tests/type-check/bad/data-as-object-extend-missing.arr create mode 100644 tests/type-check/bad/data-as-object-extend-ref.arr create mode 100644 tests/type-check/bad/data-as-object-extend-wrong-type.arr create mode 100644 tests/type-check/bad/data-as-object-update-missing.arr create mode 100644 tests/type-check/bad/data-as-object-update-non-ref.arr create mode 100644 tests/type-check/bad/data-as-object-update-wrong.arr create mode 100644 tests/type-check/good/data-as-object.arr diff --git a/src/arr/compiler/type-check.arr b/src/arr/compiler/type-check.arr index 5e57549f7e..67cf8ec430 100644 --- a/src/arr/compiler/type-check.arr +++ b/src/arr/compiler/type-check.arr @@ -1858,8 +1858,8 @@ end fun synthesis-extend(update-loc :: Loc, obj :: Expr, obj-type :: Type, fields :: List, context :: Context) -> TypingResult: collect-members(fields, false, context).typing-bind(lam(new-members, shadow context): - instantiate-object-type(obj-type, context).typing-bind(lam(shadow obj-type, shadow context): - cases(Type) obj-type: + instantiate-object-type(obj-type, context).typing-bind(lam(instantiated-obj-type, shadow context): + cases(Type) instantiated-obj-type: | t-record(t-fields, _, inferred) => final-fields = new-members.fold-keys(lam(key, final-fields): final-fields.set(key, new-members.get-value(key)) @@ -1868,7 +1868,10 @@ fun synthesis-extend(update-loc :: Loc, obj :: Expr, obj-type :: Type, fields :: | t-existential(_, l, _) => typing-error([list: C.unable-to-infer(l)]) | else => - typing-error([list: C.incorrect-type-expression(tostring(obj-type), obj-type.l, "an object type", update-loc, obj)]) + shadow context = new-members.fold-keys(lam(key, shadow context): + context.add-field-constraint(instantiated-obj-type, key, new-members.get-value(key)) + end, context) + typing-result(A.s-extend(update-loc, obj, fields), obj-type, context) end end) end) @@ -1876,13 +1879,13 @@ end fun synthesis-update(update-loc :: Loc, obj :: Expr, obj-type :: Type, fields :: List, context :: Context) -> TypingResult: collect-members(fields, false, context).typing-bind(lam(new-members, shadow context): - instantiate-object-type(obj-type, context).typing-bind(lam(shadow obj-type, shadow context): + instantiate-object-type(obj-type, context).typing-bind(lam(instantiated-obj-type, shadow context): cases(Type) obj-type: | t-record(t-fields, _, inferred) => foldr-fold-result(lam(key, shadow context, final-fields): cases(Option) t-fields.get(key): | none => - fold-errors([list: C.object-missing-field(key, tostring(obj-type), obj-type.l, update-loc)]) + fold-errors([list: C.object-missing-field(key, tostring(instantiated-obj-type), instantiated-obj-type.l, update-loc)]) | some(old-type) => cases(Type) old-type: | t-ref(onto, l, ref-inferred) => @@ -1898,7 +1901,11 @@ fun synthesis-update(update-loc :: Loc, obj :: Expr, obj-type :: Type, fields :: | t-existential(_, l, _) => typing-error([list: C.unable-to-infer(l)]) | else => - typing-error([list: C.incorrect-type-expression(tostring(obj-type), obj-type.l, "an object type", update-loc, obj)]) + shadow context = new-members.fold-keys(lam(key, shadow context): + member-type = new-members.get-value(key) + context.add-field-constraint(instantiated-obj-type, key, t-ref(member-type, member-type.l, false)) + end, context) + typing-result(A.s-update(update-loc, obj, fields), obj-type, context) end end) end) diff --git a/tests/type-check/bad/data-as-object-extend-missing.arr b/tests/type-check/bad/data-as-object-extend-missing.arr new file mode 100644 index 0000000000..01f57495cf --- /dev/null +++ b/tests/type-check/bad/data-as-object-extend-missing.arr @@ -0,0 +1,5 @@ +data Foo: + | bar(a :: Number, ref b :: String) +end + +bar(1, "a").{a: "a"} \ No newline at end of file diff --git a/tests/type-check/bad/data-as-object-extend-ref.arr b/tests/type-check/bad/data-as-object-extend-ref.arr new file mode 100644 index 0000000000..afb87b6320 --- /dev/null +++ b/tests/type-check/bad/data-as-object-extend-ref.arr @@ -0,0 +1,5 @@ +data Foo: + | bar(a :: Number, ref b :: String) +end + +bar(1, "a").{c: "a"} \ No newline at end of file diff --git a/tests/type-check/bad/data-as-object-extend-wrong-type.arr b/tests/type-check/bad/data-as-object-extend-wrong-type.arr new file mode 100644 index 0000000000..35848bf6e9 --- /dev/null +++ b/tests/type-check/bad/data-as-object-extend-wrong-type.arr @@ -0,0 +1,5 @@ +data Foo: + | bar(a :: Number, ref b :: String) +end + +bar(1, "a").{b: "b"} \ No newline at end of file diff --git a/tests/type-check/bad/data-as-object-update-missing.arr b/tests/type-check/bad/data-as-object-update-missing.arr new file mode 100644 index 0000000000..57ad8ff60c --- /dev/null +++ b/tests/type-check/bad/data-as-object-update-missing.arr @@ -0,0 +1,5 @@ +data Foo: + | bar(a :: Number, ref b :: String) +end + +bar(1, "a").{b: 3} \ No newline at end of file diff --git a/tests/type-check/bad/data-as-object-update-non-ref.arr b/tests/type-check/bad/data-as-object-update-non-ref.arr new file mode 100644 index 0000000000..97f7fb01a2 --- /dev/null +++ b/tests/type-check/bad/data-as-object-update-non-ref.arr @@ -0,0 +1,5 @@ +data Foo: + | bar(a :: Number, ref b :: String) +end + +bar(1, "a").{c: 3} \ No newline at end of file diff --git a/tests/type-check/bad/data-as-object-update-wrong.arr b/tests/type-check/bad/data-as-object-update-wrong.arr new file mode 100644 index 0000000000..57ad8ff60c --- /dev/null +++ b/tests/type-check/bad/data-as-object-update-wrong.arr @@ -0,0 +1,5 @@ +data Foo: + | bar(a :: Number, ref b :: String) +end + +bar(1, "a").{b: 3} \ No newline at end of file diff --git a/tests/type-check/good/data-as-object.arr b/tests/type-check/good/data-as-object.arr new file mode 100644 index 0000000000..59c86c67c9 --- /dev/null +++ b/tests/type-check/good/data-as-object.arr @@ -0,0 +1,6 @@ +data Foo: + | bar(a :: Number, ref b :: String) +end + +bar(1, "a").{a: 3} +bar(1, "b")!{b: "a"} \ No newline at end of file From ad313fb2cfe6ef172043b279d85d015998a42787 Mon Sep 17 00:00:00 2001 From: mkolosick Date: Mon, 13 Nov 2017 22:02:05 -0500 Subject: [PATCH 2/3] Fixed data-as-object tests --- tests/type-check/bad/data-as-object-extend-ref.arr | 3 ++- tests/type-check/bad/data-as-object-extend-wrong-type.arr | 3 ++- tests/type-check/bad/data-as-object-update-missing.arr | 3 ++- tests/type-check/bad/data-as-object-update-non-ref.arr | 3 ++- tests/type-check/bad/data-as-object-update-wrong.arr | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/type-check/bad/data-as-object-extend-ref.arr b/tests/type-check/bad/data-as-object-extend-ref.arr index afb87b6320..d8ac0068ce 100644 --- a/tests/type-check/bad/data-as-object-extend-ref.arr +++ b/tests/type-check/bad/data-as-object-extend-ref.arr @@ -2,4 +2,5 @@ data Foo: | bar(a :: Number, ref b :: String) end -bar(1, "a").{c: "a"} \ No newline at end of file +# bar(1, "a").b is a ref String while "a" is a String +bar(1, "a").{b: "a"} \ No newline at end of file diff --git a/tests/type-check/bad/data-as-object-extend-wrong-type.arr b/tests/type-check/bad/data-as-object-extend-wrong-type.arr index 35848bf6e9..f7e2610c87 100644 --- a/tests/type-check/bad/data-as-object-extend-wrong-type.arr +++ b/tests/type-check/bad/data-as-object-extend-wrong-type.arr @@ -2,4 +2,5 @@ data Foo: | bar(a :: Number, ref b :: String) end -bar(1, "a").{b: "b"} \ No newline at end of file +# bar(1, "a").a has type Number not String +bar(1, "a").{a: "b"} \ No newline at end of file diff --git a/tests/type-check/bad/data-as-object-update-missing.arr b/tests/type-check/bad/data-as-object-update-missing.arr index 57ad8ff60c..60e96538b5 100644 --- a/tests/type-check/bad/data-as-object-update-missing.arr +++ b/tests/type-check/bad/data-as-object-update-missing.arr @@ -2,4 +2,5 @@ data Foo: | bar(a :: Number, ref b :: String) end -bar(1, "a").{b: 3} \ No newline at end of file +# bar(1, "a") does not have a field c +bar(1, "a")!{c: 3} \ No newline at end of file diff --git a/tests/type-check/bad/data-as-object-update-non-ref.arr b/tests/type-check/bad/data-as-object-update-non-ref.arr index 97f7fb01a2..d21993beca 100644 --- a/tests/type-check/bad/data-as-object-update-non-ref.arr +++ b/tests/type-check/bad/data-as-object-update-non-ref.arr @@ -2,4 +2,5 @@ data Foo: | bar(a :: Number, ref b :: String) end -bar(1, "a").{c: 3} \ No newline at end of file +# bar(1, "a").a is a String but update is for refs +bar(1, "a")!{a: 3} \ No newline at end of file diff --git a/tests/type-check/bad/data-as-object-update-wrong.arr b/tests/type-check/bad/data-as-object-update-wrong.arr index 57ad8ff60c..d8c6f9eb89 100644 --- a/tests/type-check/bad/data-as-object-update-wrong.arr +++ b/tests/type-check/bad/data-as-object-update-wrong.arr @@ -2,4 +2,5 @@ data Foo: | bar(a :: Number, ref b :: String) end -bar(1, "a").{b: 3} \ No newline at end of file +# bar(1, "a").b has type String not Number +bar(1, "a")!{b: 3} \ No newline at end of file From ca12539667095e456eb141247a190fb66dd1e553 Mon Sep 17 00:00:00 2001 From: mkolosick Date: Sun, 17 Dec 2017 11:24:45 -0500 Subject: [PATCH 3/3] Fixed data-as-object-extend-missing test case --- tests/type-check/bad/data-as-object-extend-missing.arr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/type-check/bad/data-as-object-extend-missing.arr b/tests/type-check/bad/data-as-object-extend-missing.arr index 01f57495cf..bcfcbd4b69 100644 --- a/tests/type-check/bad/data-as-object-extend-missing.arr +++ b/tests/type-check/bad/data-as-object-extend-missing.arr @@ -2,4 +2,5 @@ data Foo: | bar(a :: Number, ref b :: String) end -bar(1, "a").{a: "a"} \ No newline at end of file +# bar(1, "a") does not have a field c +bar(1, "a").{c: "a"} \ No newline at end of file