19
19
namespace Rust {
20
20
namespace Analysis {
21
21
22
- TypeResolution::TypeResolution (AST::Crate &crate) : crate (crate)
22
+ TypeResolution::TypeResolution (AST::Crate &crate, TopLevelScan &toplevel)
23
+ : crate (crate), toplevel (toplevel)
23
24
{
24
25
typeScope.Push ();
25
26
scope.Push ();
@@ -50,9 +51,9 @@ TypeResolution::~TypeResolution ()
50
51
}
51
52
52
53
bool
53
- TypeResolution::ResolveNamesAndTypes (AST::Crate &crate)
54
+ TypeResolution::ResolveNamesAndTypes (AST::Crate &crate, TopLevelScan &toplevel )
54
55
{
55
- TypeResolution resolver (crate);
56
+ TypeResolution resolver (crate, toplevel );
56
57
return resolver.go ();
57
58
}
58
59
@@ -65,6 +66,30 @@ TypeResolution::go ()
65
66
return true ;
66
67
}
67
68
69
+ bool
70
+ TypeResolution::typesAreCompatible (AST::Type *lhs, AST::Type *rhs,
71
+ Location locus)
72
+ {
73
+ lhs->accept_vis (*this );
74
+ rhs->accept_vis (*this );
75
+
76
+ auto rhsTypeStr = typeComparisonBuffer.back ();
77
+ typeComparisonBuffer.pop_back ();
78
+ auto lhsTypeStr = typeComparisonBuffer.back ();
79
+ typeComparisonBuffer.pop_back ();
80
+
81
+ // FIXME this needs to handle the cases of an i8 going into an i32 which is
82
+ // compatible
83
+ if (lhsTypeStr.compare (rhsTypeStr))
84
+ {
85
+ rust_error_at (locus, " E0308: expected: %s, found %s" ,
86
+ lhsTypeStr.c_str (), rhsTypeStr.c_str ());
87
+ return false ;
88
+ }
89
+
90
+ return true ;
91
+ }
92
+
68
93
void
69
94
TypeResolution::visit (AST::Token &tok)
70
95
{}
@@ -124,18 +149,21 @@ TypeResolution::visit (AST::TypePathSegmentFunction &segment)
124
149
void
125
150
TypeResolution::visit (AST::TypePath &path)
126
151
{
127
- printf (" TypePath: %s\n " , path.as_string ().c_str ());
152
+ // this may not be robust enough for type comparisons but lets try it for now
153
+ typeComparisonBuffer.push_back (path.as_string ());
128
154
}
129
155
130
156
void
131
157
TypeResolution::visit (AST::QualifiedPathInExpression &path)
132
158
{
133
- printf ( " QualifiedPathInExpression: %s \n " , path.as_string (). c_str ());
159
+ typeComparisonBuffer. push_back ( path.as_string ());
134
160
}
135
161
136
162
void
137
163
TypeResolution::visit (AST::QualifiedPathInType &path)
138
- {}
164
+ {
165
+ typeComparisonBuffer.push_back (path.as_string ());
166
+ }
139
167
140
168
// rust-expr.h
141
169
void
@@ -245,7 +273,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr)
245
273
// scope will require knowledge of the type
246
274
247
275
// do the lhsType and the rhsType match
248
- // TODO
276
+ typesAreCompatible (lhsType, rhsType, expr. right_expr -> get_locus_slow ());
249
277
}
250
278
251
279
void
@@ -254,9 +282,7 @@ TypeResolution::visit (AST::ComparisonExpr &expr)
254
282
255
283
void
256
284
TypeResolution::visit (AST::LazyBooleanExpr &expr)
257
- {
258
- printf (" LazyBooleanExpr: %s\n " , expr.as_string ().c_str ());
259
- }
285
+ {}
260
286
261
287
void
262
288
TypeResolution::visit (AST::TypeCastExpr &expr)
@@ -265,14 +291,41 @@ TypeResolution::visit (AST::TypeCastExpr &expr)
265
291
void
266
292
TypeResolution::visit (AST::AssignmentExpr &expr)
267
293
{
268
- printf (" AssignmentExpr: %s\n " , expr.as_string ().c_str ());
294
+ size_t before;
295
+ before = typeBuffer.size ();
296
+ expr.visit_lhs (*this );
297
+ if (typeBuffer.size () <= before)
298
+ {
299
+ rust_error_at (expr.locus , " unable to determine lhs type" );
300
+ return ;
301
+ }
302
+
303
+ auto lhsType = typeBuffer.back ();
304
+ typeBuffer.pop_back ();
305
+
306
+ before = typeBuffer.size ();
307
+ expr.visit_rhs (*this );
308
+ if (typeBuffer.size () <= before)
309
+ {
310
+ rust_error_at (expr.locus , " unable to determine rhs type" );
311
+ return ;
312
+ }
313
+
314
+ auto rhsType = typeBuffer.back ();
315
+ // not poping because we will be checking they match and the
316
+ // scope will require knowledge of the type
317
+
318
+ // do the lhsType and the rhsType match
319
+ if (!typesAreCompatible (lhsType, rhsType,
320
+ expr.right_expr ->get_locus_slow ()))
321
+ return ;
322
+
323
+ // is the lhs mutable?
269
324
}
270
325
271
326
void
272
327
TypeResolution::visit (AST::CompoundAssignmentExpr &expr)
273
- {
274
- printf (" CompoundAssignmentExpr: %s\n " , expr.as_string ().c_str ());
275
- }
328
+ {}
276
329
277
330
void
278
331
TypeResolution::visit (AST::GroupedExpr &expr)
@@ -340,9 +393,13 @@ TypeResolution::visit (AST::EnumExprTuple &expr)
340
393
void
341
394
TypeResolution::visit (AST::EnumExprFieldless &expr)
342
395
{}
396
+
343
397
void
344
398
TypeResolution::visit (AST::CallExpr &expr)
345
- {}
399
+ {
400
+ printf (" CallExpr: %s\n " , expr.as_string ().c_str ());
401
+ }
402
+
346
403
void
347
404
TypeResolution::visit (AST::MethodCallExpr &expr)
348
405
{}
@@ -481,18 +538,25 @@ TypeResolution::visit (AST::UseDeclaration &use_decl)
481
538
void
482
539
TypeResolution::visit (AST::Function &function)
483
540
{
541
+ // always emit the function with return type in the event of nil return type
542
+ // its a marker for a void function
484
543
scope.Insert (function.function_name , function.return_type .get ());
485
544
486
545
scope.Push ();
487
- printf (" INSIDE FUNCTION: %s\n " , function.function_name .c_str ());
488
-
489
546
for (auto ¶m : function.function_params )
490
547
{
491
- printf (" FUNC PARAM: %s\n " , param.as_string ().c_str ());
492
- }
548
+ auto before = letPatternBuffer.size ();
549
+ param.param_name ->accept_vis (*this );
550
+ if (letPatternBuffer.size () <= before)
551
+ {
552
+ rust_error_at (param.locus , " failed to analyse parameter name" );
553
+ return ;
554
+ }
493
555
494
- // ensure return types
495
- // TODO
556
+ auto paramName = letPatternBuffer.back ();
557
+ letPatternBuffer.pop_back ();
558
+ scope.Insert (paramName.variable_ident , param.type .get ());
559
+ }
496
560
497
561
// walk the expression body
498
562
for (auto &stmt : function.function_body ->statements )
@@ -713,8 +777,11 @@ TypeResolution::visit (AST::LetStmt &stmt)
713
777
714
778
if (stmt.has_type () && stmt.has_init_expr ())
715
779
{
716
- auto declaredTyped = stmt.type .get ();
717
- // TODO compare this type to the inferred type to ensure they match
780
+ if (!typesAreCompatible (stmt.type .get (), inferedType,
781
+ stmt.init_expr ->get_locus_slow ()))
782
+ {
783
+ return ;
784
+ }
718
785
}
719
786
else if (stmt.has_type () && !stmt.has_init_expr ())
720
787
{
@@ -727,8 +794,7 @@ TypeResolution::visit (AST::LetStmt &stmt)
727
794
// ensure the decl has the type set for compilation later on
728
795
if (!stmt.has_type ())
729
796
{
730
- // FIXME
731
- // stmt.type = inferedType;
797
+ stmt.inferedType = inferedType;
732
798
}
733
799
734
800
// get all the names part of this declaration and add the types to the scope
@@ -743,16 +809,12 @@ TypeResolution::visit (AST::LetStmt &stmt)
743
809
void
744
810
TypeResolution::visit (AST::ExprStmtWithoutBlock &stmt)
745
811
{
746
- printf (" ExprStmtWithoutBlock: %s\n " , stmt.as_string ().c_str ());
747
812
stmt.expr ->accept_vis (*this );
748
813
}
749
814
750
815
void
751
816
TypeResolution::visit (AST::ExprStmtWithBlock &stmt)
752
- {
753
- printf (" ExprStmtWithBlock: %s\n " , stmt.as_string ().c_str ());
754
- stmt.expr ->accept_vis (*this );
755
- }
817
+ {}
756
818
757
819
// rust-type.h
758
820
void
0 commit comments