Skip to content

Commit

Permalink
Merge pull request #1065 from candy-lang/lists
Browse files Browse the repository at this point in the history
Lists
  • Loading branch information
JonasWanke authored Nov 22, 2024
2 parents 626c512 + 9ec7bc2 commit c921c98
Show file tree
Hide file tree
Showing 7 changed files with 505 additions and 89 deletions.
7 changes: 6 additions & 1 deletion compiler_v4/src/ast_to_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,12 @@ impl<'a> Context<'a> {
},
);
self.global_identifiers
.force_insert(signature.name, Named::Functions(vec![id]));
.entry(signature.name)
.and_modify(|it| match it {
Named::Assignment(_) => panic!(),
Named::Functions(function_ids) => function_ids.push(id),
})
.or_insert_with(|| Named::Functions(vec![id]));
}
}

Expand Down
184 changes: 156 additions & 28 deletions compiler_v4/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,28 +332,32 @@ impl NamedType {

// Builtin types
#[must_use]
pub fn array(t: impl Into<Type>) -> Self {
Self::new("Array", [t.into()])
}
#[must_use]
pub fn int() -> Self {
Self::new("Int", [])
}
#[must_use]
pub fn list(t: impl Into<Type>) -> Self {
Self::new("List", [t.into()])
}
#[must_use]
pub fn text() -> Self {
Self::new("Text", [])
}

// Standard library types
#[must_use]
pub fn nothing() -> Self {
Self::new("Nothing", [])
pub fn maybe(t: impl Into<Type>) -> Self {
Self::new("Maybe", [t.into()])
}
#[must_use]
pub fn never() -> Self {
Self::new("Never", [])
}
#[must_use]
pub fn nothing() -> Self {
Self::new("Nothing", [])
}
#[must_use]
pub fn ordering() -> Self {
Self::new("Ordering", [])
}
Expand Down Expand Up @@ -418,8 +422,10 @@ impl Type {

#[must_use]
pub fn equals_lenient(&self, other: &Self) -> bool {
#[allow(clippy::redundant_guards)]
match (self, other) {
(Self::Error, _) | (_, Self::Error) => true,
(Self::Named(NamedType { box name, .. }), _) if name == "Never" => true,
(Self::Named(from), Self::Named(to)) => {
from.name == to.name
&& from
Expand Down Expand Up @@ -710,12 +716,22 @@ pub struct SwitchCase {
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, VariantArray)]
#[strum(serialize_all = "camelCase")]
pub enum BuiltinFunction {
ArrayFilled,
ArrayLength,
IntAdd,
IntCompareTo,
IntSubtract,
IntToText,
ListFilled,
ListGet,
ListInsert,
ListLength,
ListOf0,
ListOf1,
ListOf2,
ListOf3,
ListOf4,
ListOf5,
ListRemoveAt,
ListReplace,
Panic,
Print,
TextConcat,
Expand All @@ -729,26 +745,6 @@ impl BuiltinFunction {
#[must_use]
pub fn signature(self) -> BuiltinFunctionSignature {
match self {
Self::ArrayFilled => BuiltinFunctionSignature {
name: "builtinArrayFilled".into(),
type_parameters: ["T".into()].into(),
parameters: [
("length".into(), NamedType::int().into()),
("item".into(), ParameterType::new("T").into()),
]
.into(),
return_type: NamedType::array(ParameterType::new("T")).into(),
},
Self::ArrayLength => BuiltinFunctionSignature {
name: "builtinArrayLength".into(),
type_parameters: ["T".into()].into(),
parameters: [(
"array".into(),
NamedType::array(ParameterType::new("T")).into(),
)]
.into(),
return_type: NamedType::int().into(),
},
Self::IntAdd => BuiltinFunctionSignature {
name: "builtinIntAdd".into(),
type_parameters: Box::default(),
Expand Down Expand Up @@ -785,6 +781,138 @@ impl BuiltinFunction {
parameters: [("int".into(), NamedType::int().into())].into(),
return_type: NamedType::text().into(),
},
Self::ListFilled => BuiltinFunctionSignature {
name: "builtinListFilled".into(),
type_parameters: ["T".into()].into(),
parameters: [
("length".into(), NamedType::int().into()),
("item".into(), ParameterType::new("T").into()),
]
.into(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::ListGet => BuiltinFunctionSignature {
name: "builtinListGet".into(),
type_parameters: ["T".into()].into(),
parameters: [
(
"list".into(),
NamedType::list(ParameterType::new("T")).into(),
),
("index".into(), NamedType::int().into()),
]
.into(),
return_type: NamedType::maybe(ParameterType::new("T")).into(),
},
Self::ListInsert => BuiltinFunctionSignature {
name: "builtinListInsert".into(),
type_parameters: ["T".into()].into(),
parameters: [
(
"list".into(),
NamedType::list(ParameterType::new("T")).into(),
),
("index".into(), NamedType::int().into()),
("item".into(), ParameterType::new("T").into()),
]
.into(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::ListLength => BuiltinFunctionSignature {
name: "builtinListLength".into(),
type_parameters: ["T".into()].into(),
parameters: [(
"list".into(),
NamedType::list(ParameterType::new("T")).into(),
)]
.into(),
return_type: NamedType::int().into(),
},
Self::ListOf0 => BuiltinFunctionSignature {
name: "builtinListOf".into(),
type_parameters: ["T".into()].into(),
parameters: Box::default(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::ListOf1 => BuiltinFunctionSignature {
name: "builtinListOf".into(),
type_parameters: ["T".into()].into(),
parameters: [("item0".into(), ParameterType::new("T").into())].into(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::ListOf2 => BuiltinFunctionSignature {
name: "builtinListOf".into(),
type_parameters: ["T".into()].into(),
parameters: [
("item0".into(), ParameterType::new("T").into()),
("item1".into(), ParameterType::new("T").into()),
]
.into(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::ListOf3 => BuiltinFunctionSignature {
name: "builtinListOf".into(),
type_parameters: ["T".into()].into(),
parameters: [
("item0".into(), ParameterType::new("T").into()),
("item1".into(), ParameterType::new("T").into()),
("item2".into(), ParameterType::new("T").into()),
]
.into(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::ListOf4 => BuiltinFunctionSignature {
name: "builtinListOf".into(),
type_parameters: ["T".into()].into(),
parameters: [
("item0".into(), ParameterType::new("T").into()),
("item1".into(), ParameterType::new("T").into()),
("item2".into(), ParameterType::new("T").into()),
("item3".into(), ParameterType::new("T").into()),
]
.into(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::ListOf5 => BuiltinFunctionSignature {
name: "builtinListOf".into(),
type_parameters: ["T".into()].into(),
parameters: [
("item0".into(), ParameterType::new("T").into()),
("item1".into(), ParameterType::new("T").into()),
("item2".into(), ParameterType::new("T").into()),
("item3".into(), ParameterType::new("T").into()),
("item4".into(), ParameterType::new("T").into()),
]
.into(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::ListRemoveAt => BuiltinFunctionSignature {
name: "builtinListRemoveAt".into(),
type_parameters: ["T".into()].into(),
parameters: [
(
"list".into(),
NamedType::list(ParameterType::new("T")).into(),
),
("index".into(), NamedType::int().into()),
]
.into(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::ListReplace => BuiltinFunctionSignature {
name: "builtinListReplace".into(),
type_parameters: ["T".into()].into(),
parameters: [
(
"list".into(),
NamedType::list(ParameterType::new("T")).into(),
),
("index".into(), NamedType::int().into()),
("newItem".into(), ParameterType::new("T").into()),
]
.into(),
return_type: NamedType::list(ParameterType::new("T")).into(),
},
Self::Panic => BuiltinFunctionSignature {
name: "builtinPanic".into(),
type_parameters: Box::default(),
Expand Down
56 changes: 42 additions & 14 deletions compiler_v4/src/hir_to_mono.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
ast_to_hir::TypeUnifier,
hir::{self, Hir, NamedType, ParameterType, Type},
hir::{self, BuiltinFunction, Hir, NamedType, ParameterType, Type},
id::IdGenerator,
mono::{self, Mono},
type_solver::{goals::SolverSolution, values::SolverVariable},
Expand Down Expand Up @@ -32,6 +32,7 @@ impl<'h> Context<'h> {
functions: FxHashMap::default(),
};
let main_function = context.lower_function(hir.main_function_id, &FxHashMap::default());
context.lower_function(BuiltinFunction::Panic.id(), &FxHashMap::default());
Mono {
type_declarations: context
.type_declarations
Expand All @@ -56,7 +57,11 @@ impl<'h> Context<'h> {
}

fn lower_assignment(&mut self, id: hir::Id) -> Box<str> {
let assignment = &self.hir.assignments[&id];
let assignment = &self
.hir
.assignments
.get(&id)
.unwrap_or_else(|| panic!("Unknown assignment: {id}"));
let name = assignment.name.to_string().into_boxed_str();
match self.assignments.entry(name.clone()) {
Entry::Occupied(_) => return name.clone(),
Expand All @@ -82,12 +87,16 @@ impl<'h> Context<'h> {
let function = self.hir.functions.get(&id).unwrap_or_else(|| {
let impl_ = self.find_impl_for(id, &substitutions);
let function = &impl_.functions[&id];
if let Type::Parameter(parameter_type) = &impl_.type_ {
let self_type = substitutions[&ParameterType::self_type()].clone();
substitutions
.to_mut()
.force_insert(parameter_type.clone(), self_type);

let mut unifier = TypeUnifier::new(&impl_.type_parameters);
assert!(unifier
.unify(&substitutions[&ParameterType::self_type()], &impl_.type_)
.unwrap());
let substitutions = substitutions.to_mut();
for (parameter_type, type_) in unifier.finish().unwrap() {
substitutions.force_insert(parameter_type, type_);
}

function
});

Expand Down Expand Up @@ -123,7 +132,18 @@ impl<'h> Context<'h> {
let (parameters, _) = BodyBuilder::build(self, &substitutions, |builder| {
builder.add_parameters(&function.signature.parameters);
});
(parameters, mono::BodyOrBuiltin::Builtin(*builtin_function))
(
parameters,
mono::BodyOrBuiltin::Builtin {
builtin_function: *builtin_function,
substitutions: substitutions
.iter()
.map(|(parameter_type, type_)| {
(parameter_type.name.clone(), self.lower_type(type_))
})
.collect(),
},
)
}
};
let return_type = function.signature.return_type.substitute(&substitutions);
Expand Down Expand Up @@ -504,12 +524,20 @@ impl<'c, 'h> BodyBuilder<'c, 'h> {
let enum_ = self.lower_type(enum_);
let cases = cases
.iter()
.map(|case| mono::SwitchCase {
variant: case.variant.clone(),
value_id: case.value_id.map(|id| self.lower_id(id)),
body: BodyBuilder::build_inner(self, |builder| {
builder.lower_expressions(&case.body.expressions);
}),
.map(|case| {
let value_ids = case
.value_id
.map(|hir_id| (hir_id, self.id_generator.generate()));
mono::SwitchCase {
variant: case.variant.clone(),
value_id: value_ids.map(|(_, mir_id)| mir_id),
body: BodyBuilder::build_inner(self, |builder| {
if let Some((hir_id, mir_id)) = value_ids {
builder.id_mapping.force_insert(hir_id, mir_id);
}
builder.lower_expressions(&case.body.expressions);
}),
}
})
.collect();
self.push(
Expand Down
9 changes: 6 additions & 3 deletions compiler_v4/src/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub struct Assignment {
pub body: Body,
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Function {
pub parameters: Box<[Parameter]>,
pub return_type: Box<str>,
Expand All @@ -59,10 +59,13 @@ pub struct Parameter {
pub type_: Box<str>,
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum BodyOrBuiltin {
Body(Body),
Builtin(BuiltinFunction),
Builtin {
builtin_function: BuiltinFunction,
substitutions: FxHashMap<Box<str>, Box<str>>,
},
}
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
pub struct Body {
Expand Down
Loading

0 comments on commit c921c98

Please sign in to comment.