Skip to content

Commit

Permalink
impl block
Browse files Browse the repository at this point in the history
  • Loading branch information
edg-l committed Apr 9, 2024
1 parent 4aa8b20 commit 5e40306
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 31 deletions.
9 changes: 9 additions & 0 deletions lib/edlang_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum ModuleStatement {
Function(Function),
Constant(Constant),
Struct(Struct),
StructImpl(StructImpl),
Module(Module),
}

Expand Down Expand Up @@ -169,6 +170,14 @@ pub struct Struct {
pub span: Span,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StructImpl {
pub name: Ident,
pub generics: Vec<Type>,
pub methods: Vec<Function>,
pub span: Span,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Expression {
Value(ValueExpr),
Expand Down
1 change: 1 addition & 0 deletions lib/edlang_ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub struct SymbolTable {
pub symbols: BTreeMap<DefId, String>,
pub modules: BTreeMap<String, DefId>,
pub functions: BTreeMap<String, DefId>,
pub methods: BTreeMap<DefId, BTreeMap<String, DefId>>,
pub constants: BTreeMap<String, DefId>,
pub structs: BTreeMap<String, DefId>,
pub types: BTreeMap<String, DefId>,
Expand Down
109 changes: 88 additions & 21 deletions lib/edlang_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,35 +60,104 @@ fn lower_module(

// fill fn sigs
for content in &module.contents {
if let ModuleStatement::Function(fn_def) = content {
let body = ctx.body.modules.get(&id).unwrap();
let fn_id = *body.symbols.functions.get(&fn_def.name.name).unwrap();
match content {
ModuleStatement::Function(fn_def) => {
let body = ctx.body.modules.get(&id).unwrap();
let fn_id = *body.symbols.functions.get(&fn_def.name.name).unwrap();

let mut args = Vec::new();
let ret_type;

let mut args = Vec::new();
let ret_type;
for arg in &fn_def.params {
let ty = lower_type(&ctx, &arg.arg_type, id)?;
args.push(ty);
}

for arg in &fn_def.params {
let ty = lower_type(&ctx, &arg.arg_type, id)?;
args.push(ty);
if let Some(ty) = &fn_def.return_type {
ret_type = lower_type(&ctx, ty, id)?;
} else {
ret_type = TypeInfo {
span: None,
kind: ir::TypeKind::Unit,
};
}

ctx.body.function_signatures.insert(fn_id, (args, ret_type));
}
ModuleStatement::StructImpl(info) => {
// todo: handle generics
assert!(info.generics.is_empty(), "generics not yet implemented");

if let Some(ty) = &fn_def.return_type {
ret_type = lower_type(&ctx, ty, id)?;
} else {
ret_type = TypeInfo {
span: None,
kind: ir::TypeKind::Unit,
let struct_id = {
let body = ctx.body.modules.get(&id).unwrap();
*body.symbols.structs.get(&info.name.name).unwrap()
};
}

ctx.body.function_signatures.insert(fn_id, (args, ret_type));
for fn_def in &info.methods {
let body = ctx.body.modules.get(&id).unwrap();

let fn_id = *body
.symbols
.methods
.get(&struct_id)
.expect("struct id not found")
.get(&fn_def.name.name)
.expect("struct method not found");

let mut args = Vec::new();
let ret_type;

for arg in &fn_def.params {
let ty = lower_type(&ctx, &arg.arg_type, id)?;
args.push(ty);
}

if let Some(ty) = &fn_def.return_type {
ret_type = lower_type(&ctx, ty, id)?;
} else {
ret_type = TypeInfo {
span: None,
kind: ir::TypeKind::Unit,
};
}

ctx.body.function_signatures.insert(fn_id, (args, ret_type));
}
}
_ => {}
}
}

for content in &module.contents {
match content {
ModuleStatement::Function(fn_def) => {
ctx = lower_function(ctx, fn_def, id)?;
let fn_id = {
let body = ctx.body.modules.get(&id).unwrap();
*body.symbols.functions.get(&fn_def.name.name).unwrap()
};
ctx = lower_function(ctx, fn_def, id, fn_id)?;
}
ModuleStatement::StructImpl(info) => {
let struct_id = {
let body = ctx.body.modules.get(&id).unwrap();
*body.symbols.structs.get(&info.name.name).unwrap()
};

for fn_def in &info.methods {
// todo: handle generics
assert!(info.generics.is_empty(), "generics not yet implemented");
let fn_id = {
let body = ctx.body.modules.get(&id).unwrap();
*body
.symbols
.methods
.get(&struct_id)
.unwrap()
.get(&fn_def.name.name)
.unwrap()
};
ctx = lower_function(ctx, fn_def, id, fn_id)?;
}
}
// ModuleStatement::Type(_) => todo!(),
ModuleStatement::Module(mod_def) => {
Expand Down Expand Up @@ -139,16 +208,14 @@ fn lower_function(
ctx: BuildCtx,
func: &ast::Function,
module_id: DefId,
fn_id: DefId,
) -> Result<BuildCtx, LoweringError> {
let mut builder = BodyBuilder {
body: Body {
blocks: Default::default(),
locals: Default::default(),
name: func.name.name.clone(),
def_id: {
let body = ctx.body.modules.get(&module_id).unwrap();
*body.symbols.functions.get(&func.name.name).unwrap()
},
def_id: fn_id,
is_pub: func.is_public,
is_extern: func.is_extern,
is_exported: func.is_exported || func.name.name == "main",
Expand Down
90 changes: 80 additions & 10 deletions lib/edlang_lowering/src/prepass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,19 @@ pub fn prepass_module(
);
}
ast::ModuleStatement::Struct(info) => {
let next_id = gen.next_defid();
current_module
if current_module
.symbols
.structs
.insert(info.name.name.clone(), next_id);
current_module.structs.insert(next_id);
.get(&info.name.name)
.is_none()
{
let next_id = gen.next_defid();
current_module
.symbols
.structs
.insert(info.name.name.clone(), next_id);
current_module.structs.insert(next_id);
}
}
/*
ast::ModuleStatement::Type(info) => {
Expand All @@ -96,6 +103,39 @@ pub fn prepass_module(
.insert(info.name.name.clone(), next_id);
current_module.modules.insert(next_id);
}
ast::ModuleStatement::StructImpl(info) => {
if current_module
.symbols
.structs
.get(&info.name.name)
.is_none()
{
let next_id = gen.next_defid();
current_module
.symbols
.structs
.insert(info.name.name.clone(), next_id);
current_module.structs.insert(next_id);
}

let struct_id = *current_module.symbols.structs.get(&info.name.name).unwrap();

for method in &info.methods {
let next_id = gen.next_defid();
let struct_methods =
current_module.symbols.methods.entry(struct_id).or_default();
current_module.functions.insert(next_id);
struct_methods.insert(method.name.name.clone(), next_id);

ctx.unresolved_function_signatures.insert(
next_id,
(
method.params.iter().map(|x| &x.arg_type).cloned().collect(),
method.return_type.clone(),
),
);
}
}
}
}

Expand Down Expand Up @@ -172,12 +212,14 @@ pub fn prepass_sub_module(
);
}
ast::ModuleStatement::Struct(info) => {
let next_id = gen.next_defid();
submodule
.symbols
.structs
.insert(info.name.name.clone(), next_id);
submodule.structs.insert(next_id);
if submodule.symbols.structs.get(&info.name.name).is_none() {
let next_id = gen.next_defid();
submodule
.symbols
.structs
.insert(info.name.name.clone(), next_id);
submodule.structs.insert(next_id);
}
}
/*
ast::ModuleStatement::Type(info) => {
Expand All @@ -197,6 +239,34 @@ pub fn prepass_sub_module(
.insert(info.name.name.clone(), next_id);
submodule.modules.insert(next_id);
}
ast::ModuleStatement::StructImpl(info) => {
if submodule.symbols.structs.get(&info.name.name).is_none() {
let next_id = gen.next_defid();
submodule
.symbols
.structs
.insert(info.name.name.clone(), next_id);
submodule.structs.insert(next_id);
}

let struct_id = *submodule.symbols.structs.get(&info.name.name).unwrap();

for method in &info.methods {
let next_id = gen.next_defid();
let struct_methods =
submodule.symbols.methods.entry(struct_id).or_default();
submodule.functions.insert(next_id);
struct_methods.insert(method.name.name.clone(), next_id);

ctx.unresolved_function_signatures.insert(
next_id,
(
method.params.iter().map(|x| &x.arg_type).cloned().collect(),
method.return_type.clone(),
),
);
}
}
}
}

Expand Down
11 changes: 11 additions & 0 deletions lib/edlang_parser/src/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern {
"extern" => Token::KeywordExtern,
"as" => Token::KeywordAs,
"exported" => Token::KeywordExported,
"impl" => Token::KeywordImpl,

// literals
"identifier" => Token::Identifier(<String>),
Expand Down Expand Up @@ -473,6 +474,15 @@ pub(crate) Struct: ast::Struct = {
}
}

pub StructImpl: ast::StructImpl = {
<lo:@L> "impl" <name:Ident> <generics:("<" <Comma<Type>> ">")?> "{" <methods:List<Function>?> "}" <hi:@R> => ast::StructImpl {
name,
methods: methods.unwrap_or(vec![]),
generics: generics.unwrap_or(vec![]),
span: ast::Span::new(lo, hi),
}
}

pub(crate) Import: ast::Import = {
<lo:@L> "use" <module:DoubleColon<Ident>> <symbols:("{" <Comma<Ident>> "}")?> ";" <hi:@R> => ast::Import {
module,
Expand Down Expand Up @@ -512,5 +522,6 @@ pub(crate) ModuleStatement: ast::ModuleStatement = {
<Function> => ast::ModuleStatement::Function(<>),
<Constant> => ast::ModuleStatement::Constant(<>),
<Struct> => ast::ModuleStatement::Struct(<>),
<StructImpl> => ast::ModuleStatement::StructImpl(<>),
<Module> => ast::ModuleStatement::Module(<>),
}
2 changes: 2 additions & 0 deletions lib/edlang_parser/src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub enum Token {
KeywordAs,
#[token("exported")]
KeywordExported,
#[token("impl")]
KeywordImpl,

// Modern way of allowing identifiers, read: https://unicode.org/reports/tr31/
#[regex(r"[\p{XID_Start}_]\p{XID_Continue}*", |lex| lex.slice().to_string())]
Expand Down

0 comments on commit 5e40306

Please sign in to comment.