Skip to content

Commit

Permalink
Reintroduce futures using Future and Promise
Browse files Browse the repository at this point in the history
This commit reintroduces futures, allowing messages to send their
results back to the sender of the message, without the need for a
channel. Futures are split into two user facing types: Future and
Promise. A Future is a proxy for a value to be computed in the future,
while a Promise is used for specifying what that value is. Both a Future
and Promise can only be used once (e.g. Future.get consumes its
receiver). This in turn allows for a simple and efficient
implementation, rather than the more complex implementation of the old
Channel type.

TODO: add deque
TODO: replace channels

Changelog: changed
  • Loading branch information
yorickpeterse committed Sep 17, 2024
1 parent e0feaae commit 61702ef
Show file tree
Hide file tree
Showing 22 changed files with 1,144 additions and 385 deletions.
4 changes: 2 additions & 2 deletions compiler/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,14 +444,14 @@ impl Diagnostics {
);
}

pub(crate) fn builtin_function_not_available(
pub(crate) fn intrinsic_not_available(
&mut self,
file: PathBuf,
location: SourceLocation,
) {
self.error(
DiagnosticId::InvalidCall,
"builtin functions can only be used in the standard library",
"intrinsics can only be used in the standard library",
file,
location,
);
Expand Down
43 changes: 40 additions & 3 deletions compiler/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,14 @@ pub(crate) struct Call {
/// `Option<Vec<Argument>>` since we don't care about the presence (or lack)
/// of parentheses 99% of the time.
pub(crate) parens: bool,
/// A flag indicating if the call resides directly in a `mut` expression.
pub(crate) in_mut: bool,
pub(crate) location: SourceLocation,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct BuiltinCall {
pub(crate) info: Option<types::BuiltinCallInfo>,
pub(crate) info: Option<types::IntrinsicCall>,
pub(crate) name: Identifier,
pub(crate) arguments: Vec<Expression>,
pub(crate) location: SourceLocation,
Expand Down Expand Up @@ -859,6 +861,7 @@ pub(crate) struct FieldRef {
pub(crate) name: String,
pub(crate) resolved_type: types::TypeRef,
pub(crate) location: SourceLocation,
pub(crate) in_mut: bool,
}

#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -2065,6 +2068,7 @@ impl<'a> LowerToHir<'a> {
location: loc.clone(),
},
parens: false,
in_mut: false,
arguments: Vec::new(),
location: loc,
}));
Expand Down Expand Up @@ -2131,6 +2135,7 @@ impl<'a> LowerToHir<'a> {
location: node.location.clone(),
},
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: Expression::Int(Box::new(IntLiteral {
Expand Down Expand Up @@ -2165,6 +2170,7 @@ impl<'a> LowerToHir<'a> {
location: node.location.clone(),
},
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: arg,
Expand Down Expand Up @@ -2405,6 +2411,7 @@ impl<'a> LowerToHir<'a> {
location: node.operator.location,
},
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: self.expression(node.right),
Expand All @@ -2420,6 +2427,7 @@ impl<'a> LowerToHir<'a> {
field_id: None,
name: node.name,
resolved_type: types::TypeRef::Unknown,
in_mut: false,
location: node.location,
})
}
Expand All @@ -2445,7 +2453,7 @@ impl<'a> LowerToHir<'a> {
fn call(&mut self, node: ast::Call) -> Expression {
if self.is_builtin_call(&node) {
if !self.module.is_std(&self.state.db) {
self.state.diagnostics.builtin_function_not_available(
self.state.diagnostics.intrinsic_not_available(
self.file(),
node.location.clone(),
);
Expand All @@ -2471,6 +2479,7 @@ impl<'a> LowerToHir<'a> {
receiver: node.receiver.map(|n| self.expression(n)),
name: self.identifier(node.name),
parens: node.arguments.is_some(),
in_mut: false,
arguments: self.optional_call_arguments(node.arguments),
location: node.location,
}))
Expand Down Expand Up @@ -2641,6 +2650,7 @@ impl<'a> LowerToHir<'a> {
},
receiver: Some(receiver),
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: self.expression(node.value),
Expand All @@ -2664,6 +2674,7 @@ impl<'a> LowerToHir<'a> {
field_id: None,
name: field.name.clone(),
resolved_type: types::TypeRef::Unknown,
in_mut: false,
location: field.location.clone(),
}));

Expand All @@ -2678,6 +2689,7 @@ impl<'a> LowerToHir<'a> {
},
receiver: Some(receiver),
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: self.expression(node.value),
Expand Down Expand Up @@ -2730,6 +2742,7 @@ impl<'a> LowerToHir<'a> {
receiver: Some(setter_rec.clone()),
name: name.clone(),
parens: false,
in_mut: false,
arguments: Vec::new(),
location: getter_loc,
}));
Expand All @@ -2742,6 +2755,7 @@ impl<'a> LowerToHir<'a> {
kind: types::CallKind::Unknown,
receiver: Some(getter_rec),
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: self.expression(node.value),
Expand Down Expand Up @@ -2855,10 +2869,18 @@ impl<'a> LowerToHir<'a> {
}

fn mut_reference(&mut self, node: ast::Mut) -> Box<Mut> {
let mut value = self.expression(node.value);

match &mut value {
Expression::Call(n) => n.in_mut = true,
Expression::FieldRef(n) => n.in_mut = true,
_ => {}
}

Box::new(Mut {
pointer_to_method: None,
resolved_type: types::TypeRef::Unknown,
value: self.expression(node.value),
value,
location: node.location,
})
}
Expand Down Expand Up @@ -5172,6 +5194,7 @@ mod tests {
location: cols(12, 13)
},
parens: false,
in_mut: false,
arguments: Vec::new(),
location: cols(12, 13)
})),
Expand Down Expand Up @@ -5220,6 +5243,7 @@ mod tests {
location: cols(8, 11),
},
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: Expression::Int(Box::new(
Expand Down Expand Up @@ -5251,6 +5275,7 @@ mod tests {
location: cols(8, 11),
},
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: Expression::Int(Box::new(IntLiteral {
Expand Down Expand Up @@ -5308,6 +5333,7 @@ mod tests {
location: cols(8, 8)
}))),
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: Expression::Int(Box::new(IntLiteral {
Expand Down Expand Up @@ -5337,6 +5363,7 @@ mod tests {
field_id: None,
name: "a".to_string(),
resolved_type: types::TypeRef::Unknown,
in_mut: false,
location: cols(8, 9)
}))
);
Expand Down Expand Up @@ -5378,6 +5405,7 @@ mod tests {
location: cols(10, 10)
},
parens: false,
in_mut: false,
arguments: Vec::new(),
location: cols(8, 10)
}))
Expand Down Expand Up @@ -5412,6 +5440,7 @@ mod tests {
location: cols(8, 8)
},
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: Expression::Int(Box::new(IntLiteral {
Expand Down Expand Up @@ -5441,6 +5470,7 @@ mod tests {
location: cols(8, 8)
},
parens: true,
in_mut: false,
arguments: vec![Argument::Named(Box::new(NamedArgument {
index: 0,
name: Identifier {
Expand Down Expand Up @@ -5480,6 +5510,7 @@ mod tests {
location: cols(10, 10)
},
parens: false,
in_mut: false,
arguments: Vec::new(),
location: cols(8, 10)
}))
Expand Down Expand Up @@ -5655,6 +5686,7 @@ mod tests {
}
))),
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: Expression::Int(Box::new(IntLiteral {
Expand Down Expand Up @@ -5738,10 +5770,12 @@ mod tests {
location: cols(10, 10)
},
parens: false,
in_mut: false,
arguments: Vec::new(),
location: cols(8, 10)
}))),
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: Expression::Int(Box::new(IntLiteral {
Expand Down Expand Up @@ -5779,9 +5813,11 @@ mod tests {
field_id: None,
name: "a".to_string(),
resolved_type: types::TypeRef::Unknown,
in_mut: false,
location: cols(8, 9)
}))),
parens: true,
in_mut: false,
arguments: vec![Argument::Positional(Box::new(
PositionalArgument {
value: Expression::Int(Box::new(IntLiteral {
Expand Down Expand Up @@ -6167,6 +6203,7 @@ mod tests {
location: cols(12, 12)
},
parens: true,
in_mut: false,
arguments: Vec::new(),
location: cols(12, 14)
})),
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@ pub(crate) fn link(
cmd.arg("-framework");
cmd.arg(name);
}

// We need to ensure that we target the same minimum version as Rust
// uses when building the runtime library.
cmd.arg("-mmacosx-version-min=11.0");
}
}

Expand Down
42 changes: 30 additions & 12 deletions compiler/src/llvm/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,16 @@ impl<'ctx> Builder<'ctx> {
.into_float_value()
}

pub(crate) fn load_bool(
&self,
variable: PointerValue<'ctx>,
) -> IntValue<'ctx> {
self.inner
.build_load(self.context.bool_type(), variable, "")
.unwrap()
.into_int_value()
}

pub(crate) fn load_pointer(
&self,
variable: PointerValue<'ctx>,
Expand Down Expand Up @@ -299,6 +309,26 @@ impl<'ctx> Builder<'ctx> {
.unwrap()
}

pub(crate) fn atomic_swap<V: BasicValue<'ctx>>(
&self,
pointer: PointerValue<'ctx>,
old: V,
new: V,
) -> IntValue<'ctx> {
let res = self
.inner
.build_cmpxchg(
pointer,
old,
new,
AtomicOrdering::AcquireRelease,
AtomicOrdering::Acquire,
)
.unwrap();

self.extract_field(res, 1).into_int_value()
}

pub(crate) fn load_atomic_counter(
&self,
variable: PointerValue<'ctx>,
Expand Down Expand Up @@ -484,18 +514,6 @@ impl<'ctx> Builder<'ctx> {
self.inner.build_int_cast_sign_flag(value, target, signed, "").unwrap()
}

pub(crate) fn bool_to_int(&self, value: IntValue<'ctx>) -> IntValue<'ctx> {
let typ = self.context.i64_type();

self.inner.build_int_cast_sign_flag(value, typ, false, "").unwrap()
}

pub(crate) fn int_to_bool(&self, value: IntValue<'ctx>) -> IntValue<'ctx> {
let typ = self.context.bool_type();

self.inner.build_int_cast_sign_flag(value, typ, true, "").unwrap()
}

pub(crate) fn float_to_float(
&self,
value: FloatValue<'ctx>,
Expand Down
17 changes: 8 additions & 9 deletions compiler/src/llvm/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,15 @@ impl Context {
layouts: &Layouts<'a>,
type_ref: TypeRef,
) -> BasicTypeEnum<'a> {
if let TypeRef::Pointer(_) = type_ref {
return self.pointer_type().as_basic_type_enum();
}

let Ok(id) = type_ref.type_id(db) else {
return self.pointer_type().as_basic_type_enum();
};

let base = match id {
match id {
TypeId::Foreign(ForeignType::Int(8, _)) => {
self.i8_type().as_basic_type_enum()
}
Expand All @@ -186,21 +190,16 @@ impl Context {
.as_basic_type_enum()
} else {
match cls.0 {
INT_ID | BOOL_ID | NIL_ID => {
self.i64_type().as_basic_type_enum()
BOOL_ID | NIL_ID => {
self.bool_type().as_basic_type_enum()
}
INT_ID => self.i64_type().as_basic_type_enum(),
FLOAT_ID => self.f64_type().as_basic_type_enum(),
_ => self.pointer_type().as_basic_type_enum(),
}
}
}
_ => self.pointer_type().as_basic_type_enum(),
};

if let TypeRef::Pointer(_) = type_ref {
self.pointer_type().as_basic_type_enum()
} else {
base
}
}

Expand Down
Loading

0 comments on commit 61702ef

Please sign in to comment.