Skip to content

Commit

Permalink
Refactor part 15
Browse files Browse the repository at this point in the history
  • Loading branch information
Rigidity committed Jun 23, 2024
1 parent efef59b commit f5d9dba
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 78 deletions.
70 changes: 2 additions & 68 deletions crates/rue-compiler/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@
use std::collections::HashMap;

pub(crate) use builtins::{builtins, Builtins};
use indexmap::{IndexMap, IndexSet};
use indexmap::IndexSet;
use rowan::TextRange;
use rue_parser::{AstNode, StructField, StructItem, TypeAliasItem};
use symbol_table::SymbolTable;

use crate::{
database::{Database, HirId, ScopeId, SymbolId, TypeId},
hir::Hir,
scope::Scope,
ty::{FunctionType, PairType, Rest, StructType, Type, Value},
ty::{FunctionType, PairType, Rest, Type, Value},
Comparison, ErrorKind, TypeSystem,
};

Expand Down Expand Up @@ -77,71 +76,6 @@ impl<'a> Compiler<'a> {
self.sym
}

/// Define a type for an alias in the current scope, but leave it as unknown for now.
fn declare_type_alias(&mut self, type_alias: &TypeAliasItem) -> TypeId {
let type_id = self.db.alloc_type(Type::Unknown);
if let Some(name) = type_alias.name() {
self.scope_mut().define_type(name.to_string(), type_id);
self.db.insert_type_token(type_id, name);
}
type_id
}

/// Define a type for a struct in the current scope, but leave it as unknown for now.
fn declare_struct(&mut self, struct_item: &StructItem) -> TypeId {
let type_id = self.db.alloc_type(Type::Unknown);
if let Some(name) = struct_item.name() {
self.scope_mut().define_type(name.to_string(), type_id);
self.db.insert_type_token(type_id, name);
}
type_id
}

/// Compile and resolve the type that the alias points to.
fn compile_type_alias(&mut self, ty: &TypeAliasItem, alias_type_id: TypeId) {
self.type_definition_stack.push(alias_type_id);

let type_id = ty
.ty()
.map_or(self.builtins.unknown, |ty| self.compile_type(ty));

// Set the alias type to the resolved type.
*self.db.ty_mut(alias_type_id) = Type::Alias(type_id);

// A cycle between type aliases has been detected.
// We set it to unknown to prevent stack overflow issues later.
if self.detect_cycle(alias_type_id, ty.syntax().text_range()) {
*self.db.ty_mut(alias_type_id) = Type::Unknown;
}

self.type_definition_stack.pop().unwrap();
}

/// Compile and resolve a struct type.
fn compile_struct(&mut self, struct_item: &StructItem, type_id: TypeId) {
self.type_definition_stack.push(type_id);
let fields = self.compile_struct_fields(struct_item.fields());
*self.db.ty_mut(type_id) = Type::Struct(StructType { fields });
self.type_definition_stack.pop().unwrap();
}

/// Compile and resolve the fields of a struct.
fn compile_struct_fields(&mut self, fields: Vec<StructField>) -> IndexMap<String, TypeId> {
let mut named_fields = IndexMap::new();

for field in fields {
let type_id = field
.ty()
.map_or(self.builtins.unknown, |ty| self.compile_type(ty));

if let Some(name) = field.name() {
named_fields.insert(name.to_string(), type_id);
};
}

named_fields
}

