Skip to content

Commit 44677dd

Browse files
committed
feat: basic forward declaration works now
1 parent 93af053 commit 44677dd

File tree

19 files changed

+255
-80
lines changed

19 files changed

+255
-80
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2024"
55

66
[dependencies]
77
codegen = { path = "../codegen", version = "*" }
8+
static_analyzer = { path = "../static_analyzer", version = "*" }
89
project_layout = { path = "../project_layout", version = "*" }
910
parser = { path = "../parser", version = "*" }
1011
serde = { version = "1.0.219", features = ["derive"] }

crates/cli/src/commands.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
use crate::CompilerOptions;
22
use ast::token::TokenKind;
33
use codegen::{context::context::CodeGenContext, options::OutputKind};
4-
use diagcentral::display_single_cusotm_diag;
4+
use diagcentral::{display_single_custom_diag, reporter::DiagReporter};
55
use lexer::Lexer;
66
use parser::Parser;
77
use resolver::{Resolver, Visiting, generate_module_id, moduleloader::ModuleLoaderOptions};
8-
use std::{cell::RefCell, env, mem, process::exit, rc::Rc};
9-
use typed_ast::TypedProgramTree;
10-
11-
fn get_program_trees(options: &CompilerOptions, file_path: String) -> Vec<(String, Rc<RefCell<TypedProgramTree>>)> {
8+
use static_analyzer::context::AnalysisContext;
9+
use std::{cell::RefCell, env, process::exit, rc::Rc};
10+
use typed_ast::{ModuleID, TypedProgramTree};
11+
12+
fn get_program_trees(
13+
options: &CompilerOptions,
14+
file_path: String,
15+
) -> (Vec<(String, ModuleID, Rc<RefCell<TypedProgramTree>>)>, Rc<Resolver>) {
1216
let file_content = utils::fs::read_file(file_path.clone()).0;
1317
let mut lexer = Lexer::new(file_content, file_path.clone());
1418
let mut parser = Parser::new(lexer.tokenize(), file_path.clone());
@@ -37,24 +41,36 @@ fn get_program_trees(options: &CompilerOptions, file_path: String) -> Vec<(Strin
3741
exit(1);
3842
}
3943

40-
let final_program_trees: Vec<(String, Rc<RefCell<TypedProgramTree>>)>;
44+
let final_program_trees: Vec<(String, ModuleID, Rc<RefCell<TypedProgramTree>>)>;
4145
let program_trees = resolver.program_trees.lock().unwrap();
46+
47+
{
48+
for (_, _, typed_program_tree) in program_trees.iter() {
49+
let mut typed_program_tree_borrowed = typed_program_tree.borrow_mut();
50+
let mut analyzer = AnalysisContext::new(&resolver, module_id, &mut typed_program_tree_borrowed);
51+
analyzer.analyze();
52+
if analyzer.reporter.has_errors() {
53+
DiagReporter::display(&analyzer.reporter);
54+
exit(1);
55+
}
56+
}
57+
}
4258
final_program_trees = program_trees.clone();
4359
drop(program_trees);
4460

45-
final_program_trees
61+
(final_program_trees, Rc::new(resolver))
4662
}
4763

4864
pub(crate) fn command_run(options: CompilerOptions, file_path: Option<String>) {
49-
let context = CodeGenContext::new(options.to_compiler_options(), OutputKind::None);
65+
let (program_trees, resolver_rc) = get_program_trees(&options, file_path.unwrap());
66+
67+
let context = CodeGenContext::new(options.to_compiler_options(), OutputKind::None, resolver_rc);
68+
context.compile_modules(program_trees);
5069

5170
let mut temp = env::temp_dir();
5271
temp.push("path");
5372
let temp_file_path = temp.to_str().unwrap().to_string();
5473

55-
let program_trees = get_program_trees(&options, file_path.unwrap());
56-
context.compile_modules(program_trees);
57-
5874
context.emit_exec(temp_file_path.clone());
5975
if temp.exists() {
6076
std::fs::remove_file(temp_file_path).unwrap();
@@ -63,12 +79,16 @@ pub(crate) fn command_run(options: CompilerOptions, file_path: Option<String>) {
6379

6480
pub(crate) fn command_emit_llvm(options: CompilerOptions, file_path: Option<String>, output_path: Option<String>) {
6581
let output_path = output_path.unwrap_or_else(|| {
66-
display_single_cusotm_diag!("Output directory must be specified to generate llvm-ir.".to_string());
82+
display_single_custom_diag!("Output directory must be specified to generate llvm-ir.".to_string());
6783
});
6884

69-
let context = CodeGenContext::new(options.to_compiler_options(), OutputKind::LlvmIr(output_path));
85+
let (program_trees, resolver_rc) = get_program_trees(&options, file_path.unwrap());
7086

71-
let program_trees = get_program_trees(&options, file_path.unwrap());
87+
let context = CodeGenContext::new(
88+
options.to_compiler_options(),
89+
OutputKind::LlvmIr(output_path),
90+
resolver_rc,
91+
);
7292
context.compile_modules(program_trees);
7393
}
7494

crates/cli/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clap::{Parser, ValueEnum};
22
use codegen::options::{BuildDir, CodeGenOptions, CodeModelOptions, RelocModeOptions};
33
use commands::*;
4-
use diagcentral::display_single_cusotm_diag;
4+
use diagcentral::display_single_custom_diag;
55
use serde::Deserialize;
66
use trigger::project_file_required;
77

@@ -260,7 +260,7 @@ fn command_new(project_name: String, lib: bool) {
260260
};
261261

262262
if let Err(err) = result {
263-
display_single_cusotm_diag!(err);
263+
display_single_custom_diag!(err);
264264
}
265265
}
266266

crates/cli/src/trigger.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use codegen::{
22
context::context::CodeGenContext,
33
options::{CodeGenOptions, OutputKind},
44
};
5-
use diagcentral::display_single_cusotm_diag;
5+
use diagcentral::display_single_custom_diag;
66

77
const PROJECT_FILE_PATH: &str = "Project.toml";
88

@@ -88,6 +88,6 @@ pub fn get_codegen_context(
8888

8989
pub(crate) fn project_file_required() {
9090
if !std::path::Path::new(PROJECT_FILE_PATH).exists() {
91-
display_single_cusotm_diag!(format!("'{}' not found in current directory.", PROJECT_FILE_PATH));
91+
display_single_custom_diag!(format!("'{}' not found in current directory.", PROJECT_FILE_PATH));
9292
}
9393
}

crates/codegen/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ edition = "2024"
66
[dependencies]
77
utils = { path = "../utils", version = "*" }
88
typed_ast = { path = "../typed_ast", version = "*" }
9+
resolver = { path = "../resolver", version = "*" }
910
ast = { path = "../ast", version = "*" }
1011
diagcentral = { path = "../diagcentral", version = "*" }
1112
inkwell = { version = "0.5.0", features = ["llvm18-0"] }

crates/codegen/src/builder/funcs.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ impl<'a> CodeGenBuilder<'a> {
8484
.iter()
8585
.map(|param| {
8686
let basic_type_enum: BasicTypeEnum<'a> = match param {
87-
TypedFuncParamKind::FuncParam(typed_func_param) => {
88-
self.build_conrete_type(typed_func_param.ty.clone()).try_into().unwrap()
89-
}
87+
TypedFuncParamKind::FuncParam(typed_func_param) => self
88+
.build_concrete_type(None, typed_func_param.ty.clone())
89+
.try_into()
90+
.unwrap(),
9091
TypedFuncParamKind::SelfModifier(self_modifier) => match self_modifier.kind {
9192
SelfModifierKind::Copied => BasicTypeEnum::StructType(method_struct_type.unwrap()),
9293
SelfModifierKind::Referenced => {
@@ -98,7 +99,7 @@ impl<'a> CodeGenBuilder<'a> {
9899
})
99100
.collect();
100101

101-
let return_type = self.build_conrete_type(return_type);
102+
let return_type = self.build_concrete_type(None, return_type);
102103

103104
let is_var_args = params.variadic.is_some();
104105
let fn_type = unsafe {

crates/codegen/src/builder/module.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
use crate::options::CodeGenOptions;
2-
use diagcentral::display_single_cusotm_diag;
2+
use diagcentral::display_single_custom_diag;
33
use inkwell::{
44
OptimizationLevel,
55
builder::Builder,
66
context::Context,
77
module::Module,
88
targets::{CodeModel, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple},
9-
values::{FunctionValue, GlobalValue, StructValue},
9+
types::StructType,
10+
values::{FunctionValue, GlobalValue},
1011
};
12+
use resolver::Resolver;
1113
use std::{cell::RefCell, collections::HashMap, path::Path, rc::Rc};
12-
use typed_ast::TypedProgramTree;
14+
use typed_ast::{ModuleID, TypedProgramTree};
1315
use utils::fs::ensure_output_dir;
1416

1517
pub struct CodeGenModule<'module> {
@@ -19,11 +21,13 @@ pub struct CodeGenModule<'module> {
1921
}
2022

2123
pub(crate) struct CodeGenBuilder<'a> {
24+
pub module_id: ModuleID,
2225
pub llvmmodule: Rc<RefCell<Module<'a>>>,
2326
pub llvmbuilder: Builder<'a>,
2427
pub llvmctx: &'a Context,
2528
pub llvmtm: TargetMachine,
2629
pub irreg: LocalIRValueRegistryRef<'a>,
30+
pub resolver: Rc<Resolver>,
2731
}
2832

2933
impl<'module> CodeGenModule<'module> {
@@ -37,7 +41,12 @@ impl<'module> CodeGenModule<'module> {
3741
}
3842
}
3943

40-
pub fn codegen<'a>(&'a self, module_name: String) -> CodeGenModuleOutput<'a> {
44+
pub fn codegen<'a>(
45+
&'a self,
46+
resolver_rc: Rc<Resolver>,
47+
module_id: ModuleID,
48+
module_name: String,
49+
) -> CodeGenModuleOutput<'a> {
4150
let llvmmodule = self.ctx.create_module(&module_name);
4251
let builder = self.ctx.create_builder();
4352
let llvmtm = self.get_target_machine(
@@ -53,11 +62,13 @@ impl<'module> CodeGenModule<'module> {
5362
let llvmmodule = Rc::new(RefCell::new(llvmmodule));
5463

5564
let codegen_builder = CodeGenBuilder {
65+
module_id,
5666
llvmmodule: llvmmodule.clone(),
5767
llvmbuilder: builder,
5868
llvmctx: &self.ctx,
5969
llvmtm,
6070
irreg,
71+
resolver: resolver_rc,
6172
};
6273

6374
let program_tree_borrowed = self.program_tree.borrow();
@@ -98,7 +109,7 @@ impl<'module> CodeGenModule<'module> {
98109
) {
99110
Some(target_machine) => target_machine,
100111
None => {
101-
display_single_cusotm_diag!(
112+
display_single_custom_diag!(
102113
"Failed to create LLVM Target Machine with given target_triple, cpu, features.".to_string()
103114
);
104115
}
@@ -145,5 +156,28 @@ pub type LocalIRValueRegistry<'a> = HashMap<LocalIRValueID, LocalIRValue<'a>>;
145156
pub enum LocalIRValue<'a> {
146157
Func(FunctionValue<'a>),
147158
GlobalValue(GlobalValue<'a>),
148-
Struct(StructValue<'a>),
159+
Struct(StructType<'a>),
160+
}
161+
162+
impl<'a> LocalIRValue<'a> {
163+
pub fn as_func(&self) -> Option<&FunctionValue<'a>> {
164+
match self {
165+
LocalIRValue::Func(func) => Some(func),
166+
_ => None,
167+
}
168+
}
169+
170+
pub fn as_global_value(&self) -> Option<&GlobalValue<'a>> {
171+
match self {
172+
LocalIRValue::GlobalValue(global_value) => Some(global_value),
173+
_ => None,
174+
}
175+
}
176+
177+
pub fn as_struct(&self) -> Option<&StructType<'a>> {
178+
match self {
179+
LocalIRValue::Struct(struct_type) => Some(struct_type),
180+
_ => None,
181+
}
182+
}
149183
}

0 commit comments

Comments
 (0)