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

Union & enum syntax #103

Merged
merged 18 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
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
29 changes: 29 additions & 0 deletions crates/concrete_ast/src/enums.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use crate::{
common::{GenericParam, Ident, Span},
expressions::Expression,
structs::Field,
};

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UnionDecl {
pub name: Ident,
pub generics: Vec<GenericParam>,
pub variants: Vec<Field>,
pub span: Span,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EnumDecl {
pub name: Ident,
pub generics: Vec<GenericParam>,
pub variants: Vec<EnumVariant>,
pub span: Span,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EnumVariant {
pub name: Ident,
pub fields: Vec<Field>,
pub discriminant: Option<Expression>,
pub span: Span,
}
1 change: 1 addition & 0 deletions crates/concrete_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use modules::Module;

pub mod common;
pub mod constants;
pub mod enums;
pub mod expressions;
pub mod functions;
pub mod imports;
Expand Down
3 changes: 3 additions & 0 deletions crates/concrete_ast/src/modules.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
common::{DocString, Ident, Span},
constants::ConstantDef,
enums::{EnumDecl, UnionDecl},
functions::{FunctionDecl, FunctionDef},
imports::ImportStmt,
structs::StructDecl,
Expand All @@ -22,6 +23,8 @@ pub enum ModuleDefItem {
Function(FunctionDef),
FunctionDecl(FunctionDecl),
Struct(StructDecl),
Union(UnionDecl),
Enum(EnumDecl),
Type(TypeDecl),
Module(Module),
}
2 changes: 2 additions & 0 deletions crates/concrete_ir/src/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ fn lower_module(mut ctx: BuildCtx, module: &Module, id: DefId) -> Result<BuildCt
ctx = lower_module(ctx, mod_def, id)?;
}
ModuleDefItem::Struct(_) => { /* already processed */ }
ModuleDefItem::Union(_) => todo!(),
ModuleDefItem::Enum(_) => todo!(),
ModuleDefItem::FunctionDecl(fn_decl) => {
ctx = lower_func_decl(ctx, fn_decl, id)?;
}
Expand Down
4 changes: 4 additions & 0 deletions crates/concrete_ir/src/lowering/prepass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ pub fn prepass_module(
.insert(info.name.name.clone(), next_id);
current_module.modules.insert(next_id);
}
ast::modules::ModuleDefItem::Union(_) => todo!(),
ast::modules::ModuleDefItem::Enum(_) => todo!(),
ast::modules::ModuleDefItem::FunctionDecl(info) => {
let next_id = gen.next_defid();
current_module
Expand Down Expand Up @@ -210,6 +212,8 @@ pub fn prepass_sub_module(
.insert(info.name.name.clone(), next_id);
submodule.modules.insert(next_id);
}
ast::modules::ModuleDefItem::Union(_) => todo!(),
ast::modules::ModuleDefItem::Enum(_) => todo!(),
ast::modules::ModuleDefItem::FunctionDecl(info) => {
let next_id = gen.next_defid();
submodule
Expand Down
37 changes: 37 additions & 0 deletions crates/concrete_parser/src/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ extern {
"fn" => Token::KeywordFn,
"return" => Token::KeywordReturn,
"struct" => Token::KeywordStruct,
"union" => Token::KeywordUnion,
"enum" => Token::KeywordEnum,
"if" => Token::KeywordIf,
"else" => Token::KeywordElse,
"while" => Token::KeywordWhile,
Expand Down Expand Up @@ -243,6 +245,12 @@ pub(crate) ModuleDefItem: ast::modules::ModuleDefItem = {
<StructDef> => {
ast::modules::ModuleDefItem::Struct(<>)
},
<UnionDef> => {
ast::modules::ModuleDefItem::Union(<>)
},
<EnumDef> => {
ast::modules::ModuleDefItem::Enum(<>)
},
<FunctionDef> => {
ast::modules::ModuleDefItem::Function(<>)
},
Expand Down Expand Up @@ -328,6 +336,35 @@ pub(crate) StructDef: ast::structs::StructDecl = {
}
}


pub(crate) UnionDef: ast::enums::UnionDecl = {
<lo:@L> "union" <name:Ident> <generics:GenericParams?> "{" <variants:Comma<StructField>> "}" <hi:@R> => ast::enums::UnionDecl {
name,
variants,
generics: generics.unwrap_or(vec![]),
span: Span::new(lo, hi),
}
}

pub(crate) EnumDef: ast::enums::EnumDecl = {
<lo:@L> "enum" <name:Ident> <generics:GenericParams?> "{" <variants:Comma<EnumVariant>> "}" <hi:@R> => ast::enums::EnumDecl {
name,
variants,
generics: generics.unwrap_or(vec![]),
span: Span::new(lo, hi),
}
}


pub(crate) EnumVariant: ast::enums::EnumVariant = {
<lo:@L> <name:Ident> <fields:("{" <Comma<StructField>> "}")?> <discriminant:("=" <Expression>)?><hi:@R> => ast::enums::EnumVariant {
name,
fields: fields.unwrap_or_default(),
discriminant,
span: Span::new(lo, hi),
}
}

pub(crate) StructInitField: (ast::common::Ident, ast::expressions::StructInitField) = {
<lo:@L> <name:Ident> ":" <value:Expression> <hi:@R> => (name, ast::expressions::StructInitField {
value,
Expand Down
38 changes: 38 additions & 0 deletions crates/concrete_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,44 @@ mod ModuleName {
fn parse_empty_fn() {
let source = r##"mod MyMod {
fn hello() {}
}"##;
let lexer = Lexer::new(source);
let parser = grammar::ProgramParser::new();
parser.parse(lexer).unwrap();
}

#[test]
fn parse_union_declaration() {
let source = r##"mod MyMod {
union Foo {
bar: i32,
baz: i64,
}

fn main() -> i32 {
let mut foo: Foo = Foo { bar: 1 };

// unsafe!
let bar: i32 = foo.bar;
}
}"##;
let lexer = Lexer::new(source);
let parser = grammar::ProgramParser::new();
parser.parse(lexer).unwrap();
}

#[test]
fn parse_enum() {
let source = r##"mod MyMod {
enum Foo {
Bar,
Baz { n1: i32, n2: i32 },
Qux = 3,
}

fn main() -> i32 {
let mut foo: Foo = Foo.Bar;
}
}"##;
let lexer = Lexer::new(source);
let parser = grammar::ProgramParser::new();
Expand Down
4 changes: 4 additions & 0 deletions crates/concrete_parser/src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ pub enum Token {
KeywordReturn,
#[token("struct")]
KeywordStruct,
#[token("union")]
KeywordUnion,
#[token("enum")]
KeywordEnum,
#[token("if")]
KeywordIf,
#[token("else")]
Expand Down
17 changes: 17 additions & 0 deletions examples/enum.con
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
mod EnumExample {
enum Foo {
Bar,
Baz { n1: i32, n2: i32 },
Qux = 3,
}

fn main() -> i32 {
let mut foo: Foo = Foo.Bar;

match foo {
Foo.Bar -> return 1;,
Foo.Baz -> return 2;,
Foo.Qux -> return 3;,
}
}
}
13 changes: 13 additions & 0 deletions examples/union.con
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
mod UnionExample {
union Foo {
bar: i32,
baz: i64,
}

fn main() -> i32 {
let mut foo: Foo = Foo { bar: 1 };

// unsafe!
let bar: i32 = foo.bar;
}
}
Loading