fn compile_index(&mut self, value: HirId, index: usize, rest: bool) -> HirId {
let mut result = value;
for _ in 0..index {
Expand Down
18 changes: 11 additions & 7 deletions crates/rue-compiler/src/compiler/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ mod const_item;
mod enum_item;
mod function_item;
mod module_item;
mod struct_item;
mod type_alias_item;

#[derive(Debug, Clone)]
pub struct Declarations {
Expand All @@ -28,9 +30,11 @@ impl Compiler<'_> {

for item in items {
match item {
Item::TypeAliasItem(ty) => type_ids.push(self.declare_type_alias(ty)),
Item::StructItem(struct_item) => type_ids.push(self.declare_struct(struct_item)),
Item::EnumItem(enum_item) => type_ids.push(self.declare_enum(enum_item)),
Item::TypeAliasItem(ty) => type_ids.push(self.declare_type_alias_item(ty)),
Item::StructItem(struct_item) => {
type_ids.push(self.declare_struct_item(struct_item));
}
Item::EnumItem(enum_item) => type_ids.push(self.declare_enum_item(enum_item)),
Item::ModuleItem(..)
| Item::FunctionItem(..)
| Item::ConstItem(..)
Expand All @@ -44,7 +48,7 @@ impl Compiler<'_> {

for item in items {
match item {
Item::ModuleItem(module) => symbol_ids.push(self.declare_module(module)),
Item::ModuleItem(module) => symbol_ids.push(self.declare_module_item(module)),
Item::FunctionItem(function) => {
symbol_ids.push(self.declare_function_item(function));
}
Expand Down Expand Up @@ -76,19 +80,19 @@ impl Compiler<'_> {
Item::TypeAliasItem(ty) => {
let type_id = declarations.type_ids.remove(0);
self.type_definition_stack.push(type_id);
self.compile_type_alias(ty, type_id);
self.compile_type_alias_item(ty, type_id);
self.type_definition_stack.pop().unwrap();
}
Item::StructItem(struct_item) => {
let type_id = declarations.type_ids.remove(0);
self.type_definition_stack.push(type_id);
self.compile_struct(struct_item, type_id);
self.compile_struct_item(struct_item, type_id);
self.type_definition_stack.pop().unwrap();
}
Item::EnumItem(enum_item) => {
let type_id = declarations.type_ids.remove(0);
self.type_definition_stack.push(type_id);
self.compile_enum(enum_item, type_id);
self.compile_enum_item(enum_item, type_id);
self.type_definition_stack.pop().unwrap();
}
Item::ModuleItem(..)
Expand Down
4 changes: 2 additions & 2 deletions crates/rue-compiler/src/compiler/item/enum_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
impl Compiler<'_> {
/// Define a type for an enum in the current scope.
/// This creates the enum variants as well, but they are left as unknown types.
pub fn declare_enum(&mut self, enum_item: &EnumItem) -> TypeId {
pub fn declare_enum_item(&mut self, enum_item: &EnumItem) -> TypeId {
let mut variants = IndexMap::new();

for variant in enum_item.variants() {
Expand Down Expand Up @@ -39,7 +39,7 @@ impl Compiler<'_> {
}

/// Compile and resolve an enum type, and each of its variants' struct fields.
pub fn compile_enum(&mut self, enum_item: &EnumItem, type_id: TypeId) {
pub fn compile_enum_item(&mut self, enum_item: &EnumItem, type_id: TypeId) {
self.type_definition_stack.push(type_id);

let Type::Enum(enum_type) = self.db.ty(type_id).clone() else {
Expand Down
2 changes: 1 addition & 1 deletion crates/rue-compiler/src/compiler/item/module_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl Compiler<'_> {
/// Define a module in the current scope.
/// This creates a new scope for the module, and declares its items.
/// The exports are added during this phase too.
pub fn declare_module(&mut self, module_item: &ModuleItem) -> SymbolId {
pub fn declare_module_item(&mut self, module_item: &ModuleItem) -> SymbolId {
// Add the symbol to the stack early so you can track type references.
let scope_id = self.db.alloc_scope(Scope::default());
let symbol_id = self.db.alloc_symbol(Symbol::Module(Module {
Expand Down
45 changes: 45 additions & 0 deletions crates/rue-compiler/src/compiler/item/struct_item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use indexmap::IndexMap;
use rue_parser::{StructField, StructItem};

use crate::{
compiler::Compiler,
ty::{StructType, Type},
TypeId,
};

impl Compiler<'_> {
/// Define a type for a struct in the current scope, but leave it as unknown for now.
pub fn declare_struct_item(&mut self, struct_item: &StructItem) -> TypeId {
let type_id = self.db.alloc_type(Type::Unknown);
if let Some(name) = struct_item.name() {
self.scope_mut().define_type(name.to_string(), type_id);
self.db.insert_type_token(type_id, name);
}
type_id
}

/// Compile and resolve a struct type.
pub fn compile_struct_item(&mut self, struct_item: &StructItem, type_id: TypeId) {
self.type_definition_stack.push(type_id);
let fields = self.compile_struct_fields(struct_item.fields());
*self.db.ty_mut(type_id) = Type::Struct(StructType { fields });
self.type_definition_stack.pop().unwrap();
}

/// Compile and resolve the fields of a struct.
pub fn compile_struct_fields(&mut self, fields: Vec<StructField>) -> IndexMap<String, TypeId> {
let mut named_fields = IndexMap::new();

for field in fields {
let type_id = field
.ty()
.map_or(self.builtins.unknown, |ty| self.compile_type(ty));

if let Some(name) = field.name() {
named_fields.insert(name.to_string(), type_id);
};
}

named_fields
}
}
35 changes: 35 additions & 0 deletions crates/rue-compiler/src/compiler/item/type_alias_item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use rue_parser::{AstNode, TypeAliasItem};

use crate::{compiler::Compiler, ty::Type, TypeId};

impl Compiler<'_> {
/// Define a type for an alias in the current scope, but leave it as unknown for now.
pub fn declare_type_alias_item(&mut self, type_alias: &TypeAliasItem) -> TypeId {
let type_id = self.db.alloc_type(Type::Unknown);
if let Some(name) = type_alias.name() {
self.scope_mut().define_type(name.to_string(), type_id);
self.db.insert_type_token(type_id, name);
}
type_id
}

/// Compile and resolve the type that the alias points to.
pub fn compile_type_alias_item(&mut self, ty: &TypeAliasItem, alias_type_id: TypeId) {
self.type_definition_stack.push(alias_type_id);

let type_id = ty
.ty()
.map_or(self.builtins.unknown, |ty| self.compile_type(ty));

// Set the alias type to the resolved type.
*self.db.ty_mut(alias_type_id) = Type::Alias(type_id);

// A cycle between type aliases has been detected.
// We set it to unknown to prevent stack overflow issues later.
if self.detect_cycle(alias_type_id, ty.syntax().text_range()) {
*self.db.ty_mut(alias_type_id) = Type::Unknown;
}

self.type_definition_stack.pop().unwrap();
}
}

0 comments on commit f5d9dba

Please sign in to comment.