11const std = @import ("std" );
22const parser = @import ("parser.zig" );
33const llvm_bindings = @import ("llvm.zig" );
4- const statements = @import ("statements.zig" );
54
65const Lexer = parser .Lexer ;
76const Token = parser .Token ;
87const llvm = llvm_bindings .c ;
98
10- pub const Local = struct {
9+ pub const DiagnosticLevel = enum {
10+ note ,
11+ warning ,
12+ err ,
13+ fatal ,
14+ };
15+
16+ pub const ErrorCode = enum {
17+ SyntaxError ,
18+ TypeError ,
19+ NameError ,
20+ LinkerError ,
21+ InternalError ,
22+ };
23+
24+ pub const DataType = enum {
25+ int ,
26+ float ,
27+ str ,
28+ bool
29+ };
30+
31+ pub const Variable = struct {
1132 llvm_value : llvm.LLVMValueRef ,
1233 is_const : bool ,
34+ data_type : DataType ,
1335};
1436
1537pub const Compiler = struct {
1638 allocator : std.mem.Allocator ,
17- locals : std .StringHashMap (Local ),
39+ locals : std .StringHashMap (Variable ),
1840
1941 context : llvm.LLVMContextRef ,
2042 module : llvm.LLVMModuleRef ,
@@ -80,7 +102,7 @@ pub const Compiler = struct {
80102
81103 return .{
82104 .allocator = allocator ,
83- .locals = std .StringHashMap (Local ).init (allocator ),
105+ .locals = std .StringHashMap (Variable ).init (allocator ),
84106 .context = context ,
85107 .module = module ,
86108 .builder = builder ,
@@ -92,36 +114,49 @@ pub const Compiler = struct {
92114
93115 pub fn deinit (self : * Compiler ) void {
94116 // Free all symbol table keys
95- var iterator = self .locals .keyIterator ();
96- while (iterator .next ()) | key_ptr | self .allocator .free (key_ptr .* );
97- self .locals .deinit ();
117+ var iter = self .locals .keyIterator ();
118+ while (iter .next ()) | key_ptr | self .allocator .free (key_ptr .* );
98119
120+ self .locals .deinit ();
99121 llvm .LLVMDisposeBuilder (self .builder );
100122 llvm .LLVMDisposeModule (self .module );
101123 llvm .LLVMContextDispose (self .context );
102124 }
103125
104- // Finalize main function with return 0
105126 pub fn finish (self : * Compiler ) void {
106127 const i32_type = llvm .LLVMInt32TypeInContext (self .context );
107128 const zero = llvm .LLVMConstInt (i32_type , 0 , 0 );
108129 _ = llvm .LLVMBuildRet (self .builder , zero );
109130 }
110131
111- pub const compile = statements .compile ;
112- pub const compileStatement = statements .compileStatement ;
113- pub const compileSay = statements .compileSay ;
132+ pub fn printString (self : * Compiler , str_value : llvm.LLVMValueRef ) ! void {
133+ const fmt_str = llvm .LLVMBuildGlobalStringPtr (self .builder , "%s" , "fmt.str" );
134+ var args = [_ ]llvm.LLVMValueRef { fmt_str , str_value };
135+ _ = llvm .LLVMBuildCall2 (
136+ self .builder ,
137+ self .printf_type ,
138+ self .printf_fn ,
139+ & args ,
140+ args .len ,
141+ ""
142+ );
143+ }
114144
115- // Print an integer value to stdout
116145 pub fn printInt (self : * Compiler , value : llvm.LLVMValueRef ) ! void {
117- // Create format string: "%lld\n"
118- const fmt_str = llvm .LLVMBuildGlobalStringPtr (
146+ const fmt_str = llvm .LLVMBuildGlobalStringPtr (self .builder , "%lld" , "fmt.int" );
147+ var args = [_ ]llvm.LLVMValueRef { fmt_str , value };
148+ _ = llvm .LLVMBuildCall2 (
119149 self .builder ,
120- "%lld\n " ,
121- "fmt.int"
150+ self .printf_type ,
151+ self .printf_fn ,
152+ & args ,
153+ args .len ,
154+ ""
122155 );
156+ }
123157
124- // Call printf(fmt_str, value)
158+ pub fn printFloat (self : * Compiler , value : llvm.LLVMValueRef ) ! void {
159+ const fmt_str = llvm .LLVMBuildGlobalStringPtr (self .builder , "%f" , "fmt.float" );
125160 var args = [_ ]llvm.LLVMValueRef { fmt_str , value };
126161 _ = llvm .LLVMBuildCall2 (
127162 self .builder ,
@@ -133,27 +168,79 @@ pub const Compiler = struct {
133168 );
134169 }
135170
136- // Get the i64 type for this context
171+ pub fn printNewLine (self : * Compiler ) ! void {
172+ const fmt_str = llvm .LLVMBuildGlobalStringPtr (self .builder , "\n " , "fmt.nl" );
173+ var args = [_ ]llvm.LLVMValueRef { fmt_str };
174+ _ = llvm .LLVMBuildCall2 (self .builder , self .printf_type , self .printf_fn , & args , args .len , "" );
175+ }
176+
177+ pub fn printSpace (self : * Compiler ) ! void {
178+ const fmt_str = llvm .LLVMBuildGlobalStringPtr (self .builder , " " , "fmt.sp" );
179+ var args = [_ ]llvm.LLVMValueRef { fmt_str };
180+ _ = llvm .LLVMBuildCall2 (self .builder , self .printf_type , self .printf_fn , & args , args .len , "" );
181+ }
182+
183+ pub fn report (
184+ self : * Compiler ,
185+ level : DiagnosticLevel ,
186+ code : ErrorCode ,
187+ token : parser.Token ,
188+ message : []const u8 ,
189+ extra : ? []const u8 ,
190+ ) anyerror ! void {
191+ _ = self ;
192+
193+ const color = switch (level ) {
194+ .err , .fatal = > "\x1b [31m" ,
195+ .warning = > "\x1b [33m" ,
196+ .note = > "\x1b [36m" ,
197+ };
198+ const reset = "\x1b [0m" ;
199+
200+ std .debug .print ("{s}[{s}]{s} at line {d}, col {d}: {s}\n " , .{
201+ color ,
202+ @tagName (code ),
203+ reset ,
204+ token .line ,
205+ token .col ,
206+ message ,
207+ });
208+
209+ if (extra ) | e | std .debug .print (" └─ {s}Hint: {s}{s}\n " , .{ "\x1b [32m" , e , reset });
210+
211+ if (level == .err or level == .fatal ) {
212+ if (level == .fatal ) std .process .exit (1 );
213+ return error .CompileError ;
214+ }
215+
216+ return ;
217+ }
218+
219+ pub fn getLLVMType (self : * const Compiler , dtype : DataType ) llvm.LLVMTypeRef {
220+ return switch (dtype ) {
221+ .int = > llvm .LLVMInt64TypeInContext (self .context ),
222+ .float = > llvm .LLVMDoubleTypeInContext (self .context ),
223+ .bool = > llvm .LLVMInt1TypeInContext (self .context ),
224+ .str = > llvm .LLVMPointerType (llvm .LLVMInt8TypeInContext (self .context ), 0 ),
225+ };
226+ }
227+
137228 pub inline fn getI64Type (self : * const Compiler ) llvm.LLVMTypeRef {
138229 return llvm .LLVMInt64TypeInContext (self .context );
139230 }
140231
141- // Get the i32 type for this context
142232 pub inline fn getI32Type (self : * const Compiler ) llvm.LLVMTypeRef {
143233 return llvm .LLVMInt32TypeInContext (self .context );
144234 }
145235
146- // Get the i8 type for this context
147236 pub inline fn getI8Type (self : * const Compiler ) llvm.LLVMTypeRef {
148237 return llvm .LLVMInt8TypeInContext (self .context );
149238 }
150239
151- // Look up a variable by name
152- pub fn lookupVariable (self : * const Compiler , name : []const u8 ) ? Local {
240+ pub fn lookupVariable (self : * const Compiler , name : []const u8 ) ? Variable {
153241 return self .locals .get (name );
154242 }
155243
156- // Check if a variable exists
157244 pub fn hasVariable (self : * const Compiler , name : []const u8 ) bool {
158245 return self .locals .contains (name );
159246 }
0 commit comments