Skip to content

Commit 39083ba

Browse files
committed
feat: added literal suffix support and still working on codegen
1 parent c0d15b1 commit 39083ba

File tree

19 files changed

+538
-165
lines changed

19 files changed

+538
-165
lines changed

crates/ast/src/format.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ impl fmt::Display for Identifier {
1616
impl fmt::Display for Literal {
1717
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1818
match &self.kind {
19-
LiteralKind::Integer(integer) => write!(f, "{}", integer),
19+
LiteralKind::Integer(integer, integer_type_opt) => {
20+
write!(f, "{}", integer)?;
21+
if let Some(integer_type) = integer_type_opt {
22+
write!(f, "{}", (**integer_type).to_string())?
23+
}
24+
write!(f, "")
25+
}
2026
LiteralKind::Bool(bool) => write!(f, "{}", bool),
2127
LiteralKind::String(string_type, prefix) => {
2228
if let Some(prefix) = prefix {
@@ -27,7 +33,13 @@ impl fmt::Display for Literal {
2733
}
2834
write!(f, "\"{}\"", string_type)
2935
}
30-
LiteralKind::Float(float) => write!(f, "{}", float),
36+
LiteralKind::Float(float, float_type_opt) => {
37+
write!(f, "{}", float)?;
38+
if let Some(float_type) = float_type_opt {
39+
write!(f, "{}", (**float_type).to_string())?
40+
}
41+
write!(f, "")
42+
}
3143
LiteralKind::Char(ch) => write!(f, "{}", ch),
3244
LiteralKind::Null => write!(f, "null"),
3345
}

crates/ast/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,10 @@ pub struct Literal {
232232

233233
#[derive(Debug, Clone, PartialEq)]
234234
pub enum LiteralKind {
235-
Integer(i64),
236-
Float(f64),
237-
Bool(bool),
235+
Integer(i64, Option<Box<TokenKind>>),
236+
Float(f64, Option<Box<TokenKind>>),
238237
String(String, Option<StringPrefix>),
238+
Bool(bool),
239239
Char(char),
240240
Null,
241241
}

crates/ast/src/token.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ pub const PRIMITIVE_TYPES: &[TokenKind] = &[
136136
TokenKind::Void,
137137
];
138138

139+
#[derive(Debug, Clone)]
140+
pub enum LiteralSuffix {
141+
PrimitiveType(TokenKind)
142+
}
143+
139144
impl fmt::Display for TokenKind {
140145
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141146
match self {

crates/codegen/src/builder/enums.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use typed_ast::TypedEnum;
2+
3+
use crate::builder::module::CodeGenBuilder;
4+
5+
impl<'a> CodeGenBuilder<'a> {
6+
pub(crate) fn build_enum_def(&self, typed_enum: &TypedEnum) {
7+
todo!()
8+
}
9+
}

crates/codegen/src/builder/exprs.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use crate::builder::module::CodeGenBuilder;
2+
use ast::{Literal, LiteralKind, token::TokenKind};
3+
use inkwell::{AddressSpace, types::BasicTypeEnum, values::AnyValueEnum};
4+
use resolver::scope::LocalScopeRef;
5+
use typed_ast::{TypedExpression, TypedExpressionKind, TypedLiteral, types::ConcreteType};
6+
7+
#[derive(Debug, Clone)]
8+
pub struct CodeGenExprValue<'a> {
9+
concrete_type: ConcreteType,
10+
value: AnyValueEnum<'a>,
11+
}
12+
13+
impl<'a> CodeGenExprValue<'a> {
14+
pub fn lvalue(&self) -> AnyValueEnum<'a> {
15+
self.value
16+
}
17+
18+
pub fn rvalue(&self) -> AnyValueEnum<'a> {
19+
match &self.concrete_type {
20+
ConcreteType::Symbol(_) => todo!(),
21+
ConcreteType::Pointer(concrete_type) => {
22+
todo!()
23+
}
24+
ConcreteType::Const(_) => self.value,
25+
ConcreteType::Array(_) => self.value,
26+
ConcreteType::BasicType(_) => self.value,
27+
ConcreteType::UnnamedStruct(_) => self.value,
28+
}
29+
}
30+
}
31+
32+
impl<'a> CodeGenBuilder<'a> {
33+
pub(crate) fn build_expr(
34+
&self,
35+
local_scope_opt: Option<LocalScopeRef>,
36+
typed_expr: &TypedExpression,
37+
) -> AnyValueEnum<'a> {
38+
match &typed_expr.kind {
39+
TypedExpressionKind::Symbol(_) => todo!(),
40+
TypedExpressionKind::Literal(typed_literal) => self.build_literal(typed_literal),
41+
TypedExpressionKind::Prefix(typed_prefix_expression) => todo!(),
42+
TypedExpressionKind::Infix(typed_infix_expression) => todo!(),
43+
TypedExpressionKind::Unary(typed_unary_expression) => todo!(),
44+
TypedExpressionKind::Assignment(typed_assignment) => todo!(),
45+
TypedExpressionKind::Cast(typed_cast) => todo!(),
46+
TypedExpressionKind::Array(typed_array) => todo!(),
47+
TypedExpressionKind::ArrayIndex(typed_array_index) => todo!(),
48+
TypedExpressionKind::AddressOf(typed_address_of) => todo!(),
49+
TypedExpressionKind::Dereference(typed_dereference) => todo!(),
50+
TypedExpressionKind::StructInit(typed_struct_init) => todo!(),
51+
TypedExpressionKind::FuncCall(typed_func_call) => todo!(),
52+
TypedExpressionKind::FieldAccess(typed_field_access) => todo!(),
53+
TypedExpressionKind::MethodCall(typed_method_call) => todo!(),
54+
TypedExpressionKind::UnnamedStructValue(typed_unnamed_struct_value) => todo!(),
55+
}
56+
}
57+
58+
fn build_literal(&self, literal: &TypedLiteral) -> AnyValueEnum<'a> {
59+
let basic_type_enum: BasicTypeEnum<'a> = self.build_basic_concrete_type(literal.ty.clone()).try_into().unwrap();
60+
61+
match &literal.kind {
62+
LiteralKind::Bool(value) => {
63+
AnyValueEnum::IntValue(self.llvmctx.bool_type().const_int(*value as u64, false))
64+
}
65+
LiteralKind::Integer(value, _) => AnyValueEnum::IntValue(
66+
basic_type_enum
67+
.into_int_type()
68+
.const_int((*value).try_into().unwrap(), literal.ty.is_signed()),
69+
),
70+
LiteralKind::Float(value, _) => {
71+
AnyValueEnum::FloatValue(basic_type_enum.into_float_type().const_float(*value))
72+
}
73+
LiteralKind::Char(value) => AnyValueEnum::IntValue(self.llvmctx.i8_type().const_int(*value as u64, false)),
74+
LiteralKind::Null => {
75+
AnyValueEnum::PointerValue(self.llvmctx.ptr_type(AddressSpace::default()).const_null())
76+
}
77+
LiteralKind::String(_, string_prefix) => todo!(),
78+
}
79+
}
80+
}

crates/codegen/src/builder/funcs.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,23 @@ use inkwell::{
1111
types::{AsTypeRef, BasicMetadataTypeEnum, BasicTypeEnum, FunctionType, StructType},
1212
values::FunctionValue,
1313
};
14-
use typed_ast::{TypedFuncParamKind, TypedFuncParams, types::ConcreteType};
14+
use typed_ast::{TypedFuncDef, TypedFuncParamKind, TypedFuncParams, types::ConcreteType};
1515

1616
impl<'a> CodeGenBuilder<'a> {
17+
pub(crate) fn build_func_def(&self, func_def: &TypedFuncDef) {
18+
let irreg = self.irreg.borrow();
19+
let local_ir_value = irreg.get(&func_def.symbol_id).unwrap();
20+
21+
let fn_value = local_ir_value.as_func().unwrap();
22+
23+
let entry_block = self.llvmctx.append_basic_block(*fn_value, "entry");
24+
self.llvmbuilder.position_at_end(entry_block);
25+
26+
self.build_block_statement(&func_def.body);
27+
28+
drop(irreg);
29+
}
30+
1731
pub(crate) fn build_func_decl(
1832
&self,
1933
func_name: String,

crates/codegen/src/builder/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
mod enums;
12
mod funcs;
23
pub mod module;
34
mod stmts;
45
mod types;
6+
mod variables;
7+
mod exprs;

crates/codegen/src/builder/stmts.rs

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
use super::module::{CodeGenBuilder, LocalIRValue};
2-
use ast::AccessSpecifier;
3-
use inkwell::{
4-
module::Linkage,
5-
types::{BasicTypeEnum, StructType},
6-
values::GlobalValue,
7-
};
8-
use typed_ast::{SymbolID, TypedExpression, TypedFuncDef, TypedGlobalVariable, TypedStatement, TypedStruct};
2+
use inkwell::types::{BasicTypeEnum, StructType};
3+
use typed_ast::{SymbolID, TypedBlockStatement, TypedStatement, TypedStruct};
94

105
impl<'a> CodeGenBuilder<'a> {
116
pub(crate) fn build_toplevel_statements(&self, stmts: &Vec<TypedStatement>) {
@@ -15,7 +10,7 @@ impl<'a> CodeGenBuilder<'a> {
1510
match stmt {
1611
TypedStatement::FuncDef(typed_func_def) => self.build_func_def(typed_func_def),
1712
TypedStatement::Struct(typed_struct) => self.build_struct_def(typed_struct),
18-
TypedStatement::Enum(typed_enum) => todo!(),
13+
TypedStatement::Enum(typed_enum) => self.build_enum_def(typed_enum),
1914
TypedStatement::Interface(typed_interface) => todo!(),
2015
// already handled in build_forward_decls
2116
TypedStatement::GlobalVariable(_) => continue,
@@ -104,53 +99,42 @@ impl<'a> CodeGenBuilder<'a> {
10499
self.llvmctx.opaque_struct_type(name)
105100
}
106101

107-
fn build_global_variable_linkage(&self, vis: AccessSpecifier) -> Linkage {
108-
match vis {
109-
AccessSpecifier::PublicExtern => Linkage::Common,
110-
AccessSpecifier::Extern => Linkage::Common,
111-
AccessSpecifier::Public => Linkage::External,
112-
AccessSpecifier::Internal => Linkage::Private,
113-
AccessSpecifier::Inline => unreachable!(),
114-
AccessSpecifier::PublicInline => unreachable!(),
115-
}
116-
}
117-
118-
fn build_global_var_decl(&self, global_var: &TypedGlobalVariable) -> GlobalValue<'a> {
119-
let linkage = self.build_global_variable_linkage(global_var.vis.clone());
102+
pub(crate) fn build_block_statement(&self, block_stmt: &TypedBlockStatement) {
103+
let local_scope_opt = Some(
104+
self.resolver
105+
.get_scope_ref(self.module_id, block_stmt.scope_id)
106+
.unwrap(),
107+
);
120108

121-
let mut global_var_type = {
122-
if let Some(concrete_type) = &global_var.ty {
123-
Some(self.build_concrete_type(None, concrete_type.clone()))
124-
} else {
125-
None
109+
for stmt in &block_stmt.exprs {
110+
match stmt {
111+
TypedStatement::Variable(typed_variable) => {
112+
self.build_local_variable(local_scope_opt.clone(), typed_variable)
113+
}
114+
TypedStatement::If(typed_if) => todo!(),
115+
TypedStatement::Return(typed_return) => todo!(),
116+
TypedStatement::Break(typed_break) => todo!(),
117+
TypedStatement::Continue(typed_continue) => todo!(),
118+
TypedStatement::For(typed_for) => todo!(),
119+
TypedStatement::Foreach(typed_foreach) => todo!(),
120+
TypedStatement::Switch(typed_switch) => todo!(),
121+
TypedStatement::Struct(typed_struct) => todo!(),
122+
TypedStatement::Enum(typed_enum) => todo!(),
123+
TypedStatement::Expression(typed_expr) => {
124+
self.build_expr(local_scope_opt.clone(), typed_expr);
125+
}
126+
TypedStatement::BlockStatement(typed_block_statement) => {
127+
self.build_block_statement(typed_block_statement);
128+
}
129+
TypedStatement::Interface(typed_interface) => todo!(),
130+
// Skipped statements
131+
TypedStatement::Typedef(_) => continue,
132+
// Invalid statements
133+
TypedStatement::FuncDef(_) => unreachable!(),
134+
TypedStatement::FuncDecl(_) => unreachable!(),
135+
TypedStatement::Import(_) => unreachable!(),
136+
TypedStatement::GlobalVariable(_) => unreachable!(),
126137
}
127-
};
128-
129-
if global_var_type.is_none() {
130-
let typed_expr: TypedExpression = global_var.expr.clone().unwrap();
131-
global_var_type = Some(self.build_concrete_type(None, typed_expr.concrete_type.unwrap()));
132138
}
133-
134-
let global_var_type: BasicTypeEnum<'a> = global_var_type.unwrap().try_into().unwrap();
135-
136-
let llvmmodule = self.llvmmodule.borrow();
137-
let global_var_value = llvmmodule.add_global(global_var_type, None, &global_var.name);
138-
global_var_value.set_linkage(linkage);
139-
drop(llvmmodule);
140-
global_var_value
141-
}
142-
143-
fn build_func_def(&self, func_def: &TypedFuncDef) {
144-
let irreg = self.irreg.borrow();
145-
let local_ir_value = irreg.get(&func_def.symbol_id).unwrap();
146-
147-
let fn_value = local_ir_value.as_func().unwrap();
148-
149-
let entry_block = self.llvmctx.append_basic_block(*fn_value, "entry");
150-
self.llvmbuilder.position_at_end(entry_block);
151-
152-
// TODO build body block
153-
154-
drop(irreg);
155139
}
156140
}

crates/codegen/src/builder/types.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ use inkwell::{
44
AddressSpace,
55
types::{AnyTypeEnum, BasicType, BasicTypeEnum, PointerType},
66
};
7-
use resolver::scope::SymbolEntry;
7+
use resolver::scope::{LocalScopeRef, SymbolEntry};
88
use typed_ast::{
9-
ScopeID, SymbolID,
9+
SymbolID,
1010
types::{BasicConcreteType, ConcreteType, TypedArrayCapacity},
1111
};
1212

1313
impl<'a> CodeGenBuilder<'a> {
1414
pub(crate) fn build_concrete_type_from_symbol_id(
1515
&self,
16-
local_scope_opt: Option<ScopeID>,
16+
local_scope_opt: Option<LocalScopeRef>,
1717
symbol_id: SymbolID,
1818
) -> AnyTypeEnum<'a> {
1919
if let Some(local_scope) = local_scope_opt {
@@ -52,7 +52,7 @@ impl<'a> CodeGenBuilder<'a> {
5252

5353
pub(crate) fn build_concrete_type(
5454
&self,
55-
local_scope_opt: Option<ScopeID>,
55+
local_scope_opt: Option<LocalScopeRef>,
5656
concrete_type: ConcreteType,
5757
) -> AnyTypeEnum<'a> {
5858
match concrete_type {
@@ -80,7 +80,7 @@ impl<'a> CodeGenBuilder<'a> {
8080
.fields
8181
.iter()
8282
.map(|field| {
83-
self.build_concrete_type(local_scope_opt, *field.field_type.clone())
83+
self.build_concrete_type(local_scope_opt.clone(), *field.field_type.clone())
8484
.try_into()
8585
.unwrap()
8686
})
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use crate::builder::module::CodeGenBuilder;
2+
use ast::AccessSpecifier;
3+
use inkwell::{module::Linkage, types::BasicTypeEnum, values::{BasicValueEnum, GlobalValue}};
4+
use resolver::scope::LocalScopeRef;
5+
use typed_ast::{TypedExpression, TypedGlobalVariable, TypedVariable};
6+
7+
impl<'a> CodeGenBuilder<'a> {
8+
pub(crate) fn build_global_var_decl(&self, global_var: &TypedGlobalVariable) -> GlobalValue<'a> {
9+
let linkage = self.build_global_variable_linkage(global_var.vis.clone());
10+
11+
let mut global_var_type = {
12+
if let Some(concrete_type) = &global_var.ty {
13+
Some(self.build_concrete_type(None, concrete_type.clone()))
14+
} else {
15+
None
16+
}
17+
};
18+
19+
if global_var_type.is_none() {
20+
let typed_expr: TypedExpression = global_var.expr.clone().unwrap();
21+
global_var_type = Some(self.build_concrete_type(None, typed_expr.concrete_type.unwrap()));
22+
}
23+
24+
let global_var_type: BasicTypeEnum<'a> = global_var_type.unwrap().try_into().unwrap();
25+
26+
let llvmmodule = self.llvmmodule.borrow();
27+
let global_var_value = llvmmodule.add_global(global_var_type, None, &global_var.name);
28+
global_var_value.set_linkage(linkage);
29+
drop(llvmmodule);
30+
global_var_value
31+
}
32+
33+
fn build_global_variable_linkage(&self, vis: AccessSpecifier) -> Linkage {
34+
match vis {
35+
AccessSpecifier::PublicExtern => Linkage::Common,
36+
AccessSpecifier::Extern => Linkage::Common,
37+
AccessSpecifier::Public => Linkage::External,
38+
AccessSpecifier::Internal => Linkage::Private,
39+
AccessSpecifier::Inline => unreachable!(),
40+
AccessSpecifier::PublicInline => unreachable!(),
41+
}
42+
}
43+
44+
pub(crate) fn build_local_variable(&self, local_scope_opt: Option<LocalScopeRef>, variable: &TypedVariable) {
45+
let var_type: BasicTypeEnum<'a> = {
46+
if let Some(concrete_type) = &variable.ty {
47+
self.build_concrete_type(local_scope_opt.clone(), concrete_type.clone())
48+
.try_into()
49+
.unwrap()
50+
} else {
51+
self.build_concrete_type(
52+
local_scope_opt.clone(),
53+
variable.rhs.clone().unwrap().concrete_type.unwrap(),
54+
)
55+
.try_into()
56+
.unwrap()
57+
}
58+
};
59+
60+
let alloca = self.llvmbuilder.build_alloca(var_type, &variable.name).unwrap();
61+
if let Some(typed_expr) = &variable.rhs {
62+
let rvalue: BasicValueEnum<'a> = self.build_expr(local_scope_opt, typed_expr).try_into().unwrap();
63+
// TODO
64+
// let rvalue = self.implicit_cast();
65+
self.llvmbuilder.build_store(alloca, rvalue).unwrap();
66+
}
67+
}
68+
}

0 commit comments

Comments
 (0)