Skip to content

Add extern block to codegen #47

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
71 changes: 71 additions & 0 deletions src/extern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use crate::{Formatter, Function};
use std::fmt::Write;
#[derive(Debug, Clone)]
pub enum ExternSymbol {
Function(Function),
}

/// Defines an extern block.
#[derive(Debug, Clone)]
pub struct Extern {
abi: Option<String>,
symbols: Vec<ExternSymbol>
}


impl Extern {

/// Return a new extern block.
pub fn new() -> Self {
Extern {
abi: None,
symbols: Vec::new()
}
}

/// Set the ABI for the extern block.
pub fn abi(&mut self, abi: &str) -> &mut Self {
self.abi = Some(abi.to_string());
self
}

/// Return a new extern function with the given name.
pub fn function(&mut self, name: &str) -> &mut Function {
let function = Function::new(name);
self.symbols.push(ExternSymbol::Function(function));
match self.symbols.last_mut().unwrap() {
ExternSymbol::Function(function) => function.no_body(),
}
}


/// Push a function to the extern block.
pub fn push_function(&mut self, function: Function) -> &mut Self {
assert!(function.body.is_none(), "Extern functions cannot have bodies");
self.symbols.push(ExternSymbol::Function(function));
self
}


/// Formats the extern block using the given formatter.
pub fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
if let Some(abi) = &self.abi {
writeln!(f, "extern \"{}\"", abi)?;
} else {
writeln!(f, "extern ")?;
}

f.block(|x| {
let mut res = Ok(());
for symbol in &self.symbols {
match symbol {
ExternSymbol::Function(function) => {
res = function.fmt(true, x)
}
}
}

res
})
}
}
6 changes: 6 additions & 0 deletions src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ impl Function {
self
}

/// Remove the function body.
pub fn no_body(&mut self) -> &mut Self {
self.body = None;
self
}

/// Add a `where` bound to the function.
pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
where
Expand Down
2 changes: 2 additions & 0 deletions src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::function::Function;
use crate::module::Module;

use crate::r#enum::Enum;
use crate::r#extern::Extern;
use crate::r#impl::Impl;
use crate::r#struct::Struct;
use crate::r#trait::Trait;
Expand All @@ -11,6 +12,7 @@ pub enum Item {
Module(Module),
Struct(Struct),
Function(Function),
Extern(Extern),
Trait(Trait),
Enum(Enum),
Impl(Impl),
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ mod r#impl;
mod r#struct;
mod r#trait;
mod r#type;

mod r#extern;

pub use associated_type::*;
pub use block::*;
Expand Down
18 changes: 18 additions & 0 deletions src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::item::Item;
use crate::module::Module;

use crate::r#enum::Enum;
use crate::r#extern::Extern;
use crate::r#impl::Impl;
use crate::r#struct::Struct;
use crate::r#trait::Trait;
Expand Down Expand Up @@ -163,6 +164,22 @@ impl Scope {
self
}

/// Push a new extern definition, returning a mutable reference to it.
pub fn new_extern(&mut self) -> &mut Extern {
self.items.push(Item::Extern(Extern::new()));

match *self.items.last_mut().unwrap() {
Item::Extern(ref mut v) => v,
_ => unreachable!(),
}
}

/// Push an extern definition
pub fn push_extern(&mut self, item: Extern) -> &mut Self {
self.items.push(Item::Extern(item));
self
}

/// Push a new trait definition, returning a mutable reference to it.
pub fn new_trait(&mut self, name: &str) -> &mut Trait {
self.push_trait(Trait::new(name));
Expand Down Expand Up @@ -253,6 +270,7 @@ impl Scope {
Item::Trait(ref v) => v.fmt(fmt)?,
Item::Enum(ref v) => v.fmt(fmt)?,
Item::Impl(ref v) => v.fmt(fmt)?,
Item::Extern(ref v) => v.fmt(fmt)?,
Item::Raw(ref v) => {
write!(fmt, "{}\n", v)?;
}
Expand Down