From 21ff1509f6c11e8fb41e1ca233c393dc9e030dab Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 15 May 2017 13:58:55 +0300 Subject: [PATCH] user-functions initial --- src/interpreter/env.rs | 68 ++++++++++++++++++++++++++------------ src/interpreter/program.rs | 14 ++++++-- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/interpreter/env.rs b/src/interpreter/env.rs index a58a11d..bf4bc73 100644 --- a/src/interpreter/env.rs +++ b/src/interpreter/env.rs @@ -1,4 +1,6 @@ use std::sync::{Arc, Weak}; +use std::collections::HashMap; + use builder::module; use elements::{Module, FunctionType, ExportEntry, Internal, GlobalEntry, GlobalType, ValueType, InitExpr, Opcode, Opcodes}; @@ -67,6 +69,19 @@ const INDEX_FUNC_MIN_NONUSED: u32 = 7; /// Max index of reserved function. const INDEX_FUNC_MAX: u32 = 10000; +/// Set of user-defined functions +pub type UserFunctions = HashMap; + +/// User function closure +pub type UserFunctionClosure = Box Result, Error>>; + +/// Signature of user-defined env function +pub struct UserFunction { + params: Vec, + result: Option, + closure: UserFunctionClosure, +} + /// Environment parameters. pub struct EnvParams { /// Stack size in bytes. @@ -77,17 +92,21 @@ pub struct EnvParams { pub allow_memory_growth: bool, } +type UserFunctionsInternals = HashMap; + pub struct EnvModuleInstance { _params: EnvParams, + user_functions: UserFunctionsInternals, instance: ModuleInstance, } impl EnvModuleInstance { - pub fn new(params: EnvParams, module: Module) -> Result { + pub fn new(params: EnvParams, user_functions: UserFunctionsInternals, module: Module) -> Result { let instance = ModuleInstance::new(Weak::default(), module)?; Ok(EnvModuleInstance { _params: params, + user_functions: user_functions, instance: instance, }) } @@ -157,12 +176,12 @@ impl ModuleInstanceInterface for EnvModuleInstance { } } -pub fn env_module() -> Result { - let env_params = EnvParams::default(); +pub fn env_module(user_functions: UserFunctions) -> Result { + let mut env_params = EnvParams::default(); debug_assert!(env_params.total_stack < env_params.total_memory); debug_assert!((env_params.total_stack % LINEAR_MEMORY_PAGE_SIZE) == 0); debug_assert!((env_params.total_memory % LINEAR_MEMORY_PAGE_SIZE) == 0); - let module = module() + let mut module = module() // memory regions .memory() .with_min(env_params.total_memory / LINEAR_MEMORY_PAGE_SIZE) @@ -214,25 +233,32 @@ pub fn env_module() -> Result { .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build() .build() .with_export(ExportEntry::new("getTotalMemory".into(), Internal::Function(INDEX_FUNC_GET_TOTAL_MEMORY))) - // non-standard functions (TODO: pass as parameters to EnvModuleInstance) - .function() - .signature().param().i32().build() - .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build() - .build() - .with_export(ExportEntry::new("gas".into(), Internal::Function(INDEX_FUNC_MAX + 1))) - .function() - .signature().return_type().i32().build() - .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build() - .build() - .with_export(ExportEntry::new("_storage_size".into(), Internal::Function(INDEX_FUNC_MAX + 2))) - .function() - .signature().param().i32().param().i32().param().i32().return_type().i32().build() - .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build() - .build() - .with_export(ExportEntry::new("_storage_write".into(), Internal::Function(INDEX_FUNC_MAX + 3))) .build(); + // non-standard functions (TODO: pass as parameters to EnvModuleInstance) + // .function() + // .signature().param().i32().build() + // .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build() + // .build() + // .with_export(ExportEntry::new("gas".into(), Internal::Function(INDEX_FUNC_MAX + 1))) + // .function() + // .signature().return_type().i32().build() + // .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build() + // .build() + // .with_export(ExportEntry::new("_storage_size".into(), Internal::Function(INDEX_FUNC_MAX + 2))) + // .function() + // .signature().param().i32().param().i32().param().i32().return_type().i32().build() + // .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build() + // .build() + // .with_export(ExportEntry::new("_storage_write".into(), Internal::Function(INDEX_FUNC_MAX + 3))) + // .build(); - EnvModuleInstance::new(env_params, module) + let mut funcs = user_functions; + let internals = HashMap::new(); + for (func_name, func) in funcs.drain() { + + } + + EnvModuleInstance::new(env_params, internals, module) } impl Default for EnvParams { diff --git a/src/interpreter/program.rs b/src/interpreter/program.rs index 87acc64..02331e2 100644 --- a/src/interpreter/program.rs +++ b/src/interpreter/program.rs @@ -4,7 +4,7 @@ use std::collections::hash_map::Entry; use parking_lot::RwLock; use elements::Module; use interpreter::Error; -use interpreter::env::env_module; +use interpreter::env::{self, env_module}; use interpreter::module::{ModuleInstance, ModuleInstanceInterface}; /// Program instance. Program is a set of instantiated modules. @@ -27,6 +27,12 @@ impl ProgramInstance { }) } + pub fn with_functions(funcs: env::UserFunctions) -> Result { + Ok(ProgramInstance { + essence: Arc::new(ProgramInstanceEssence::with_functions(funcs)?), + }) + } + /// Instantiate module. pub fn add_module(&self, name: &str, module: Module) -> Result, Error> { let module_instance = Arc::new(ModuleInstance::new(Arc::downgrade(&self.essence), module)?); @@ -49,8 +55,12 @@ impl ProgramInstance { impl ProgramInstanceEssence { /// Create new program essence. pub fn new() -> Result { + ProgramInstanceEssence::with_functions(HashMap::with_capacity(0)) + } + + pub fn with_functions(funcs: env::UserFunctions) -> Result { let mut modules = HashMap::new(); - let env_module: Arc = Arc::new(env_module()?); + let env_module: Arc = Arc::new(env_module(funcs)?); modules.insert("env".into(), env_module); Ok(ProgramInstanceEssence { modules: RwLock::new(modules),