Skip to content

Commit

Permalink
Merge pull request #28 from IsaacShelton/new_type_resolution
Browse files Browse the repository at this point in the history
feat: create new type resolution system that will support new import-based namespaces
  • Loading branch information
IsaacShelton authored Oct 15, 2024
2 parents 356a48e + e2ae56b commit 710d43d
Show file tree
Hide file tree
Showing 32 changed files with 885 additions and 670 deletions.
1 change: 1 addition & 0 deletions src/ast/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use num::BigInt;

#[derive(Clone, Debug)]
pub struct Enum {
pub name: String,
pub backing_type: Option<Type>,
pub source: Source,
pub members: IndexMap<String, EnumMember>,
Expand Down
8 changes: 4 additions & 4 deletions src/ast/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use indexmap::IndexMap;
pub struct AstFile {
pub functions: Vec<Function>,
pub structures: Vec<Structure>,
pub type_aliases: IndexMap<Name, TypeAlias>,
pub type_aliases: Vec<TypeAlias>,
pub global_variables: Vec<GlobalVar>,
pub enums: IndexMap<Name, Enum>,
pub enums: Vec<Enum>,
pub helper_exprs: IndexMap<Name, HelperExpr>,
pub settings: Option<SettingsId>,
}
Expand All @@ -21,9 +21,9 @@ impl AstFile {
AstFile {
functions: vec![],
structures: vec![],
type_aliases: IndexMap::default(),
type_aliases: vec![],
global_variables: vec![],
enums: IndexMap::default(),
enums: vec![],
helper_exprs: IndexMap::default(),
settings: None,
}
Expand Down
1 change: 1 addition & 0 deletions src/ast/type_alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::source_files::Source;

#[derive(Clone, Debug)]
pub struct TypeAlias {
pub name: String,
pub value: Type,
pub source: Source,
pub privacy: Privacy,
Expand Down
36 changes: 18 additions & 18 deletions src/ast/workspace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,6 @@ pub struct AstWorkspace<'a> {
impl<'a> AstWorkspace<'a> {
pub const DEFAULT_SETTINGS_ID: SettingsId = SettingsId(0);

pub fn get_owning_module(&self, fs_node_id: FsNodeId) -> Option<FsNodeId> {
let mut fs_node_id = fs_node_id;

loop {
if self.module_folders.contains_key(&fs_node_id) {
return Some(fs_node_id);
}

if let Some(parent) = self.fs.get(fs_node_id).parent {
fs_node_id = parent;
} else {
break;
}
}

None
}

pub fn new(
fs: Fs,
files: IndexMap<FsNodeId, AstFile>,
Expand Down Expand Up @@ -70,6 +52,24 @@ impl<'a> AstWorkspace<'a> {
workspace
}

pub fn get_owning_module(&self, fs_node_id: FsNodeId) -> Option<FsNodeId> {
let mut fs_node_id = fs_node_id;

loop {
if self.module_folders.contains_key(&fs_node_id) {
return Some(fs_node_id);
}

if let Some(parent) = self.fs.get(fs_node_id).parent {
fs_node_id = parent;
} else {
break;
}
}

None
}

pub fn get_mut(&mut self, id: FsNodeId) -> Option<&mut AstFile> {
self.files.get_mut(&id)
}
Expand Down
15 changes: 6 additions & 9 deletions src/c/translation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::{
ast::{self, AstFile, Privacy},
c::parser::{CTypedef, DeclarationSpecifiers, Declarator, ParseError},
diagnostics::Diagnostics,
name::Name,
};
use std::collections::HashMap;

Expand All @@ -32,14 +31,12 @@ pub fn declare_named_declaration(
)?;

if is_typedef {
ast_file.type_aliases.insert(
Name::plain(name.clone()),
ast::TypeAlias {
value: ast_type.clone(),
source: declarator.source,
privacy: Privacy::Public,
},
);
ast_file.type_aliases.push(ast::TypeAlias {
name: name.clone(),
value: ast_type.clone(),
source: declarator.source,
privacy: Privacy::Public,
});

typedefs.insert(name, CTypedef { ast_type });
return Ok(());
Expand Down
46 changes: 22 additions & 24 deletions src/interpreter_env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,30 +106,28 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
privacy: Privacy::Public,
});

file.enums.insert(
Name::plain("ProjectKind"),
Enum {
backing_type: Some(TypeKind::u64().at(source)),
source,
members: IndexMap::from_iter([
(
"ConsoleApp".into(),
EnumMember {
value: (ProjectKind::ConsoleApp as u64).into(),
explicit_value: true,
},
),
(
"WindowedApp".into(),
EnumMember {
value: (ProjectKind::WindowedApp as u64).into(),
explicit_value: true,
},
),
]),
privacy: Privacy::Private,
},
);
file.enums.push(Enum {
name: "ProjectKind".into(),
backing_type: Some(TypeKind::u64().at(source)),
source,
members: IndexMap::from_iter([
(
"ConsoleApp".into(),
EnumMember {
value: (ProjectKind::ConsoleApp as u64).into(),
explicit_value: true,
},
),
(
"WindowedApp".into(),
EnumMember {
value: (ProjectKind::WindowedApp as u64).into(),
explicit_value: true,
},
),
]),
privacy: Privacy::Private,
});

file.structures.push(Structure {
name: Name::plain("Project"),
Expand Down
42 changes: 24 additions & 18 deletions src/lower/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ fn lower_global(
let mangled_name = if global.is_foreign {
global.name.plain().to_string()
} else {
global.name.display(resolved_ast.fs).to_string()
global.name.display(&resolved_ast.workspace.fs).to_string()
};

ir_module.globals.insert(
Expand Down Expand Up @@ -167,7 +167,10 @@ fn lower_function(
} else {
return Err(LowerErrorKind::MustReturnValueOfTypeBeforeExitingFunction {
return_type: function.return_type.to_string(),
function: function.name.display(resolved_ast.fs).to_string(),
function: function
.name
.display(&resolved_ast.workspace.fs)
.to_string(),
}
.at(function.source));
}
Expand Down Expand Up @@ -200,7 +203,10 @@ fn lower_function(
} else if function.is_foreign {
function.name.plain().to_string()
} else {
function.name.display(resolved_ast.fs).to_string()
function
.name
.display(&resolved_ast.workspace.fs)
.to_string()
};

let is_main = mangled_name == "main";
Expand Down Expand Up @@ -341,6 +347,7 @@ fn lower_type(
use resolved::{IntegerBits as Bits, IntegerSign as Sign};

match &resolved_type.kind {
resolved::TypeKind::Unresolved => panic!("got unresolved type during lower_type!"),
resolved::TypeKind::Boolean => Ok(ir::Type::Boolean),
resolved::TypeKind::Integer(bits, sign) => Ok(match (bits, sign) {
(Bits::Bits8, Sign::Signed) => ir::Type::S8,
Expand Down Expand Up @@ -395,14 +402,22 @@ fn lower_type(
})))
}
resolved::TypeKind::FunctionPointer(_function_pointer) => Ok(ir::Type::FunctionPointer),
resolved::TypeKind::Enum(enum_name) => {
resolved::TypeKind::Enum(_human_name, enum_ref) => {
let enum_definition = resolved_ast
.enums
.get(enum_name)
.get(*enum_ref)
.expect("referenced enum to exist");

lower_type(target, &enum_definition.resolved_type, resolved_ast)
}
resolved::TypeKind::TypeAlias(_, type_alias_ref) => {
let resolved_type = resolved_ast
.type_aliases
.get(*type_alias_ref)
.expect("referenced type alias to exist");

lower_type(target, resolved_type, resolved_ast)
}
}
}

Expand Down Expand Up @@ -888,18 +903,15 @@ fn lower_expr(
ExprKind::EnumMemberLiteral(enum_member_literal) => {
let enum_definition = resolved_ast
.enums
.get(&enum_member_literal.enum_name)
.get(enum_member_literal.enum_ref)
.expect("referenced enum to exist for enum member literal");

let member = enum_definition
.members
.get(&enum_member_literal.variant_name)
.ok_or_else(|| {
LowerErrorKind::NoSuchEnumMember {
enum_name: enum_member_literal
.enum_name
.display(resolved_ast.fs)
.to_string(),
enum_name: enum_member_literal.human_name.to_string(),
variant_name: enum_member_literal.variant_name.clone(),
}
.at(enum_member_literal.source)
Expand All @@ -916,10 +928,7 @@ fn lower_expr(
let make_error = |_| {
LowerErrorKind::CannotFit {
value: value.to_string(),
expected_type: enum_member_literal
.enum_name
.display(resolved_ast.fs)
.to_string(),
expected_type: enum_member_literal.human_name.to_string(),
}
.at(enum_definition.source)
};
Expand Down Expand Up @@ -951,10 +960,7 @@ fn lower_expr(
}
_ => {
return Err(LowerErrorKind::EnumBackingTypeMustBeInteger {
enum_name: enum_member_literal
.enum_name
.display(resolved_ast.fs)
.to_string(),
enum_name: enum_member_literal.human_name.to_string(),
}
.at(enum_definition.source))
}
Expand Down
6 changes: 3 additions & 3 deletions src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ impl Display for DisplayResolvedName<'_> {
#[allow(dead_code)]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let filename = &self.fs.get(self.name.fs_node_id).filename;
let prefix = if cfg!(target_os = "windows") { "/" } else { "" };
let prefix = if cfg!(target_os = "windows") { "" } else { "/" };

write!(
f,
"{}{} ::: {}",
"{}{} - {}",
prefix,
filename.to_string_lossy(),
self.name.plain()
self.name.plain(),
)?;

Ok(())
Expand Down
21 changes: 8 additions & 13 deletions src/parser/parse_enum.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
use super::{annotation::Annotation, error::ParseError, Parser};
use crate::{
ast::{Enum, EnumMember, Named, Privacy},
ast::{Enum, EnumMember, Privacy},
inflow::Inflow,
name::Name,
parser::annotation::AnnotationKind,
token::{Token, TokenKind},
};
use indexmap::IndexMap;
use num::{BigInt, Zero};

impl<'a, I: Inflow<Token>> Parser<'a, I> {
pub fn parse_enum(&mut self, annotations: Vec<Annotation>) -> Result<Named<Enum>, ParseError> {
pub fn parse_enum(&mut self, annotations: Vec<Annotation>) -> Result<Enum, ParseError> {
let source = self.source_here();
assert!(self.input.advance().is_enum_keyword());

let mut privacy = Privacy::Private;
let mut namespace = None;
let name = self.parse_identifier(Some("for enum name after 'enum' keyword"))?;
self.ignore_newlines();

for annotation in annotations {
match annotation.kind {
AnnotationKind::Namespace(new_namespace) => namespace = Some(new_namespace),
AnnotationKind::Public => privacy = Privacy::Public,
_ => return Err(self.unexpected_annotation(&annotation, Some("for enum"))),
}
Expand Down Expand Up @@ -58,14 +55,12 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {

self.parse_token(TokenKind::CloseParen, Some("to close enum body"))?;

Ok(Named::<Enum> {
name: Name::new(namespace, name),
value: Enum {
backing_type: None,
members,
source,
privacy,
},
Ok(Enum {
name,
backing_type: None,
members,
source,
privacy,
})
}
}
28 changes: 5 additions & 23 deletions src/parser/parse_top_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::{
Parser,
};
use crate::{
ast::{AstFile, Enum, HelperExpr, Named, TypeAlias},
ast::{AstFile, HelperExpr, Named},
index_map_ext::IndexMapExt,
inflow::Inflow,
token::{Token, TokenKind},
Expand Down Expand Up @@ -60,31 +60,13 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
ast_file.structures.push(self.parse_structure(annotations)?)
}
TokenKind::TypeAliasKeyword => {
let Named::<TypeAlias> { name, value: alias } =
self.parse_type_alias(annotations)?;
let source = alias.source;

ast_file.type_aliases.try_insert(name, alias, |name| {
ParseErrorKind::TypeAliasHasMultipleDefinitions {
name: name.to_string(),
}
.at(source)
})?;
let type_alias = self.parse_type_alias(annotations)?;
ast_file.type_aliases.push(type_alias);
}
TokenKind::EnumKeyword => {
let Named::<Enum> {
name,
value: enum_definition,
} = self.parse_enum(annotations)?;
let enum_definition = self.parse_enum(annotations)?;

let source = enum_definition.source;

ast_file.enums.try_insert(name, enum_definition, |name| {
ParseErrorKind::EnumHasMultipleDefinitions {
name: name.to_string(),
}
.at(source)
})?;
ast_file.enums.push(enum_definition);
}
TokenKind::DefineKeyword => {
let Named::<HelperExpr> {
Expand Down
Loading

0 comments on commit 710d43d

Please sign in to comment.