Skip to content

Commit 783f412

Browse files
committed
Types Update. YAY. w bug fixes
1 parent e4513ce commit 783f412

11 files changed

Lines changed: 719 additions & 395 deletions

File tree

Interp/Interpreter.hxx

Lines changed: 459 additions & 352 deletions
Large diffs are not rendered by default.

Interp/Value.cxx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,13 @@ inline std::ostream& operator<<(std::ostream& os, const Environment& env) {
276276
if (std::holds_alternative<PackList>(lhs) and std::holds_alternative<PackList>(rhs))
277277
return get<PackList>(lhs)->values == get<PackList>(rhs)->values;
278278

279+
if (std::holds_alternative<ListValue>(lhs) and std::holds_alternative<ListValue>(lhs)) {
280+
return get<ListValue>(lhs).elts->values == get<ListValue>(rhs).elts->values;
281+
}
282+
283+
if (std::holds_alternative<MapValue>(lhs) and std::holds_alternative<MapValue>(lhs)) {
284+
return get<MapValue>(lhs).items->map == get<MapValue>(rhs).items->map;
285+
}
279286

280287
// error();
281288
return false;

Interp/Value.hxx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ struct Value : VariantType {
4949
using VariantType::operator=;
5050
};
5151

52+
using ValuePtr = std::shared_ptr<Value>;
53+
5254

5355
std::string stringify(const Value& value, const size_t indent = {});
5456
[[nodiscard]] bool operator==(const Value& lhs, const Value& rhs) noexcept;
@@ -86,7 +88,7 @@ template <typename ...Ts>
8688
using Environment = std::unordered_map<
8789
std::string,
8890
std::pair<
89-
std::shared_ptr<Value>,
91+
ValuePtr,
9092
type::TypePtr
9193
>
9294
>;

Tests/Test.cc

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,127 @@
99

1010

1111

12+
13+
TEST_CASE("Concepts 2", "[Type]") {
14+
const auto src = R"(
15+
MoreThan10 = (x: Int) => __builtin_gt(x, 10);
16+
LessThan20 = (x: Int) => __builtin_lt(x, 20);
17+
func = (x: MoreThan10): LessThan20 => __builtin_add(x, 5);
18+
func("meow");
19+
)";
20+
21+
REQUIRE_THROWS_AS(run(src), pie::except::TypeMismatch);
22+
}
23+
24+
25+
TEST_CASE("Concepts", "[Type]") {
26+
const auto src1 = R"(
27+
MoreThan10 = (x: Int) => __builtin_gt(x, 10);
28+
LessThan20 = (x: Int) => __builtin_lt(x, 20);
29+
a: MoreThan10 = 15;
30+
func = (x: MoreThan10): LessThan20 => __builtin_add(x, 5);
31+
func(13);
32+
)";
33+
34+
REQUIRE_NOTHROW(run(src1));
35+
36+
const auto src2 = R"(
37+
MoreThan10 = (x: Int) => __builtin_gt(x, 10);
38+
a: MoreThan10 = 5;
39+
)";
40+
41+
REQUIRE_THROWS_AS(run(src2), pie::except::TypeMismatch);
42+
43+
const auto src3 = R"(
44+
MoreThan10 = (x: Int) => __builtin_gt(x, 10);
45+
LessThan20 = (x: Int) => __builtin_lt(x, 20);
46+
func = (x: MoreThan10): LessThan20 => __builtin_add(x, 5);
47+
func(17);
48+
)";
49+
50+
REQUIRE_THROWS_AS(run(src3), pie::except::TypeMismatch);
51+
}
52+
53+
54+
55+
TEST_CASE("Types as Values - List of Bool vs {Bool}", "[Type]") {
56+
const auto src1 = R"(
57+
a: {Bool} = {true, false};
58+
v: {Type} = {Bool};
59+
x: v = {Bool};
60+
)";
61+
62+
REQUIRE_NOTHROW(run(src1));
63+
64+
const auto src2 = R"(
65+
x: {Bool} = {Bool};
66+
)";
67+
68+
REQUIRE_THROWS_AS(run(src2), pie::except::TypeMismatch);
69+
}
70+
71+
72+
73+
TEST_CASE("Expanding Pack in Partial Application", "[Func]") {
74+
const auto src = R"(
75+
print = __builtin_print;
76+
f = (a, b, c, z) => print(a, b, c, z);
77+
caller = (args: ...Any) => f(10, args...);
78+
new_closure = caller(1, 2);
79+
new_closure(1000);
80+
)";
81+
82+
83+
REQUIRE(run(src) == "10 1 2 1000");
84+
}
85+
86+
87+
88+
89+
TEST_CASE("Values as types w unions", "[Type]") {
90+
const auto src1 = R"(
91+
print = __builtin_print;
92+
93+
l1 = {1, 2, 3};
94+
l2 = {5, 6};
95+
x: union { l1; l2; } = {5, 6};
96+
print(x);
97+
x = {1, 2,3};
98+
print(x);
99+
100+
y: union { 1; "hi"; Bool; } = 1;
101+
print(y);
102+
y = "hi";
103+
print(y);
104+
y = true;
105+
print(y);
106+
y = false;
107+
print(y);
108+
)";
109+
110+
REQUIRE(run(src1) == R"({5, 6}
111+
{1, 2, 3}
112+
1
113+
hi
114+
true
115+
false)");
116+
117+
const auto src2 = R"(
118+
l1 = {1, 2, 3};
119+
l2 = {5, 6};
120+
x: union { l1; l2; } = {1, 2, 3, 5, 6};
121+
)";
122+
123+
REQUIRE_THROWS_AS(run(src2), pie::except::TypeMismatch);
124+
125+
const auto src3 = R"(
126+
y: union { 1; "hi"; Bool; } = "bye";
127+
)";
128+
129+
REQUIRE_THROWS_AS(run(src3), pie::except::TypeMismatch);
130+
}
131+
132+
12133
TEST_CASE("Redefining builtin type, espacially Any", "[Type]") {
13134
const auto src = R"(
14135
Any = class { };
@@ -442,7 +563,7 @@ x: d = 1.2;
442563
)";
443564

