1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+
5
+ #include "typechecker.h"
6
+ #include "../vm/vm.h"
7
+
8
+ struct ClassTypeChecker {
9
+ ClassTypeChecker * enclosing ;
10
+ Token name ;
11
+ BehaviorTypeInfo * type ;
12
+ bool isAnonymous ;
13
+ };
14
+
15
+ struct FunctionTypeChecker {
16
+ FunctionTypeChecker * enclosing ;
17
+ Token name ;
18
+ SymbolTable * symtab ;
19
+ CallableTypeInfo * type ;
20
+ bool isAsync ;
21
+ };
22
+
23
+ static void typeError (TypeChecker * typeChecker , const char * format , ...) {
24
+ va_list args ;
25
+ va_start (args , format );
26
+ fprintf (stderr , "[line %d] Type Error: " , typeChecker -> currentToken .line );
27
+ vfprintf (stderr , format , args );
28
+ va_end (args );
29
+ fputs ("\n" , stderr );
30
+ typeChecker -> hadError = true;
31
+ }
32
+
33
+ static void initClassTypeChecker (TypeChecker * typeChecker , ClassTypeChecker * klass , Token name , BehaviorTypeInfo * type , bool isAnonymous ) {
34
+ klass -> enclosing = typeChecker -> currentClass ;
35
+ klass -> name = name ;
36
+ klass -> type = type ;
37
+ klass -> isAnonymous = isAnonymous ;
38
+ typeChecker -> currentClass = klass ;
39
+ }
40
+
41
+ static void endClassTypeChecker (TypeChecker * typeChecker ) {
42
+ typeChecker -> currentClass = typeChecker -> currentClass -> enclosing ;
43
+ }
44
+
45
+ static void initFunctionTypeChecker (TypeChecker * typeChecker , FunctionTypeChecker * function , Token name , CallableTypeInfo * type , bool isAsync ) {
46
+ function -> enclosing = typeChecker -> currentFunction ;
47
+ function -> name = name ;
48
+ function -> type = type ;
49
+ function -> isAsync = isAsync ;
50
+ typeChecker -> currentFunction = function ;
51
+ }
52
+
53
+ static void endFunctionTypeChecker (TypeChecker * typeChecker ) {
54
+ typeChecker -> currentFunction = typeChecker -> currentFunction -> enclosing ;
55
+ }
56
+
57
+ void initTypeChecker (VM * vm , TypeChecker * typeChecker , bool debugTypetab ) {
58
+ typeChecker -> vm = vm ;
59
+ typeChecker -> currentNamespace = emptyString (vm );
60
+ typeChecker -> currentClass = NULL ;
61
+ typeChecker -> currentFunction = NULL ;
62
+ typeChecker -> scopeDepth = 0 ;
63
+ typeChecker -> debugTypetab = debugTypetab ;
64
+ typeChecker -> hadError = false;
65
+ }
66
+
67
+ static void typeCheckExpression (TypeChecker * typeChecker , Ast * ast ) {
68
+ // To be implemented.
69
+ }
70
+
71
+ static void typeCheckStatement (TypeChecker * typeChecker , Ast * ast ) {
72
+ // To be implemented.
73
+ }
74
+
75
+ static void typeCheckDeclaration (TypeChecker * typeChecker , Ast * ast ) {
76
+ // To be implemented.
77
+ }
78
+
79
+ void typeCheckAst (TypeChecker * typeChecker , Ast * ast ) {
80
+ for (int i = 0 ; i < ast -> children -> count ; i ++ ) {
81
+ typeCheckChild (typeChecker , ast , i );
82
+ }
83
+ }
84
+
85
+ void typeCheckChild (TypeChecker * typeChecker , Ast * ast , int index ) {
86
+ Ast * child = astGetChild (ast , index );
87
+ child -> symtab = ast -> symtab ;
88
+ typeChecker -> currentToken = child -> token ;
89
+
90
+ switch (child -> category ) {
91
+ case AST_CATEGORY_SCRIPT :
92
+ case AST_CATEGORY_OTHER :
93
+ typeCheckAst (typeChecker , child );
94
+ break ;
95
+ case AST_CATEGORY_EXPR :
96
+ typeCheckExpression (typeChecker , child );
97
+ break ;
98
+ case AST_CATEGORY_STMT :
99
+ typeCheckStatement (typeChecker , child );
100
+ break ;
101
+ case AST_CATEGORY_DECL :
102
+ typeCheckDeclaration (typeChecker , child );
103
+ break ;
104
+ default :
105
+ typeError (typeChecker , "Invalid AST category." );
106
+ }
107
+ }
108
+
109
+ void typeCheck (TypeChecker * typeChecker , Ast * ast ) {
110
+ FunctionTypeChecker functionTypeChecker ;
111
+ initFunctionTypeChecker (typeChecker , & functionTypeChecker , syntheticToken ("script" ), NULL , ast -> modifier .isAsync );
112
+ typeCheckAst (typeChecker , ast );
113
+
114
+ endFunctionTypeChecker (typeChecker );
115
+ if (typeChecker -> debugTypetab ) {
116
+ typeTableOutput (typeChecker -> vm -> typetab );
117
+ }
118
+ }
0 commit comments