Skip to content

Commit 6786fb9

Browse files
committed
Type checker compiles and runs
1 parent 477b7f2 commit 6786fb9

File tree

9 files changed

+449
-154
lines changed

9 files changed

+449
-154
lines changed

include/yoyo/ir_gen.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ namespace Yoyo
4949
requires std::same_as<std::remove_cvref_t<decltype(*list.begin())>, Type>
5050
{
5151
if (std::ranges::empty(list)) return "";
52-
std::string final = "::<" + list.begin()->full_name();
53-
for (auto& tp : std::ranges::subrange(list.begin() + 1, list.end()))
52+
std::string final = "::<" + (*list.begin()).full_name();
53+
for (const auto& tp : std::ranges::subrange(list.begin() + 1, list.end()))
5454
final += "," + tp.full_name();
5555
final += ">";
5656
return final;

include/yoyo/type.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,14 @@ namespace Yoyo
112112
[[nodiscard]] bool is_lambda() const {return name.starts_with("__lambda");}
113113
[[nodiscard]] std::string full_name() const;
114114
[[nodiscard]] std::string full_name_no_block() const;
115+
[[nodiscard]] std::string full_name_no_generics() const;
115116
[[nodiscard]] std::string pretty_name(const std::string& block) const;
116117

117118
[[nodiscard]] size_t bitsize(IRGenerator* irgen) const;
118119
//there's no actual sorting, just to fulfill `set` requirements
119-
bool operator<(const Type& other) const
120+
auto operator<=>(const Type& other) const
120121
{
121-
if(module == other.module) return name < other.name;
122-
return module < other.module;
123-
122+
return full_name() <=> other.full_name();
124123
}
125124

126125
};

