Skip to content

Commit ef4ffdc

Browse files
committed
Started working on support for C global variable declarations
1 parent 6202bf6 commit ef4ffdc

File tree

7 files changed

+157
-101
lines changed

7 files changed

+157
-101
lines changed

Diff for: src/c/parser/mod.rs

+46-13
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::{
2121
diagnostics::{Diagnostics, WarningDiagnostic},
2222
source_files::source::Source,
2323
};
24-
use derive_more::IsVariant;
24+
use derive_more::{From, IsVariant};
2525
use itertools::Itertools;
2626
use std::collections::HashMap;
2727

@@ -202,17 +202,50 @@ impl From<TypeSpecifierQualifier> for DeclarationSpecifier {
202202
}
203203
}
204204

205-
#[derive(Clone, Debug)]
206-
pub enum DeclarationSpecifierKind {
205+
#[derive(Copy, Clone, Debug, IsVariant)]
206+
pub enum StorageClassSpecifier {
207207
Auto,
208208
Constexpr,
209209
Extern,
210210
Register,
211211
Static,
212212
ThreadLocal,
213213
Typedef,
214+
}
215+
216+
impl StorageClassSpecifier {
217+
pub fn as_str(&self) -> &'static str {
218+
match self {
219+
StorageClassSpecifier::Auto => "auto",
220+
StorageClassSpecifier::Constexpr => "constexpr",
221+
StorageClassSpecifier::Extern => "extern",
222+
StorageClassSpecifier::Register => "register",
223+
StorageClassSpecifier::Static => "static",
224+
StorageClassSpecifier::ThreadLocal => "thread_local",
225+
StorageClassSpecifier::Typedef => "typedef",
226+
}
227+
}
228+
}
229+
230+
#[derive(Copy, Clone, Debug, IsVariant)]
231+
pub enum FunctionSpecifier {
214232
Inline,
215233
Noreturn,
234+
}
235+
236+
impl FunctionSpecifier {
237+
pub fn as_str(&self) -> &'static str {
238+
match self {
239+
FunctionSpecifier::Inline => "inline",
240+
FunctionSpecifier::Noreturn => "_Noreturn",
241+
}
242+
}
243+
}
244+
245+
#[derive(Clone, Debug, From)]
246+
pub enum DeclarationSpecifierKind {
247+
StorageClassSpecifier(StorageClassSpecifier),
248+
FunctionSpecifier(FunctionSpecifier),
216249
TypeSpecifierQualifier(TypeSpecifierQualifier),
217250
}
218251

