Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic types #6

Merged
merged 3 commits into from
Jun 24, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Generic type
Rigidity committed Jun 23, 2024
commit 9a78b6fdfed0c0b359825a41940dada6b3f59f35
2 changes: 2 additions & 0 deletions crates/rue-compiler/src/compiler.rs
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ mod block;
mod builtins;
mod context;
mod expr;
mod generic_types;
mod item;
mod path;
mod stmt;
@@ -165,6 +166,7 @@ impl<'a> Compiler<'a> {

let name = match self.db.ty(ty) {
Type::Unknown => "{unknown}".to_string(),
Type::Generic => "{generic}".to_string(),
Type::Nil => "Nil".to_string(),
Type::Any => "Any".to_string(),
Type::Int => "Int".to_string(),
3 changes: 3 additions & 0 deletions crates/rue-compiler/src/compiler/generic_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use super::Compiler;

impl Compiler<'_> {}
2 changes: 1 addition & 1 deletion crates/rue-compiler/src/compiler/ty/function_type.rs
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ impl Compiler<'_> {
}

let return_type = function
.ret()
.return_type()
.map_or(self.builtins.unknown, |ty| self.compile_type(ty));

self.db.alloc_type(Type::Function(FunctionType {
16 changes: 16 additions & 0 deletions crates/rue-compiler/src/database/type_system.rs
Original file line number Diff line number Diff line change
@@ -59,6 +59,10 @@ impl Database {
// However, anything can be assigned to `Any` implicitly.
(_, Type::Any) => Comparison::Assignable,

// `Generic` types are unrelated to everything else except their specific instance.
// The only exception is the `Any` type above.
(Type::Generic, _) | (_, Type::Generic) => Comparison::Unrelated,

// You have to explicitly convert between other atom types.
// This is because the compiled output can change depending on the type.
(Type::Int, Type::Bytes) => Comparison::Castable,
@@ -234,6 +238,7 @@ impl Database {
| Type::EnumVariant(..)
| Type::Function(..)
| Type::Unknown
| Type::Generic
| Type::Nil
| Type::Any
| Type::Int
@@ -291,6 +296,17 @@ mod tests {
assert_eq!(db.compare_type(int_alias, double_alias), Comparison::Equal);
}

#[test]
fn test_generic_type() {
let (mut db, ty) = setup();
let a = db.alloc_type(Type::Generic);
let b = db.alloc_type(Type::Generic);
assert_eq!(db.compare_type(a, b), Comparison::Unrelated);
assert_eq!(db.compare_type(a, ty.int), Comparison::Unrelated);
assert_eq!(db.compare_type(ty.int, a), Comparison::Unrelated);
assert_eq!(db.compare_type(a, a), Comparison::Equal);
}

#[test]
fn test_any_type() {
let (db, ty) = setup();
1 change: 1 addition & 0 deletions crates/rue-compiler/src/ty.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ use crate::{
#[derive(Debug, Clone)]
pub enum Type {
Unknown,
Generic,
Nil,
Any,
Int,
18 changes: 17 additions & 1 deletion crates/rue-parser/src/ast.rs
Original file line number Diff line number Diff line change
@@ -143,6 +143,8 @@ ast_node!(RaiseStmt);
ast_node!(AssertStmt);
ast_node!(AssumeStmt);

ast_node!(GenericTypes);

impl Root {
pub fn items(&self) -> Vec<Item> {
self.syntax().children().filter_map(Item::cast).collect()
@@ -191,6 +193,10 @@ impl FunctionItem {
.find(|token| token.kind() == SyntaxKind::Ident)
}

pub fn generic_types(&self) -> Option<GenericTypes> {
self.syntax().children().find_map(GenericTypes::cast)
}

pub fn params(&self) -> Vec<FunctionParam> {
self.syntax()
.children()
@@ -826,7 +832,7 @@ impl FunctionType {
.collect()
}

pub fn ret(&self) -> Option<Type> {
pub fn return_type(&self) -> Option<Type> {
self.syntax().children().find_map(Type::cast)
}
}
@@ -849,3 +855,13 @@ impl OptionalType {
self.syntax().children().find_map(Type::cast)
}
}

impl GenericTypes {
pub fn idents(&self) -> Vec<SyntaxToken> {
self.syntax()
.children_with_tokens()
.filter_map(SyntaxElement::into_token)
.filter(|token| token.kind() == SyntaxKind::Ident)
.collect()
}
}
16 changes: 16 additions & 0 deletions crates/rue-parser/src/grammar.rs
Original file line number Diff line number Diff line change
@@ -66,6 +66,9 @@ fn function_item(p: &mut Parser<'_>, cp: Checkpoint) {
p.start_at(cp, SyntaxKind::FunctionItem);
p.expect(SyntaxKind::Fun);
p.expect(SyntaxKind::Ident);
if p.at(SyntaxKind::LessThan) {
generic_types(p);
}
function_params(p);
p.expect(SyntaxKind::Arrow);
ty(p);
@@ -591,3 +594,16 @@ fn function_type_param(p: &mut Parser<'_>) {
ty(p);
p.finish();
}

fn generic_types(p: &mut Parser<'_>) {
p.start(SyntaxKind::GenericTypes);
p.expect(SyntaxKind::LessThan);
while !p.at(SyntaxKind::GreaterThan) {
p.expect(SyntaxKind::Ident);
if !p.try_eat(SyntaxKind::Comma) {
break;
}
}
p.expect(SyntaxKind::GreaterThan);
p.finish();
}
4 changes: 4 additions & 0 deletions crates/rue-parser/src/syntax_kind.rs
Original file line number Diff line number Diff line change
@@ -125,6 +125,8 @@ pub enum SyntaxKind {
FunctionType,
FunctionTypeParam,
OptionalType,

GenericTypes,
}

impl fmt::Display for SyntaxKind {
@@ -239,6 +241,8 @@ impl fmt::Display for SyntaxKind {
Self::FunctionType => "function type",
Self::FunctionTypeParam => "function type parameter",
Self::OptionalType => "optional type",

Self::GenericTypes => "generic types",
}
)
}