2017-04-06 11:34:31 +03:00
|
|
|
use elements;
|
2017-04-06 18:23:02 +03:00
|
|
|
use super::invoke::{Invoke, Identity};
|
|
|
|
use super::misc::{ValueTypeBuilder, ValueTypesBuilder, OptionalValueTypeBuilder};
|
2017-04-06 11:34:31 +03:00
|
|
|
|
|
|
|
pub enum Signature {
|
|
|
|
TypeReference(u32),
|
|
|
|
Inline(elements::FunctionType),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct SignatureBuilder<F=Identity> {
|
|
|
|
callback: F,
|
2017-04-06 16:00:12 +03:00
|
|
|
signature: elements::FunctionType,
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
|
|
|
|
2017-04-10 13:58:14 +03:00
|
|
|
impl SignatureBuilder {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
SignatureBuilder::with_callback(Identity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
impl<F> SignatureBuilder<F> where F: Invoke<elements::FunctionType> {
|
2017-04-06 11:34:31 +03:00
|
|
|
pub fn with_callback(callback: F) -> Self {
|
|
|
|
SignatureBuilder {
|
|
|
|
callback: callback,
|
2017-04-06 16:00:12 +03:00
|
|
|
signature: elements::FunctionType::default(),
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-06 18:23:02 +03:00
|
|
|
pub fn with_param(mut self, value_type: elements::ValueType) -> Self {
|
2017-04-06 16:00:12 +03:00
|
|
|
self.signature.params_mut().push(value_type);
|
2017-04-06 18:23:02 +03:00
|
|
|
self
|
|
|
|
}
|
2017-04-06 11:34:31 +03:00
|
|
|
|
2017-04-06 18:23:02 +03:00
|
|
|
pub fn with_params(mut self, value_types: Vec<elements::ValueType>) -> Self {
|
|
|
|
self.signature.params_mut().extend(value_types);
|
2017-04-06 11:34:31 +03:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-04-06 18:23:02 +03:00
|
|
|
pub fn with_return_type(mut self, return_type: Option<elements::ValueType>) -> Self {
|
|
|
|
*self.signature.return_type_mut() = return_type;
|
2017-04-06 11:34:31 +03:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-04-06 18:23:02 +03:00
|
|
|
pub fn param(self) -> ValueTypeBuilder<Self> {
|
|
|
|
ValueTypeBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn params(self) -> ValueTypesBuilder<Self> {
|
|
|
|
ValueTypesBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn return_type(self) -> OptionalValueTypeBuilder<Self> {
|
|
|
|
OptionalValueTypeBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
2017-04-06 11:34:31 +03:00
|
|
|
pub fn build(self) -> F::Result {
|
|
|
|
self.callback.invoke(self.signature)
|
|
|
|
}
|
2017-04-10 13:58:14 +03:00
|
|
|
|
|
|
|
pub fn build_sig(self) -> Signature {
|
|
|
|
Signature::Inline(self.signature)
|
|
|
|
}
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
|
|
|
|
2017-04-06 18:23:02 +03:00
|
|
|
impl<F> Invoke<Vec<elements::ValueType>> for SignatureBuilder<F>
|
|
|
|
where F: Invoke<elements::FunctionType>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, args: Vec<elements::ValueType>) -> Self {
|
|
|
|
self.with_params(args)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> Invoke<Option<elements::ValueType>> for SignatureBuilder<F>
|
|
|
|
where F: Invoke<elements::FunctionType>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, arg: Option<elements::ValueType>) -> Self {
|
|
|
|
self.with_return_type(arg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> Invoke<elements::ValueType> for SignatureBuilder<F>
|
|
|
|
where F: Invoke<elements::FunctionType>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, arg: elements::ValueType) -> Self {
|
|
|
|
self.with_param(arg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
pub struct TypeRefBuilder<F=Identity> {
|
|
|
|
callback: F,
|
|
|
|
type_ref: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> TypeRefBuilder<F> where F: Invoke<u32> {
|
|
|
|
pub fn with_callback(callback: F) -> Self {
|
|
|
|
TypeRefBuilder {
|
|
|
|
callback: callback,
|
|
|
|
type_ref: 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn val(mut self, val: u32) -> Self {
|
|
|
|
self.type_ref = val;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build(self) -> F::Result { self.callback.invoke(self.type_ref) }
|
|
|
|
}
|
|
|
|
|
2017-04-07 14:04:27 +03:00
|
|
|
pub struct SignaturesBuilder<F=Identity> {
|
2017-04-06 11:34:31 +03:00
|
|
|
callback: F,
|
|
|
|
section: Vec<Signature>,
|
|
|
|
}
|
|
|
|
|
2017-04-07 14:04:27 +03:00
|
|
|
impl SignaturesBuilder {
|
2017-04-06 11:34:31 +03:00
|
|
|
/// New empty functions section builder
|
|
|
|
pub fn new() -> Self {
|
2017-04-07 14:04:27 +03:00
|
|
|
SignaturesBuilder::with_callback(Identity)
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 14:04:27 +03:00
|
|
|
impl<F> SignaturesBuilder<F> {
|
2017-04-06 11:34:31 +03:00
|
|
|
pub fn with_callback(callback: F) -> Self {
|
2017-04-07 14:04:27 +03:00
|
|
|
SignaturesBuilder {
|
2017-04-06 11:34:31 +03:00
|
|
|
callback: callback,
|
|
|
|
section: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_signature(mut self, signature: Signature) -> Self {
|
|
|
|
self.section.push(signature);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
pub fn type_ref(self) -> TypeRefBuilder<Self> {
|
|
|
|
TypeRefBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 14:04:27 +03:00
|
|
|
impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
|
2017-04-06 11:34:31 +03:00
|
|
|
pub fn signature(self) -> SignatureBuilder<Self> {
|
|
|
|
SignatureBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 14:04:27 +03:00
|
|
|
impl<F> Invoke<elements::FunctionType> for SignaturesBuilder<F> {
|
2017-04-06 16:00:12 +03:00
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, signature: elements::FunctionType) -> Self {
|
|
|
|
self.with_signature(Signature::Inline(signature))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 14:04:27 +03:00
|
|
|
impl<F> Invoke<u32> for SignaturesBuilder<F> {
|
2017-04-06 11:34:31 +03:00
|
|
|
type Result = Self;
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
fn invoke(self, type_ref: u32) -> Self {
|
|
|
|
self.with_signature(Signature::TypeReference(type_ref))
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-03 23:31:38 +03:00
|
|
|
impl<F> SignaturesBuilder<F> where F: Invoke<elements::FunctionSection> {
|
2017-04-06 11:34:31 +03:00
|
|
|
pub fn build(self) -> F::Result {
|
2017-06-03 23:31:38 +03:00
|
|
|
let mut result = elements::FunctionSection::default();
|
2017-04-06 11:34:31 +03:00
|
|
|
for f in self.section.into_iter() {
|
|
|
|
if let Signature::TypeReference(type_ref) = f {
|
|
|
|
result.entries_mut().push(elements::Func::new(type_ref));
|
|
|
|
} else {
|
|
|
|
unreachable!(); // never possible with current generics impl-s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.callback.invoke(result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type SignatureBindings = Vec<Signature>;
|
|
|
|
|
2017-04-07 14:04:27 +03:00
|
|
|
impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
|
2017-04-06 11:34:31 +03:00
|
|
|
pub fn bind(self) -> F::Result {
|
|
|
|
self.callback.invoke(self.section)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 19:48:19 +03:00
|
|
|
pub struct FuncBodyBuilder<F=Identity> {
|
|
|
|
callback: F,
|
2017-04-10 13:11:34 +03:00
|
|
|
body: elements::FuncBody,
|
2017-04-07 19:48:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> FuncBodyBuilder<F> {
|
|
|
|
pub fn with_callback(callback: F) -> Self {
|
|
|
|
FuncBodyBuilder {
|
|
|
|
callback: callback,
|
2017-04-10 13:11:34 +03:00
|
|
|
body: elements::FuncBody::new(Vec::new(), elements::Opcodes::empty()),
|
2017-04-07 19:48:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> FuncBodyBuilder<F> where F: Invoke<elements::FuncBody> {
|
2017-04-10 13:11:34 +03:00
|
|
|
pub fn with_func(mut self, func: elements::FuncBody) -> Self {
|
|
|
|
self.body = func;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-04-07 19:48:19 +03:00
|
|
|
pub fn with_locals(mut self, locals: Vec<elements::Local>) -> Self {
|
2017-04-10 13:11:34 +03:00
|
|
|
self.body.locals_mut().extend(locals);
|
2017-04-07 19:48:19 +03:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_opcodes(mut self, opcodes: elements::Opcodes) -> Self {
|
2017-04-10 13:11:34 +03:00
|
|
|
*self.body.code_mut() = opcodes;
|
2017-04-07 19:48:19 +03:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build(self) -> F::Result {
|
2017-04-10 13:11:34 +03:00
|
|
|
self.callback.invoke(self.body)
|
2017-04-07 19:48:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 15:45:52 +03:00
|
|
|
pub struct FunctionDefinition {
|
2017-04-28 13:34:58 +03:00
|
|
|
pub is_main: bool,
|
2017-04-07 15:45:52 +03:00
|
|
|
pub signature: Signature,
|
|
|
|
pub code: elements::FuncBody,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for FunctionDefinition {
|
|
|
|
fn default() -> Self {
|
|
|
|
FunctionDefinition {
|
2017-04-28 13:34:58 +03:00
|
|
|
is_main: false,
|
2017-04-07 15:45:52 +03:00
|
|
|
signature: Signature::TypeReference(0),
|
|
|
|
code: elements::FuncBody::empty(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct FunctionBuilder<F=Identity> {
|
|
|
|
callback: F,
|
2017-04-07 19:48:19 +03:00
|
|
|
func: FunctionDefinition,
|
2017-04-07 15:45:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FunctionBuilder {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
FunctionBuilder::with_callback(Identity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
|
|
|
|
pub fn with_callback(callback: F) -> Self {
|
|
|
|
FunctionBuilder {
|
|
|
|
callback: callback,
|
2017-04-07 19:48:19 +03:00
|
|
|
func: Default::default(),
|
2017-04-07 15:45:52 +03:00
|
|
|
}
|
|
|
|
}
|
2017-04-07 19:48:19 +03:00
|
|
|
|
2017-04-28 13:34:58 +03:00
|
|
|
pub fn main(mut self) -> Self {
|
|
|
|
self.func.is_main = true;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-04-07 19:48:19 +03:00
|
|
|
pub fn signature(self) -> SignatureBuilder<Self> {
|
|
|
|
SignatureBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_signature(mut self, signature: Signature) -> Self {
|
|
|
|
self.func.signature = signature;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn body(self) -> FuncBodyBuilder<Self> {
|
|
|
|
FuncBodyBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_body(mut self, body: elements::FuncBody) -> Self {
|
|
|
|
self.func.code = body;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build(self) -> F::Result {
|
|
|
|
self.callback.invoke(self.func)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> Invoke<elements::FunctionType> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, signature: elements::FunctionType) -> Self {
|
|
|
|
self.with_signature(Signature::Inline(signature))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> Invoke<u32> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, type_ref: u32) -> Self {
|
|
|
|
self.with_signature(Signature::TypeReference(type_ref))
|
|
|
|
}
|
2017-04-07 15:45:52 +03:00
|
|
|
}
|
|
|
|
|
2017-04-07 19:48:19 +03:00
|
|
|
impl<F> Invoke<elements::FuncBody> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, body: elements::FuncBody) -> Self::Result {
|
|
|
|
self.with_body(body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// New builder of signature list
|
2017-04-07 14:04:27 +03:00
|
|
|
pub fn signatures() -> SignaturesBuilder {
|
|
|
|
SignaturesBuilder::new()
|
2017-04-06 16:00:12 +03:00
|
|
|
}
|
|
|
|
|
2017-04-10 13:58:14 +03:00
|
|
|
/// New signature builder
|
|
|
|
pub fn signature() -> SignatureBuilder {
|
|
|
|
SignatureBuilder::new()
|
|
|
|
}
|
|
|
|
|
2017-04-07 19:48:19 +03:00
|
|
|
/// New builder of function (signature & body)
|
|
|
|
pub fn function() -> FunctionBuilder {
|
|
|
|
FunctionBuilder::new()
|
|
|
|
}
|
|
|
|
|
2017-04-06 11:34:31 +03:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
2017-04-07 19:48:19 +03:00
|
|
|
use super::{signatures, function};
|
|
|
|
use elements;
|
2017-04-06 11:34:31 +03:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn example() {
|
2017-04-07 14:04:27 +03:00
|
|
|
let result = signatures()
|
2017-04-06 16:00:12 +03:00
|
|
|
.type_ref().val(1).build()
|
2017-04-06 11:34:31 +03:00
|
|
|
.build();
|
|
|
|
|
|
|
|
assert_eq!(result.entries().len(), 1);
|
|
|
|
|
2017-04-07 14:04:27 +03:00
|
|
|
let result = signatures()
|
2017-04-06 16:00:12 +03:00
|
|
|
.signature()
|
2017-04-06 18:23:02 +03:00
|
|
|
.param().i32()
|
|
|
|
.param().i32()
|
|
|
|
.return_type().i64()
|
2017-04-06 16:00:12 +03:00
|
|
|
.build()
|
2017-04-06 11:34:31 +03:00
|
|
|
.bind();
|
|
|
|
|
2017-06-27 13:45:33 +03:00
|
|
|
assert_eq!(result.len(), 1);
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
2017-04-07 19:48:19 +03:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn func_example() {
|
|
|
|
let func = function()
|
|
|
|
.signature()
|
|
|
|
.param().i32()
|
|
|
|
.return_type().i32()
|
|
|
|
.build()
|
|
|
|
.body()
|
|
|
|
.with_opcodes(elements::Opcodes::empty())
|
|
|
|
.build()
|
|
|
|
.build();
|
|
|
|
|
|
|
|
assert_eq!(func.code.locals().len(), 0);
|
|
|
|
assert_eq!(func.code.code().elements().len(), 1);
|
|
|
|
}
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|