444565
REQUIRE_THROWS(run(src));
445-
REQUIRE_THROWS_MATCHES(run(src), except::TypeMismatch, Catch::Matchers::MessageMatches(Catch::Matchers::ContainsSubstring("Type mis-match!")));
566+
REQUIRE_THROWS_MATCHES(run(src), pie::except::TypeMismatch, Catch::Matchers::MessageMatches(Catch::Matchers::ContainsSubstring("Type mis-match!")));
446567
}
447568

448569

@@ -1365,7 +1486,7 @@ add(z = 1);
13651486

13661487

13671488
REQUIRE_THROWS_MATCHES(run(src1), std::runtime_error, Catch::Matchers::MessageMatches(Catch::Matchers::ContainsSubstring("Named argument" )));
1368-
REQUIRE_THROWS_MATCHES(run(src2), except::TypeMismatch, Catch::Matchers::MessageMatches(Catch::Matchers::ContainsSubstring("Type mis-match!")));
1489+
REQUIRE_THROWS_MATCHES(run(src2), pie::except::TypeMismatch, Catch::Matchers::MessageMatches(Catch::Matchers::ContainsSubstring("Type mis-match!")));
13691490
}
13701491

13711492

Tests/TestSuite.hxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ std::string run(const char* src) {
8181

8282
Capture c{};
8383

84-
Visitor visitor{std::move(ops)};
84+
interp::Visitor visitor{std::move(ops)};
8585
for (const auto& expr : exprs)
8686
std::visit(visitor, expr->variant());
8787

Type/Type.cxx

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "../Interp/Interpreter.hxx"
33

44
#include <ranges>
5+
#include <variant>
56

67

78

@@ -24,7 +25,7 @@ namespace type {
2425
bool ExprType::operator>=(const Type& other) const {
2526
if (dynamic_cast<const TryReassign*>(&other)) return true;
2627

27-
return text() == other.text(); // only check for equality sine ExprType is never greater than any other ExprType
28+
return text() == other.text(); // only check for equality since ExprType is never greater than any other ExprType
2829
// const auto& type = text();
2930
// return type == "Syntax" or type == "Any" or type == other.text();
3031
}
@@ -51,12 +52,41 @@ namespace type {
5152
// * Value Type * //
5253
std::string ValueType::text(const size_t indent) const { return stringify(*val, indent); }
5354

54-
bool ValueType::operator>=(const Type& other) const {
55-
const auto* other_type = dynamic_cast<const ValueType*>(&other);
56-
if (not other_type) return false;
55+
bool ValueType::typeCheck(interp::Visitor*, [[maybe_unused]] const value::Value& v, const TypePtr& other) const {
56+
if (std::holds_alternative<expr::Closure>(*val)) { // concept case. test the upcoming value
5757

58-
// return *this == other; // I think that's fine
59-
return *val == *other_type->val;
58+
}
59+
60+
if (*val == v) return true;
61+
62+
return *this >= *other;
63+
}
64+
65+
66+
67+
// * Concept Type * //
68+
std::string ConceptType::text(const size_t indent) const { return stringify(*func, indent); }
69+
70+
bool ConceptType::typeCheck(interp::Visitor* visitor, [[maybe_unused]] const value::Value& v, const TypePtr& other) const {
71+
// const auto* f = dynamic_cast<const expr::Closure*>(func.get());
72+
const auto& f = get<expr::Closure>(*func);
73+
interp::Visitor::ScopeGuard sg{visitor, interp::Visitor::EnvTag::FUNC, f.args_env, f.env};
74+
75+
76+
if (not f.type.params[0]->typeCheck(visitor, v, other)) return false;
77+
78+
sg.addEnv({{f.params[0],
79+
{
80+
std::make_shared<value::Value>(v),
81+
other
82+
}}}
83+
);
84+
85+
86+
auto ret = visitor->checkReturnType(std::visit(*visitor, f.body->variant()), f.type.ret);
87+
if (std::holds_alternative<bool>(ret)) return get<bool>(ret);
88+
89+
throw except::TypeMismatch{"Concept didn't return a boolean: " + stringify(*func)};
6090
}
6191

6292

@@ -152,7 +182,6 @@ namespace type {
152182
s += t->text(indent + 4) + "; ";
153183
}
154184

155-
156185
return s + '}';
157186
}
158187

@@ -163,11 +192,11 @@ namespace type {
163192
return false;
164193
}
165194

166-
bool UnionType::operator> (const Type& other) const {
167-
// for (const auto& type : types)
168-
// if (*type > other) return true;
169-
// return false;
195+
bool UnionType::typeCheck(interp::Visitor* visitor, [[maybe_unused]] const value::Value& v, const TypePtr& other) const {
196+
return std::ranges::any_of(types, [visitor, &v, &other](const auto& type) { return type->typeCheck(visitor, v, other); });
197+
}
170198

199+
bool UnionType::operator> (const Type& other) const {
171200
return std::ranges::any_of(types, [&other](const auto& type) { return *type > other; });
172201
};
173202

@@ -218,10 +247,6 @@ namespace type {
218247
const auto& that = dynamic_cast<const FuncType&>(other);
219248

220249
for (const auto& [type1, type2] : std::views::zip(params, that.params)) {
221-
// std::clog << "type1: " << type1->text() << std::endl;
222-
// std::clog << "type2: " << type2->text() << std::endl;
223-
// std::clog << "not (" << type2->text() << " >= " << type1->text() << "): " << not (*type2 >= *type1) << std::endl;
224-
225250
// if (*type1 > *type2) return false; // args have an inverse relationship
226251

227252
if (not (*type2 >= *type1)) return false; // args have an inverse relationship

0 commit comments

Comments
 (0)