Skip to content

Commit

Permalink
Implement file IO in Inko
Browse files Browse the repository at this point in the history
TODO: write the rest of the commit message.

This commit includes changes related to defining the types and values of
constants. Prior to this commit the work was performed in two passes,
but this approach wasn't able to handle certain cases introduced by the
IO changes. In the new setup, both defining the types and values uses a
work list that is processed until no more constants remain, or until we
detect a circular dependency (e.g. A = B and B = A).

This fixes #633 and closes
#583.

Changelog: changed
  • Loading branch information
yorickpeterse committed Aug 28, 2024
1 parent ac83133 commit 998a95e
Show file tree
Hide file tree
Showing 50 changed files with 1,564 additions and 742 deletions.
12 changes: 6 additions & 6 deletions ast/src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ impl Node for DefineField {
pub enum ClassExpression {
DefineMethod(Box<DefineMethod>),
DefineField(Box<DefineField>),
DefineVariant(Box<DefineVariant>),
DefineConstructor(Box<DefineConstructor>),
Comment(Box<Comment>),
}

Expand All @@ -461,7 +461,7 @@ impl Node for ClassExpression {
match self {
ClassExpression::DefineMethod(n) => &n.location,
ClassExpression::DefineField(n) => &n.location,
ClassExpression::DefineVariant(n) => &n.location,
ClassExpression::DefineConstructor(n) => &n.location,
ClassExpression::Comment(n) => &n.location,
}
}
Expand Down Expand Up @@ -505,7 +505,7 @@ impl Node for DefineClass {
}

#[derive(Debug, PartialEq, Eq)]
pub struct DefineVariant {
pub struct DefineConstructor {
pub name: Constant,
pub members: Option<Types>,
pub location: SourceLocation,
Expand Down Expand Up @@ -1438,7 +1438,7 @@ pub struct TuplePattern {
}

#[derive(Debug, PartialEq, Eq)]
pub struct VariantPattern {
pub struct ConstructorPattern {
pub name: Constant,
pub values: Vec<Pattern>,
pub location: SourceLocation,
Expand Down Expand Up @@ -1485,7 +1485,7 @@ pub struct StringPattern {
#[derive(Debug, PartialEq, Eq)]
pub enum Pattern {
Constant(Box<Constant>),
Variant(Box<VariantPattern>),
Constructor(Box<ConstructorPattern>),
Class(Box<ClassPattern>),
Int(Box<IntLiteral>),
True(Box<True>),
Expand All @@ -1501,7 +1501,7 @@ impl Pattern {
pub fn location(&self) -> &SourceLocation {
match self {
Pattern::Constant(ref n) => &n.location,
Pattern::Variant(ref n) => &n.location,
Pattern::Constructor(ref n) => &n.location,
Pattern::Class(ref n) => &n.location,
Pattern::Int(ref n) => n.location(),
Pattern::True(ref n) => n.location(),
Expand Down
42 changes: 22 additions & 20 deletions ast/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1076,7 +1076,7 @@ impl Parser {
fn define_constructor(
&mut self,
start: Token,
) -> Result<DefineVariant, ParseError> {
) -> Result<DefineConstructor, ParseError> {
let name = Constant::from(self.expect(TokenKind::Constant)?);
let members = if self.peek().kind == TokenKind::ParenOpen {
let (values, location) = self.list(
Expand All @@ -1094,7 +1094,7 @@ impl Parser {
members.as_ref().map(|n| &n.location).unwrap_or(&start.location);
let location = SourceLocation::start_end(&start.location, end_loc);

Ok(DefineVariant { name, members, location })
Ok(DefineConstructor { name, members, location })
}

fn class_expressions(&mut self) -> Result<ClassExpressions, ParseError> {
Expand Down Expand Up @@ -1161,7 +1161,7 @@ impl Parser {
TokenKind::Fn => ClassExpression::DefineMethod(Box::new(
self.define_method(start)?,
)),
TokenKind::Case => ClassExpression::DefineVariant(Box::new(
TokenKind::Case => ClassExpression::DefineConstructor(Box::new(
self.define_constructor(start)?,
)),
TokenKind::Comment => ClassExpression::Comment(self.comment(start)),
Expand Down Expand Up @@ -2734,7 +2734,7 @@ impl Parser {
let location =
SourceLocation::start_end(&name.location, &close.location);

Pattern::Variant(Box::new(VariantPattern {
Pattern::Constructor(Box::new(ConstructorPattern {
name,
values,
location,
Expand Down Expand Up @@ -9184,18 +9184,20 @@ mod tests {
location: cols(7, 7)
})),
expressions: vec![MatchExpression::Case(Box::new(MatchCase {
pattern: Pattern::Variant(Box::new(VariantPattern {
name: Constant {
source: None,
name: "A".to_string(),
location: cols(16, 16)
},
values: vec![Pattern::Int(Box::new(IntLiteral {
value: "1".to_string(),
location: cols(18, 18)
}))],
location: cols(16, 19)
})),
pattern: Pattern::Constructor(Box::new(
ConstructorPattern {
name: Constant {
source: None,
name: "A".to_string(),
location: cols(16, 16)
},
values: vec![Pattern::Int(Box::new(IntLiteral {
value: "1".to_string(),
location: cols(18, 18)
}))],
location: cols(16, 19)
}
)),
guard: None,
body: Expressions {
values: vec![Expression::Int(Box::new(IntLiteral {
Expand Down Expand Up @@ -9448,8 +9450,8 @@ mod tests {
}),
body: ClassExpressions {
values: vec![
ClassExpression::DefineVariant(Box::new(
DefineVariant {
ClassExpression::DefineConstructor(Box::new(
DefineConstructor {
name: Constant {
source: None,
name: "Some".to_string(),
Expand All @@ -9475,8 +9477,8 @@ mod tests {
location: cols(24, 35)
},
)),
ClassExpression::DefineVariant(Box::new(
DefineVariant {
ClassExpression::DefineConstructor(Box::new(
DefineConstructor {
name: Constant {
source: None,
name: "None".to_string(),
Expand Down
12 changes: 6 additions & 6 deletions compiler/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ use crate::pkg::version::Version;
use crate::state::State;
use crate::type_check::define_types::{
CheckTraitImplementations, CheckTraitRequirements, CheckTypeParameters,
DefineFields, DefineTraitRequirements, DefineTypeParameterRequirements,
DefineTypeParameters, DefineTypes, DefineVariants, ImplementTraits,
InsertPrelude,
DefineConstructors, DefineFields, DefineTraitRequirements,
DefineTypeParameterRequirements, DefineTypeParameters, DefineTypes,
ImplementTraits, InsertPrelude,
};
use crate::type_check::expressions::{DefineConstants, Expressions};
use crate::type_check::expressions::{define_constants, Expressions};
use crate::type_check::imports::{CollectExternImports, DefineImportedTypes};
use crate::type_check::methods::{
CheckMainMethod, DefineMethods, DefineModuleMethodNames,
Expand Down Expand Up @@ -448,12 +448,12 @@ LLVM module timings:
&& ImplementTraits::run_all(state, modules)
&& CheckTraitImplementations::run_all(state, modules)
&& CheckTypeParameters::run_all(state, modules)
&& DefineVariants::run_all(state, modules)
&& DefineConstructors::run_all(state, modules)
&& DefineFields::run_all(state, modules)
&& DefineMethods::run_all(state, modules)
&& CheckMainMethod::run(state)
&& ImplementTraitMethods::run_all(state, modules)
&& DefineConstants::run_all(state, modules)
&& define_constants(state, modules)
&& Expressions::run_all(state, modules);

self.timings.type_check = start.elapsed();
Expand Down
14 changes: 14 additions & 0 deletions compiler/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,20 @@ impl Diagnostics {
);
}

pub(crate) fn not_a_module(
&mut self,
name: &str,
file: PathBuf,
location: SourceLocation,
) {
self.error(
DiagnosticId::InvalidSymbol,
format!("the symbol '{}' isn't a module", name),
file,
location,
);
}

pub(crate) fn duplicate_method(
&mut self,
method_name: &str,
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ impl<'a> DefineDocumentation<'a> {
take(&mut n.documentation),
);
}
hir::ClassExpression::Variant(n) => {
hir::ClassExpression::Constructor(n) => {
n.constructor_id.unwrap().set_documentation(
self.db_mut(),
take(&mut n.documentation),
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,9 +760,9 @@ impl Document {
self.define_field(n),
matches!(next, Some(ClassExpression::DefineField(_))),
),
ClassExpression::DefineVariant(n) => (
ClassExpression::DefineConstructor(n) => (
self.define_constructor(n),
matches!(next, Some(ClassExpression::DefineVariant(_))),
matches!(next, Some(ClassExpression::DefineConstructor(_))),
),
ClassExpression::Comment(n) => (self.comment(n), true),
};
Expand Down Expand Up @@ -1040,7 +1040,7 @@ impl Document {
Node::Nodes(group)
}

fn define_constructor(&mut self, node: &nodes::DefineVariant) -> Node {
fn define_constructor(&mut self, node: &nodes::DefineConstructor) -> Node {
let mut group = vec![Node::text("case "), Node::text(&node.name.name)];

if let Some(nodes) =
Expand Down Expand Up @@ -2098,7 +2098,7 @@ impl Document {
nodes::Pattern::Constant(n) => {
vec![self.constant(n)]
}
nodes::Pattern::Variant(n) => {
nodes::Pattern::Constructor(n) => {
let mut group = vec![Node::text(&n.name.name)];

if !n.values.is_empty() {
Expand Down
39 changes: 14 additions & 25 deletions compiler/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ pub(crate) enum ClassExpression {
StaticMethod(Box<DefineStaticMethod>),
AsyncMethod(Box<DefineAsyncMethod>),
Field(Box<DefineField>),
Variant(Box<DefineVariant>),
Constructor(Box<DefineConstructor>),
}

#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -409,10 +409,10 @@ pub(crate) struct DefineExternClass {
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct DefineVariant {
pub(crate) struct DefineConstructor {
pub(crate) documentation: String,
pub(crate) method_id: Option<types::MethodId>,
pub(crate) constructor_id: Option<types::VariantId>,
pub(crate) constructor_id: Option<types::ConstructorId>,
pub(crate) name: Constant,
pub(crate) members: Vec<Type>,
pub(crate) location: SourceLocation,
Expand Down Expand Up @@ -642,17 +642,6 @@ impl ConstExpression {
Self::False(ref n) => &n.location,
}
}

pub(crate) fn is_simple_literal(&self) -> bool {
matches!(
self,
ConstExpression::Int(_)
| ConstExpression::Float(_)
| ConstExpression::String(_)
| ConstExpression::True(_)
| ConstExpression::False(_)
)
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -1020,8 +1009,8 @@ pub(crate) struct ClassPattern {
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct VariantPattern {
pub(crate) constructor_id: Option<types::VariantId>,
pub(crate) struct ConstructorPattern {
pub(crate) constructor_id: Option<types::ConstructorId>,
pub(crate) name: Constant,
pub(crate) values: Vec<Pattern>,
pub(crate) location: SourceLocation,
Expand Down Expand Up @@ -1069,7 +1058,7 @@ pub(crate) enum Pattern {
Int(Box<IntLiteral>),
String(Box<StringPattern>),
Tuple(Box<TuplePattern>),
Variant(Box<VariantPattern>),
Constructor(Box<ConstructorPattern>),
Wildcard(Box<WildcardPattern>),
True(Box<True>),
False(Box<False>),
Expand All @@ -1080,7 +1069,7 @@ impl Pattern {
pub(crate) fn location(&self) -> &SourceLocation {
match self {
Pattern::Constant(ref n) => &n.location,
Pattern::Variant(ref n) => &n.location,
Pattern::Constructor(ref n) => &n.location,
Pattern::Int(ref n) => &n.location,
Pattern::String(ref n) => &n.location,
Pattern::Identifier(ref n) => &n.location,
Expand Down Expand Up @@ -1400,7 +1389,7 @@ impl<'a> LowerToHir<'a> {
self.define_field(*node, doc),
)));
}
ast::ClassExpression::DefineVariant(node) => {
ast::ClassExpression::DefineConstructor(node) => {
let doc = comments.documentation_for(&node.location);

exprs.push(self.define_case(*node, doc));
Expand Down Expand Up @@ -1431,10 +1420,10 @@ impl<'a> LowerToHir<'a> {

fn define_case(
&mut self,
node: ast::DefineVariant,
node: ast::DefineConstructor,
documentation: String,
) -> ClassExpression {
ClassExpression::Variant(Box::new(DefineVariant {
ClassExpression::Constructor(Box::new(DefineConstructor {
documentation,
method_id: None,
constructor_id: None,
Expand Down Expand Up @@ -3121,8 +3110,8 @@ impl<'a> LowerToHir<'a> {
}
ast::Pattern::True(n) => Pattern::True(self.true_literal(*n)),
ast::Pattern::False(n) => Pattern::False(self.false_literal(*n)),
ast::Pattern::Variant(n) => {
Pattern::Variant(Box::new(VariantPattern {
ast::Pattern::Constructor(n) => {
Pattern::Constructor(Box::new(ConstructorPattern {
constructor_id: None,
name: self.constant(n.name),
values: self.patterns(n.values),
Expand Down Expand Up @@ -6403,7 +6392,7 @@ mod tests {
location: cols(19, 19)
}],
body: vec![
ClassExpression::Variant(Box::new(DefineVariant {
ClassExpression::Constructor(Box::new(DefineConstructor {
documentation: String::new(),
method_id: None,
constructor_id: None,
Expand All @@ -6423,7 +6412,7 @@ mod tests {
}))],
location: cols(24, 35)
},)),
ClassExpression::Variant(Box::new(DefineVariant {
ClassExpression::Constructor(Box::new(DefineConstructor {
documentation: String::new(),
method_id: None,
constructor_id: None,
Expand Down
13 changes: 12 additions & 1 deletion compiler/src/llvm/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,20 @@ impl<'ctx> Builder<'ctx> {
index: u32,
) -> BasicValueEnum<'ctx> {
let vtype = receiver_type.get_field_type_at_index(index).unwrap();

self.load_field_as(receiver_type, receiver, index, vtype)
}

pub(crate) fn load_field_as<T: BasicType<'ctx>>(
&self,
receiver_type: StructType<'ctx>,
receiver: PointerValue<'ctx>,
index: u32,
typ: T,
) -> BasicValueEnum<'ctx> {
let field_ptr = self.field_address(receiver_type, receiver, index);

self.inner.build_load(vtype, field_ptr, "").unwrap()
self.inner.build_load(typ, field_ptr, "").unwrap()
}

pub(crate) fn field_address(
Expand Down
Loading

0 comments on commit 998a95e

Please sign in to comment.