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),
|
Function(Function),
|
||||||
Constant(Constant),
|
Constant(Constant),
|
||||||
Struct(Struct),
|
Struct(Struct),
|
||||||
|
StructImpl(StructImpl),
|
||||||
Module(Module),
|
Module(Module),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,6 +170,14 @@ pub struct Struct {
|
||||||
pub span: Span,
|
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)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
Value(ValueExpr),
|
Value(ValueExpr),
|
||||||
|
|
|
@ -16,6 +16,7 @@ pub struct SymbolTable {
|
||||||
pub symbols: BTreeMap<DefId, String>,
|
pub symbols: BTreeMap<DefId, String>,
|
||||||
pub modules: BTreeMap<String, DefId>,
|
pub modules: BTreeMap<String, DefId>,
|
||||||
pub functions: BTreeMap<String, DefId>,
|
pub functions: BTreeMap<String, DefId>,
|
||||||
|
pub methods: BTreeMap<DefId, BTreeMap<String, DefId>>,
|
||||||
pub constants: BTreeMap<String, DefId>,
|
pub constants: BTreeMap<String, DefId>,
|
||||||
pub structs: BTreeMap<String, DefId>,
|
pub structs: BTreeMap<String, DefId>,
|
||||||
pub types: BTreeMap<String, DefId>,
|
pub types: BTreeMap<String, DefId>,
|
||||||
|
|
|
@ -60,35 +60,104 @@ fn lower_module(
|
||||||
|
|
||||||
// fill fn sigs
|
// fill fn sigs
|
||||||
for content in &module.contents {
|
for content in &module.contents {
|
||||||
if let ModuleStatement::Function(fn_def) = content {
|
match content {
|
||||||
let body = ctx.body.modules.get(&id).unwrap();
|
ModuleStatement::Function(fn_def) => {
|
||||||
let fn_id = *body.symbols.functions.get(&fn_def.name.name).unwrap();
|
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 mut args = Vec::new();
|
||||||
let ret_type;
|
let ret_type;
|
||||||
|
|
||||||
for arg in &fn_def.params {
|
for arg in &fn_def.params {
|
||||||
let ty = lower_type(&ctx, &arg.arg_type, id)?;
|
let ty = lower_type(&ctx, &arg.arg_type, id)?;
|
||||||
args.push(ty);
|
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 {
|
let struct_id = {
|
||||||
ret_type = lower_type(&ctx, ty, id)?;
|
let body = ctx.body.modules.get(&id).unwrap();
|
||||||
} else {
|
*body.symbols.structs.get(&info.name.name).unwrap()
|
||||||
ret_type = TypeInfo {
|
|
||||||
span: None,
|
|
||||||
kind: ir::TypeKind::Unit,
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
for content in &module.contents {
|
||||||
match content {
|
match content {
|
||||||
ModuleStatement::Function(fn_def) => {
|
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::Type(_) => todo!(),
|
||||||
ModuleStatement::Module(mod_def) => {
|
ModuleStatement::Module(mod_def) => {
|
||||||
|
@ -139,16 +208,14 @@ fn lower_function(
|
||||||
ctx: BuildCtx,
|
ctx: BuildCtx,
|
||||||
func: &ast::Function,
|
func: &ast::Function,
|
||||||
module_id: DefId,
|
module_id: DefId,
|
||||||
|
fn_id: DefId,
|
||||||
) -> Result<BuildCtx, LoweringError> {
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
let mut builder = BodyBuilder {
|
let mut builder = BodyBuilder {
|
||||||
body: Body {
|
body: Body {
|
||||||
blocks: Default::default(),
|
blocks: Default::default(),
|
||||||
locals: Default::default(),
|
locals: Default::default(),
|
||||||
name: func.name.name.clone(),
|
name: func.name.name.clone(),
|
||||||
def_id: {
|
def_id: fn_id,
|
||||||
let body = ctx.body.modules.get(&module_id).unwrap();
|
|
||||||
*body.symbols.functions.get(&func.name.name).unwrap()
|
|
||||||
},
|
|
||||||
is_pub: func.is_public,
|
is_pub: func.is_public,
|
||||||
is_extern: func.is_extern,
|
is_extern: func.is_extern,
|
||||||
is_exported: func.is_exported || func.name.name == "main",
|
is_exported: func.is_exported || func.name.name == "main",
|
||||||
|
|
|
@ -71,12 +71,19 @@ pub fn prepass_module(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ast::ModuleStatement::Struct(info) => {
|
ast::ModuleStatement::Struct(info) => {
|
||||||
let next_id = gen.next_defid();
|
if current_module
|
||||||
current_module
|
|
||||||
.symbols
|
.symbols
|
||||||
.structs
|
.structs
|
||||||
.insert(info.name.name.clone(), next_id);
|
.get(&info.name.name)
|
||||||
current_module.structs.insert(next_id);
|
.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) => {
|
ast::ModuleStatement::Type(info) => {
|
||||||
|
@ -96,6 +103,39 @@ pub fn prepass_module(
|
||||||
.insert(info.name.name.clone(), next_id);
|
.insert(info.name.name.clone(), next_id);
|
||||||
current_module.modules.insert(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,12 +212,14 @@ pub fn prepass_sub_module(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ast::ModuleStatement::Struct(info) => {
|
ast::ModuleStatement::Struct(info) => {
|
||||||
let next_id = gen.next_defid();
|
if submodule.symbols.structs.get(&info.name.name).is_none() {
|
||||||
submodule
|
let next_id = gen.next_defid();
|
||||||
.symbols
|
submodule
|
||||||
.structs
|
.symbols
|
||||||
.insert(info.name.name.clone(), next_id);
|
.structs
|
||||||
submodule.structs.insert(next_id);
|
.insert(info.name.name.clone(), next_id);
|
||||||
|
submodule.structs.insert(next_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
ast::ModuleStatement::Type(info) => {
|
ast::ModuleStatement::Type(info) => {
|
||||||
|
@ -197,6 +239,34 @@ pub fn prepass_sub_module(
|
||||||
.insert(info.name.name.clone(), next_id);
|
.insert(info.name.name.clone(), next_id);
|
||||||
submodule.modules.insert(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,
|
"extern" => Token::KeywordExtern,
|
||||||
"as" => Token::KeywordAs,
|
"as" => Token::KeywordAs,
|
||||||
"exported" => Token::KeywordExported,
|
"exported" => Token::KeywordExported,
|
||||||
|
"impl" => Token::KeywordImpl,
|
||||||
|
|
||||||
// literals
|
// literals
|
||||||
"identifier" => Token::Identifier(<String>),
|
"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 = {
|
pub(crate) Import: ast::Import = {
|
||||||
<lo:@L> "use" <module:DoubleColon<Ident>> <symbols:("{" <Comma<Ident>> "}")?> ";" <hi:@R> => ast::Import {
|
<lo:@L> "use" <module:DoubleColon<Ident>> <symbols:("{" <Comma<Ident>> "}")?> ";" <hi:@R> => ast::Import {
|
||||||
module,
|
module,
|
||||||
|
@ -512,5 +522,6 @@ pub(crate) ModuleStatement: ast::ModuleStatement = {
|
||||||
<Function> => ast::ModuleStatement::Function(<>),
|
<Function> => ast::ModuleStatement::Function(<>),
|
||||||
<Constant> => ast::ModuleStatement::Constant(<>),
|
<Constant> => ast::ModuleStatement::Constant(<>),
|
||||||
<Struct> => ast::ModuleStatement::Struct(<>),
|
<Struct> => ast::ModuleStatement::Struct(<>),
|
||||||
|
<StructImpl> => ast::ModuleStatement::StructImpl(<>),
|
||||||
<Module> => ast::ModuleStatement::Module(<>),
|
<Module> => ast::ModuleStatement::Module(<>),
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,8 @@ pub enum Token {
|
||||||
KeywordAs,
|
KeywordAs,
|
||||||
#[token("exported")]
|
#[token("exported")]
|
||||||
KeywordExported,
|
KeywordExported,
|
||||||
|
#[token("impl")]
|
||||||
|
KeywordImpl,
|
||||||
|
|
||||||
// Modern way of allowing identifiers, read: https://unicode.org/reports/tr31/
|
// Modern way of allowing identifiers, read: https://unicode.org/reports/tr31/
|
||||||
#[regex(r"[\p{XID_Start}_]\p{XID_Continue}*", |lex| lex.slice().to_string())]
|
#[regex(r"[\p{XID_Start}_]\p{XID_Continue}*", |lex| lex.slice().to_string())]
|
||||||
|
|
Loading…
Reference in a new issue