@@ -565,16 +598,16 @@ impl<'a> Parser<'a> {
565598
let CToken { kind, source } = self.input.peek();
566599
let source = *source;
567600

568-
let result = match kind {
569-
CTokenKind::AutoKeyword => DeclarationSpecifierKind::Auto,
570-
CTokenKind::ConstexprKeyword => DeclarationSpecifierKind::Constexpr,
571-
CTokenKind::ExternKeyword => DeclarationSpecifierKind::Extern,
572-
CTokenKind::RegisterKeyword => DeclarationSpecifierKind::Register,
573-
CTokenKind::StaticKeyword => DeclarationSpecifierKind::Static,
574-
CTokenKind::ThreadLocalKeyword => DeclarationSpecifierKind::ThreadLocal,
575-
CTokenKind::TypedefKeyword => DeclarationSpecifierKind::Typedef,
576-
CTokenKind::InlineKeyword => DeclarationSpecifierKind::Inline,
577-
CTokenKind::NoreturnKeyword => DeclarationSpecifierKind::Noreturn,
601+
let result: DeclarationSpecifierKind = match kind {
602+
CTokenKind::AutoKeyword => StorageClassSpecifier::Auto.into(),
603+
CTokenKind::ConstexprKeyword => StorageClassSpecifier::Constexpr.into(),
604+
CTokenKind::ExternKeyword => StorageClassSpecifier::Extern.into(),
605+
CTokenKind::RegisterKeyword => StorageClassSpecifier::Register.into(),
606+
CTokenKind::StaticKeyword => StorageClassSpecifier::Static.into(),
607+
CTokenKind::ThreadLocalKeyword => StorageClassSpecifier::ThreadLocal.into(),
608+
CTokenKind::TypedefKeyword => StorageClassSpecifier::Typedef.into(),
609+
CTokenKind::InlineKeyword => FunctionSpecifier::Inline.into(),
610+
CTokenKind::NoreturnKeyword => FunctionSpecifier::Noreturn.into(),
578611
_ => {
579612
return Ok(DeclarationSpecifierKind::TypeSpecifierQualifier(
580613
self.parse_type_specifier_qualifier()?,

Diff for: src/c/translation/expr/caster.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,18 @@ pub fn get_caster_type(
3434

3535
let base = builder.build()?;
3636

37-
if base.is_typedef {
38-
todo!("error message for typedef base in caster");
37+
if base.storage_class.is_some() {
38+
return Err(ParseError::message(
39+
"Storage class specifier cannot be used on cast",
40+
caster.source,
41+
));
42+
}
43+
44+
if base.function_specifier.is_some() {
45+
return Err(ParseError::message(
46+
"Storage class specifier cannot be used on cast",
47+
caster.source,
48+
));
3949
}
4050

4151
Ok(base.ast_type)

Diff for: src/c/translation/function.rs

+33-14
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
ast::{self, AstFile, Func, FuncHead, Param, Params, Privacy},
55
c::parser::{
66
error::ParseErrorKind, CTypedef, DeclarationSpecifiers, Declarator,
7-
ParameterDeclarationCore, ParameterTypeList, ParseError,
7+
ParameterDeclarationCore, ParameterTypeList, ParseError, StorageClassSpecifier,
88
},
99
diagnostics::Diagnostics,
1010
};
@@ -20,7 +20,7 @@ pub fn declare_function(
2020
diagnostics: &Diagnostics,
2121
) -> Result<(), ParseError> {
2222
let source = declarator.source;
23-
let (name, return_type, is_typedef) = get_name_and_type(
23+
let (name, return_type, storage_class, function_specifier) = get_name_and_type(
2424
ast_file,
2525
typedefs,
2626
declarator,
@@ -30,9 +30,13 @@ pub fn declare_function(
3030
)?;
3131
let mut required = vec![];
3232

33+
if function_specifier.is_some() {
34+
return Err(ParseErrorKind::Misc("Function specifiers are not supported yet").at(source));
35+
}
36+
3337
if has_parameters(parameter_type_list) {
3438
for param in parameter_type_list.parameter_declarations.iter() {
35-
let (name, ast_type, is_typedef) = match &param.core {
39+
let (name, ast_type, storage_class, function_specifier) = match &param.core {
3640
ParameterDeclarationCore::Declarator(declarator) => get_name_and_type(
3741
ast_file,
3842
typedefs,
@@ -45,26 +49,41 @@ pub fn declare_function(
4549
ParameterDeclarationCore::Nothing => todo!(),
4650
};
4751

48-
if is_typedef {
52+
if storage_class.is_some() {
53+
return Err(
54+
ParseErrorKind::Misc("Storage classes not support on typedef").at(param.source),
55+
);
56+
}
57+
58+
if function_specifier.is_some() {
4959
return Err(
50-
ParseErrorKind::Misc("Parameter type cannot be typedef").at(param.source)
60+
ParseErrorKind::Misc("Function specifiers cannot be used on typedef")
61+
.at(source),
5162
);
5263
}
5364

5465
required.push(Param { name, ast_type });
5566
}
5667
}
5768

58-
if is_typedef {
59-
let ast_type = ast::TypeKind::FuncPtr(ast::FuncPtr {
60-
parameters: required,
61-
return_type: Box::new(return_type),
62-
is_cstyle_variadic: parameter_type_list.is_variadic,
63-
})
64-
.at(declarator.source);
69+
match storage_class {
70+
Some(StorageClassSpecifier::Typedef) => {
71+
let ast_type = ast::TypeKind::FuncPtr(ast::FuncPtr {
72+
parameters: required,
73+
return_type: Box::new(return_type),
74+
is_cstyle_variadic: parameter_type_list.is_variadic,
75+
})
76+
.at(declarator.source);
6577

66-
typedefs.insert(name, CTypedef { ast_type });
67-
return Ok(());
78+
typedefs.insert(name, CTypedef { ast_type });
79+
return Ok(());
80+
}
81+
Some(_) => {
82+
return Err(
83+
ParseErrorKind::Misc("Unsupported storage class here").at(declarator.source)
84+
);
85+
}
86+
None => (),
6887
}
6988

7089
let head = FuncHead {

Diff for: src/c/translation/mod.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ pub use self::{expr::translate_expr, function::declare_function};
99
use crate::{
1010
asg::TypeParams,
1111
ast::{self, AstFile, Privacy},
12-
c::parser::{CTypedef, DeclarationSpecifiers, Declarator, ParseError},
13-
diagnostics::Diagnostics,
12+
c::parser::{CTypedef, DeclarationSpecifiers, Declarator, ParseError, StorageClassSpecifier},
13+
diagnostics::{Diagnostics, WarningDiagnostic},
1414
};
1515
use std::collections::HashMap;
1616

@@ -22,7 +22,7 @@ pub fn declare_named_declaration(
2222
typedefs: &mut HashMap<String, CTypedef>,
2323
diagnostics: &Diagnostics,
2424
) -> Result<(), ParseError> {
25-
let (name, ast_type, is_typedef) = get_name_and_type(
25+
let (name, ast_type, storage_class, function_specifier) = get_name_and_type(
2626
ast_file,
2727
typedefs,
2828
declarator,
@@ -31,7 +31,17 @@ pub fn declare_named_declaration(
3131
diagnostics,
3232
)?;
3333

34-
if is_typedef {
34+
if let Some(StorageClassSpecifier::Typedef) = storage_class {
35+
if let Some(function_specifier) = function_specifier {
36+
diagnostics.push(WarningDiagnostic::new(
37+
format!(
38+
"Function specifier '{}' does nothing on typedef",
39+
function_specifier.as_str()
40+
),
41+
declarator.source,
42+
));
43+
}
44+
3545
ast_file.type_aliases.push(ast::TypeAlias {
3646
name: name.clone(),
3747
params: TypeParams::default(),

Diff for: src/c/translation/types/composite.rs

+20-10
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,28 @@ pub fn make_composite(
5454
for member_declarator in member.member_declarators.iter() {
5555
match member_declarator {
5656
MemberDeclarator::Declarator(declarator) => {
57-
let (name, ast_type, is_typedef) = get_name_and_type(
58-
ast_file,
59-
typedefs,
60-
declarator,
61-
&DeclarationSpecifiers::from(&member.specifier_qualifiers),
62-
false,
63-
diagnostics,
64-
)?;
57+
let (name, ast_type, storage_class, function_specifier) =
58+
get_name_and_type(
59+
ast_file,
60+
typedefs,
61+
declarator,
62+
&DeclarationSpecifiers::from(
63+
&member.specifier_qualifiers,
64+
),
65+
false,
66+
diagnostics,
67+
)?;
6568

66-
if is_typedef {
69+
if storage_class.is_some() {
6770
return Err(ParseErrorKind::Misc(
68-
"Cannot typedef a composite's member",
71+
"Storage classes not supported here",
72+
)
73+
.at(declarator.source));
74+
}
75+
76+
if function_specifier.is_some() {
77+
return Err(ParseErrorKind::Misc(
78+
"Function specifiers cannot be used here",
6979
)
7080
.at(declarator.source));
7181
}

Diff for: src/c/translation/types/get_type_base.rs

+5-47
Original file line numberDiff line numberDiff line change
@@ -25,55 +25,13 @@ pub fn get_type_base(
2525

2626
for specifier in declaration_specifiers.specifiers.iter() {
2727
match &specifier.kind {
28-
DeclarationSpecifierKind::Auto => {
29-
return Err(ParseError::message(
30-
"'auto' not supported yet",
31-
specifier.source,
32-
))
28+
DeclarationSpecifierKind::StorageClassSpecifier(storage_class) => {
29+
builder.storage_class = Some(*storage_class);
3330
}
34-
DeclarationSpecifierKind::Constexpr => {
35-
return Err(ParseError::message(
36-
"'constexpr' not supported yet",
37-
specifier.source,
38-
))
39-
}
40-
DeclarationSpecifierKind::Extern => {
41-
return Err(ParseError::message(
42-
"'extern' not supported yet",
43-
specifier.source,
44-
))
45-
}
46-
DeclarationSpecifierKind::Register => {
47-
return Err(ParseError::message(
48-
"'register' declaration specifier not supported yet",
49-
specifier.source,
50-
))
51-
}
52-
DeclarationSpecifierKind::Static => {
53-
return Err(ParseError::message(
54-
"'static' declaration specifier not supported yet",
55-
specifier.source,
56-
))
57-
}
58-
DeclarationSpecifierKind::ThreadLocal => {
59-
return Err(ParseError::message(
60-
"'thread_local' declaration specifier not supported yet",
61-
specifier.source,
62-
))
63-
}
64-
DeclarationSpecifierKind::Typedef => builder.is_typedef = true,
65-
DeclarationSpecifierKind::Inline => {
66-
return Err(ParseError::message(
67-
"'inline' declaration specifier not supported yet",
68-
specifier.source,
69-
))
70-
}
71-
DeclarationSpecifierKind::Noreturn => {
72-
return Err(ParseError::message(
73-
"'_Noreturn' declaration specifier not supported yet",
74-
specifier.source,
75-
))
31+
DeclarationSpecifierKind::FunctionSpecifier(function_specifier) => {
32+
builder.function_specifier = Some(*function_specifier);
7633
}
34+
7735
DeclarationSpecifierKind::TypeSpecifierQualifier(tsq) => {
7836
build_type_specifier_qualifier(ast_file, &mut builder, typedefs, tsq, diagnostics)?
7937
}

0 commit comments

Comments
 (0)