mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-22 07:58:24 +00:00
impl block
This commit is contained in:
parent
4aa8b2078e
commit
5e40306951
|
@ -16,6 +16,7 @@ pub enum ModuleStatement {
|
|||
Function(Function),
|
||||
Constant(Constant),
|
||||
Struct(Struct),
|
||||
StructImpl(StructImpl),
|
||||
Module(Module),
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -60,7 +60,8 @@ fn lower_module(
|
|||
|
||||
// fill fn sigs
|
||||
for content in &module.contents {
|
||||
if let ModuleStatement::Function(fn_def) = content {
|
||||
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();
|
||||
|
||||
|
@ -83,12 +84,80 @@ fn lower_module(
|
|||
|
||||
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");
|
||||
|
||||
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 {
|
||||
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) => {
|
||||
|
@ -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",
|
||||
|
|
|
@ -71,6 +71,12 @@ pub fn prepass_module(
|
|||
);
|
||||
}
|
||||
ast::ModuleStatement::Struct(info) => {
|
||||
if current_module
|
||||
.symbols
|
||||
.structs
|
||||
.get(&info.name.name)
|
||||
.is_none()
|
||||
{
|
||||
let next_id = gen.next_defid();
|
||||
current_module
|
||||
.symbols
|
||||
|
@ -78,6 +84,7 @@ pub fn prepass_module(
|
|||
.insert(info.name.name.clone(), next_id);
|
||||
current_module.structs.insert(next_id);
|
||||
}
|
||||
}
|
||||
/*
|
||||
ast::ModuleStatement::Type(info) => {
|
||||
let next_id = gen.next_defid();
|
||||
|
@ -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(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,6 +212,7 @@ pub fn prepass_sub_module(
|
|||
);
|
||||
}
|
||||
ast::ModuleStatement::Struct(info) => {
|
||||
if submodule.symbols.structs.get(&info.name.name).is_none() {
|
||||
let next_id = gen.next_defid();
|
||||
submodule
|
||||
.symbols
|
||||
|
@ -179,6 +220,7 @@ pub fn prepass_sub_module(
|
|||
.insert(info.name.name.clone(), next_id);
|
||||
submodule.structs.insert(next_id);
|
||||
}
|
||||
}
|
||||
/*
|
||||
ast::ModuleStatement::Type(info) => {
|
||||
let next_id = gen.next_defid();
|
||||
|
@ -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(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ extern {
|
|||
"extern" => Token::KeywordExtern,
|
||||
"as" => Token::KeywordAs,
|
||||
"exported" => Token::KeywordExported,
|
||||
"impl" => Token::KeywordImpl,
|
||||
|
||||
// literals
|
||||
"identifier" => Token::Identifier(<String>),
|
||||
|
@ -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,
|
||||
|
@ -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(<>),
|
||||
}
|
||||
|
|
|
@ -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())]
|
||||
|
|
Loading…
Reference in a new issue