impl block

This commit is contained in:
Edgar 2024-04-09 12:15:13 +02:00
parent 4aa8b2078e
commit 5e40306951
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
6 changed files with 191 additions and 31 deletions

View file

@ -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),

View file

@ -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>,

View file

@ -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) => {
@ -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",

View file

@ -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) => {
@ -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,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) => {
@ -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(),
),
);
}
}
}
}

View file

@ -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(<>),
}

View file

@ -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())]