include/yoyo/type_checker.h

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ namespace Yoyo
8181
Type type;
8282
Expression* expr;
8383
};
84+
struct NonOwningConstraint {
85+
Type type;
86+
Expression* expr;
87+
};
8488
// type can be called (a function or lambda)
8589
struct IsInvocableConstraint {
8690
Type type;
@@ -137,32 +141,35 @@ namespace Yoyo
137141
IsReturnOfConstraint,
138142
ImplInterfaceConstraint,
139143
ExtractsToConstraint,
140-
RefExtractsToConstraint
144+
RefExtractsToConstraint,
145+
NonOwningConstraint
141146
>;
142147
/// represents the possible types a variable can be
143148
class Domain {
144-
enum TriState : uint8_t { None = 0, False, True };
145149
bool is_infinite = true;
146-
TriState is_owning = None;
147-
148150
public:
149151
// set of concrete types a type can be
150152
// it must be one of the elements in a group
151153
struct Group {
152154
std::vector<Type> types;
153155
void add_type(Type&&);
154156
};
155-
std::optional<Error> add_and_intersect(Group&&);
156-
void constrain_to_store(uint64_t);
157-
void constrain_to_store(int64_t);
158-
void constrain_to_store(double);
159-
std::optional<Error> merge_intersect(Domain&&);
160-
std::optional<Error> equal_constrain(Type&& other);
157+
// add a group of types and intersect it with the current group
158+
[[nodiscard]] std::optional<Error> add_and_intersect(Group&&);
159+
[[nodiscard]] std::optional<Error> constrain_to_store(uint64_t);
160+
[[nodiscard]] std::optional<Error> constrain_to_store(int64_t);
161+
[[nodiscard]] std::optional<Error> constrain_to_store(double);
162+
// basically `add_and_intersect` but with an entire domain
163+
[[nodiscard]] std::optional<Error> merge_intersect(Domain&&);
164+
// this solves the domain
165+
[[nodiscard]] std::optional<Error> equal_constrain(Type other);
166+
bool is_solved();
167+
Type get_solution();
161168
private:
162-
std::vector<Group> concrete_types;
169+
Group concrete_types;
163170
};
164171
// This is a union-find
165-
// but variables maintain thier domain (set of types they can possibly be)
172+
// but variables maintain their domain (set of types they can possibly be)
166173
// checked with each constraint
167174
struct UnificationTable {
168175
std::vector<uint32_t> parents;
@@ -193,12 +200,21 @@ namespace Yoyo
193200
struct TypeCheckerState {
194201
std::vector<std::unordered_map<std::string, Type>> variables;
195202
std::vector<TypeCheckerConstraint> constraints;
203+
UnificationTable tbl;
204+
// the return type of the function being checked
196205
Type return_type;
206+
// Creates a new type variable
197207
Type new_type_var();
208+
// Adds a new constraint to be checked
209+
// (should not be called by the constraint checker, it has a special method for that)
198210
void add_constraint(TypeCheckerConstraint);
199-
void unify_types(const Type&, const Type&);
211+
// given 2 type variables, make them equal to each other
212+
void unify_types(const Type&, const Type&, IRGenerator* irgen);
213+
// append a new block for variables
200214
void push_variable_block();
215+
// remove a block for variables
201216
void pop_variable_block();
217+
// register a new variable
202218
void create_variable(std::string name, Type type);
203219
// applies a type substitution if possible
204220
// else converts it to its most solved form
@@ -211,6 +227,7 @@ namespace Yoyo
211227
bool has_error;
212228
IRGenerator* irgen;
213229
TypeCheckerState* state;
230+
std::vector<TypeCheckerConstraint> temp_constraints;
214231
bool operator()(IsIntegerConstraint& con);
215232
bool operator()(CanStoreIntegerConstraint& con);
216233
bool operator()(IsFloatConstraint& con);
@@ -230,6 +247,7 @@ namespace Yoyo
230247
bool operator()(ImplInterfaceConstraint& con);
231248
bool operator()(ExtractsToConstraint& con);
232249
bool operator()(RefExtractsToConstraint& con);
250+
bool operator()(NonOwningConstraint& con);
233251

234252
void add_new_constraint(TypeCheckerConstraint);
235253
};
@@ -240,7 +258,7 @@ namespace Yoyo
240258
TypeCheckerState* state;
241259
void operator()(FunctionDeclaration*) {}
242260
void operator()(ClassDeclaration*) {}
243-
void operator()(VariableDeclaration*) {}
261+
void operator()(VariableDeclaration*);
244262
void operator()(IfStatement*);
245263
void operator()(WhileStatement*);
246264
void operator()(ForStatement*);
@@ -252,18 +270,18 @@ namespace Yoyo
252270
void operator()(ModuleImport*) {}
253271
void operator()(ConditionalExtraction*);
254272
void operator()(WithStatement*);
255-
void operator()(OperatorOverload*);
256-
void operator()(GenericFunctionDeclaration*);
257-
void operator()(AliasDeclaration*);
258-
void operator()(GenericAliasDeclaration*);
259-
void operator()(GenericClassDeclaration*);
260-
void operator()(InterfaceDeclaration*);
261-
void operator()(BreakStatement*);
262-
void operator()(ContinueStatement*);
263-
void operator()(ConstantDeclaration*);
264-
void operator()(CImportDeclaration*);
265-
void operator()(UnionDeclaration*);
266-
void operator()(MacroDeclaration*);
273+
void operator()(OperatorOverload*) {}
274+
void operator()(GenericFunctionDeclaration*) {}
275+
void operator()(AliasDeclaration*) {}
276+
void operator()(GenericAliasDeclaration*) {}
277+
void operator()(GenericClassDeclaration*) {}
278+
void operator()(InterfaceDeclaration*) {}
279+
void operator()(BreakStatement*) {}
280+
void operator()(ContinueStatement*) {}
281+
void operator()(ConstantDeclaration*){}
282+
void operator()(CImportDeclaration*) {}
283+
void operator()(UnionDeclaration*) {}
284+
void operator()(MacroDeclaration*) {}
267285

268286
FunctionType operator()(IntegerLiteral*) const;
269287
FunctionType operator()(BooleanLiteral*) const;

src/yoyo/borrow_checker.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,7 @@ namespace Yoyo
211211
auto tuple = checker.make_object();
212212
for (auto& elem : exp->elements) {
213213
auto elem_eval = std::visit(*this, elem->toVariant());
214-
auto type = std::visit(ExpressionTypeChecker{ irgen }, elem->toVariant());
215-
clone_into(checker, elem_eval, tuple, *type, exp, irgen); // TODO: update when type system is better
214+
clone_into(checker, elem_eval, tuple, exp->evaluated_type, exp, irgen); // TODO: update when type system is better
216215
}
217216
return tuple;
218217
}

src/yoyo/type.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ namespace Yoyo
2323
}
2424
return final;
2525
}
26+
std::string Type::full_name_no_generics() const
27+
{
28+
return block_hash + name;
29+
}
2630
//TODO: move to util header !??
2731
std::vector<std::string_view> split(std::string_view str, std::string_view delim)
2832
{
@@ -804,6 +808,8 @@ namespace Yoyo
804808
return "[" + pretty_name_suffix(tp.subtypes[0]) + ":&]";
805809
if (tp.name == "__called_fn")
806810
return "called " + tp.signature->pretty_name("");
811+
if (tp.name.starts_with("?"))
812+
return "{unknown}";
807813
return tp.name;
808814
}
809815
std::string Type::pretty_name(const std::string& block) const

0 commit comments

Comments
 (0)