@@ -5,8 +5,9 @@ use std::collections::{HashMap, HashSet};
5
5
6
6
use crate :: {
7
7
ast:: {
8
- self , EnumDef , Expr , ExprEnum , Mutability , Op , ParamDef , Pattern , PatternEnum , Stmt ,
9
- StmtEnum , StructDef , Type , UnaryOp , Variant , VariantExpr , VariantExprEnum ,
8
+ self , ConstDef , ConstExpr , EnumDef , Expr , ExprEnum , Mutability , Op , ParamDef , Pattern ,
9
+ PatternEnum , Stmt , StmtEnum , StructDef , Type , UnaryOp , Variant , VariantExpr ,
10
+ VariantExprEnum ,
10
11
} ,
11
12
env:: Env ,
12
13
token:: { MetaInfo , SignedNumType , UnsignedNumType } ,
@@ -50,7 +51,7 @@ pub enum TypeErrorEnum {
50
51
/// The struct constructor is missing the specified field.
51
52
MissingStructField ( String , String ) ,
52
53
/// No enum declaration with the specified name exists.
53
- UnknownEnum ( String ) ,
54
+ UnknownEnum ( String , String ) ,
54
55
/// The enum exists, but no variant declaration with the specified name was found.
55
56
UnknownEnumVariant ( String , String ) ,
56
57
/// No variable or function with the specified name exists in the current scope.
@@ -137,8 +138,8 @@ impl std::fmt::Display for TypeErrorEnum {
137
138
TypeErrorEnum :: MissingStructField ( struct_name, struct_field) => f. write_fmt (
138
139
format_args ! ( "Field '{struct_field}' is missing for struct '{struct_name}'" ) ,
139
140
) ,
140
- TypeErrorEnum :: UnknownEnum ( enum_name) => {
141
- f. write_fmt ( format_args ! ( "Unknown enum '{enum_name}'" ) )
141
+ TypeErrorEnum :: UnknownEnum ( enum_name, enum_variant ) => {
142
+ f. write_fmt ( format_args ! ( "Unknown enum '{enum_name}::{enum_variant} '" ) )
142
143
}
143
144
TypeErrorEnum :: UnknownEnumVariant ( enum_name, enum_variant) => f. write_fmt (
144
145
format_args ! ( "Unknown enum variant '{enum_name}::{enum_variant}'" ) ,
@@ -277,21 +278,27 @@ impl Type {
277
278
278
279
/// Static top-level definitions of enums and functions.
279
280
pub struct Defs < ' a > {
281
+ consts : HashMap < & ' a str , & ' a Type > ,
280
282
structs : HashMap < & ' a str , ( Vec < & ' a str > , HashMap < & ' a str , Type > ) > ,
281
283
enums : HashMap < & ' a str , HashMap < & ' a str , Option < Vec < Type > > > > ,
282
284
fns : HashMap < & ' a str , & ' a UntypedFnDef > ,
283
285
}
284
286
285
287
impl < ' a > Defs < ' a > {
286
288
pub ( crate ) fn new (
289
+ const_defs : & ' a HashMap < String , Type > ,
287
290
struct_defs : & ' a HashMap < String , StructDef > ,
288
291
enum_defs : & ' a HashMap < String , EnumDef > ,
289
292
) -> Self {
290
293
let mut defs = Self {
294
+ consts : HashMap :: new ( ) ,
291
295
structs : HashMap :: new ( ) ,
292
296
enums : HashMap :: new ( ) ,
293
297
fns : HashMap :: new ( ) ,
294
298
} ;
299
+ for ( const_name, ty) in const_defs. iter ( ) {
300
+ defs. consts . insert ( const_name, & ty) ;
301
+ }
295
302
for ( struct_name, struct_def) in struct_defs. iter ( ) {
296
303
let mut field_names = Vec :: with_capacity ( struct_def. fields . len ( ) ) ;
297
304
let mut field_types = HashMap :: with_capacity ( struct_def. fields . len ( ) ) ;
@@ -338,6 +345,63 @@ impl UntypedProgram {
338
345
struct_names,
339
346
enum_names,
340
347
} ;
348
+ let mut const_deps: HashMap < String , HashMap < String , ( String , Type ) > > = HashMap :: new ( ) ;
349
+ let mut const_types = HashMap :: with_capacity ( self . const_defs . len ( ) ) ;
350
+ let mut const_defs = HashMap :: with_capacity ( self . const_defs . len ( ) ) ;
351
+ {
352
+ let top_level_defs = TopLevelTypes {
353
+ struct_names : HashSet :: new ( ) ,
354
+ enum_names : HashSet :: new ( ) ,
355
+ } ;
356
+ let mut env = Env :: new ( ) ;
357
+ let mut fns = TypedFns {
358
+ currently_being_checked : HashSet :: new ( ) ,
359
+ typed : HashMap :: new ( ) ,
360
+ } ;
361
+ let defs = Defs {
362
+ consts : HashMap :: new ( ) ,
363
+ structs : HashMap :: new ( ) ,
364
+ enums : HashMap :: new ( ) ,
365
+ fns : HashMap :: new ( ) ,
366
+ } ;
367
+ for ( const_name, const_def) in self . const_defs . iter ( ) {
368
+ match & const_def. value {
369
+ ConstExpr :: Literal ( expr) => {
370
+ match expr. type_check ( & top_level_defs, & mut env, & mut fns, & defs) {
371
+ Ok ( mut expr) => {
372
+ if let Err ( errs) = check_type ( & mut expr, & const_def. ty ) {
373
+ errors. extend ( errs) ;
374
+ }
375
+ const_defs. insert (
376
+ const_name. clone ( ) ,
377
+ ConstDef {
378
+ ty : const_def. ty . clone ( ) ,
379
+ value : ConstExpr :: Literal ( expr) ,
380
+ meta : const_def. meta ,
381
+ } ,
382
+ ) ;
383
+ }
384
+ Err ( errs) => {
385
+ for e in errs {
386
+ if let Some ( e) = e {
387
+ if let TypeError ( TypeErrorEnum :: UnknownEnum ( p, n) , _) = e {
388
+ // ignore this error, constant can be provided later during compilation
389
+ const_deps. entry ( p) . or_default ( ) . insert (
390
+ n,
391
+ ( const_name. clone ( ) , const_def. ty . clone ( ) ) ,
392
+ ) ;
393
+ } else {
394
+ errors. push ( Some ( e) ) ;
395
+ }
396
+ }
397
+ }
398
+ }
399
+ }
400
+ const_types. insert ( const_name. clone ( ) , const_def. ty . clone ( ) ) ;
401
+ }
402
+ }
403
+ }
404
+ }
341
405
let mut struct_defs = HashMap :: with_capacity ( self . struct_defs . len ( ) ) ;
342
406
for ( struct_name, struct_def) in self . struct_defs . iter ( ) {
343
407
let meta = struct_def. meta ;
@@ -372,7 +436,7 @@ impl UntypedProgram {
372
436
enum_defs. insert ( enum_name. clone ( ) , EnumDef { variants, meta } ) ;
373
437
}
374
438
375
- let mut untyped_defs = Defs :: new ( & struct_defs, & enum_defs) ;
439
+ let mut untyped_defs = Defs :: new ( & const_types , & struct_defs, & enum_defs) ;
376
440
let mut checked_fn_defs = TypedFns :: new ( ) ;
377
441
for ( fn_name, fn_def) in self . fn_defs . iter ( ) {
378
442
untyped_defs. fns . insert ( fn_name, fn_def) ;
@@ -406,6 +470,8 @@ impl UntypedProgram {
406
470
}
407
471
if errors. is_empty ( ) {
408
472
Ok ( TypedProgram {
473
+ const_deps,
474
+ const_defs,
409
475
struct_defs,
410
476
enum_defs,
411
477
fn_defs,
@@ -677,12 +743,15 @@ impl UntypedExpr {
677
743
Some ( ( None , _mutability) ) => {
678
744
return Err ( vec ! [ None ] ) ;
679
745
}
680
- None => {
681
- return Err ( vec ! [ Some ( TypeError (
682
- TypeErrorEnum :: UnknownIdentifier ( identifier. clone( ) ) ,
683
- meta,
684
- ) ) ] ) ;
685
- }
746
+ None => match defs. consts . get ( identifier. as_str ( ) ) {
747
+ Some ( & ty) => ( ExprEnum :: Identifier ( identifier. clone ( ) ) , ty. clone ( ) ) ,
748
+ None => {
749
+ return Err ( vec ! [ Some ( TypeError (
750
+ TypeErrorEnum :: UnknownIdentifier ( identifier. clone( ) ) ,
751
+ meta,
752
+ ) ) ] ) ;
753
+ }
754
+ } ,
686
755
} ,
687
756
ExprEnum :: ArrayLiteral ( fields) => {
688
757
let mut errors = vec ! [ ] ;
@@ -966,9 +1035,9 @@ impl UntypedExpr {
966
1035
)
967
1036
}
968
1037
ExprEnum :: EnumLiteral ( identifier, variant) => {
1038
+ let VariantExpr ( variant_name, variant, variant_meta) = variant. as_ref ( ) ;
969
1039
if let Some ( enum_def) = defs. enums . get ( identifier. as_str ( ) ) {
970
- let VariantExpr ( variant_name, variant, meta) = variant. as_ref ( ) ;
971
- let meta = * meta;
1040
+ let meta = * variant_meta;
972
1041
if let Some ( types) = enum_def. get ( variant_name. as_str ( ) ) {
973
1042
match ( variant, types) {
974
1043
( VariantExprEnum :: Unit , None ) => {
@@ -1039,7 +1108,8 @@ impl UntypedExpr {
1039
1108
return Err ( vec ! [ Some ( TypeError ( e, meta) ) ] ) ;
1040
1109
}
1041
1110
} else {
1042
- let e = TypeErrorEnum :: UnknownEnum ( identifier. clone ( ) ) ;
1111
+ let e =
1112
+ TypeErrorEnum :: UnknownEnum ( identifier. clone ( ) , variant_name. to_string ( ) ) ;
1043
1113
return Err ( vec ! [ Some ( TypeError ( e, meta) ) ] ) ;
1044
1114
}
1045
1115
}
@@ -1402,7 +1472,7 @@ impl UntypedPattern {
1402
1472
return Err ( vec ! [ Some ( TypeError ( e, meta) ) ] ) ;
1403
1473
}
1404
1474
} else {
1405
- let e = TypeErrorEnum :: UnknownEnum ( enum_name. clone ( ) ) ;
1475
+ let e = TypeErrorEnum :: UnknownEnum ( enum_name. clone ( ) , variant_name . to_string ( ) ) ;
1406
1476
return Err ( vec ! [ Some ( TypeError ( e, meta) ) ] ) ;
1407
1477
}
1408
1478
}
0 commit comments