From ca503f6a1c8481afef9c7da9a7031c9695181675 Mon Sep 17 00:00:00 2001 From: Richard Kiss Date: Fri, 20 Aug 2021 19:18:31 -0700 Subject: [PATCH] First crack at `Dialect`. --- src/chia_dialect_factory.rs | 90 +++++++++++++++++++++++++++++++++++++ src/dialect.rs | 55 +++++++++++++++++++++++ src/lib.rs | 28 ++++++------ src/run_program.rs | 4 +- 4 files changed, 161 insertions(+), 16 deletions(-) create mode 100644 src/chia_dialect_factory.rs create mode 100644 src/dialect.rs diff --git a/src/chia_dialect_factory.rs b/src/chia_dialect_factory.rs new file mode 100644 index 00000000..a36d2db0 --- /dev/null +++ b/src/chia_dialect_factory.rs @@ -0,0 +1,90 @@ +use std::collections::HashMap; + +use crate::allocator::{Allocator, NodePtr}; +use crate::cost::Cost; +use crate::dialect::Dialect; +use crate::err_utils::err; +use crate::f_table::{f_lookup_for_hashmap, FLookup}; +use crate::more_ops::op_unknown; +use crate::reduction::Response; +use crate::run_program::OperatorHandler; + +const QUOTE_KW: [u8; 1] = [1]; +const APPLY_KW: [u8; 1] = [2]; + +pub fn chia_op_handler(strict: bool) -> Box { + let f_lookup: FLookup = f_lookup_for_hashmap(chia_opcode_mapping()); + + Box::new(OperatorHandlerWithMode { f_lookup, strict }) +} + +pub fn chia_dialect(strict: bool) -> Dialect { + Dialect::new("E_KW, &APPLY_KW, chia_op_handler(strict)) +} + +pub struct OperatorHandlerWithMode { + f_lookup: FLookup, + strict: bool, +} + +impl OperatorHandler for OperatorHandlerWithMode { + fn op( + &self, + allocator: &mut Allocator, + o: NodePtr, + argument_list: NodePtr, + max_cost: Cost, + ) -> Response { + let b = &allocator.atom(o); + if b.len() == 1 { + if let Some(f) = self.f_lookup[b[0] as usize] { + return f(allocator, argument_list, max_cost); + } + } + if self.strict { + err(o, "unimplemented operator") + } else { + op_unknown(allocator, o, argument_list, max_cost) + } + } +} + +pub fn chia_opcode_mapping() -> HashMap> { + let mut h = HashMap::new(); + let items = [ + (3, "op_if"), + (4, "op_cons"), + (5, "op_first"), + (6, "op_rest"), + (7, "op_list"), + (8, "op_raise"), + (9, "op_eq"), + (10, "op_gr_bytes"), + (11, "op_sha256"), + (12, "op_substr"), + (13, "op_strlen"), + (14, "op_concat"), + (16, "op_add"), + (17, "op_subtract"), + (18, "op_multiply"), + (19, "op_divide"), + (20, "op_divmod"), + (21, "op_greater"), + (22, "op_ash"), + (23, "op_lsh"), + (24, "op_logand"), + (25, "op_logior"), + (26, "op_logxor"), + (27, "op_lognot"), + (29, "op_point_add"), + (30, "op_pubkey_for_exp"), + (32, "op_not"), + (33, "op_any"), + (34, "op_all"), + (36, "op_softfork"), + ]; + for (k, v) in items { + h.insert(v.to_string(), [k as u8].into()); + } + h +} diff --git a/src/dialect.rs b/src/dialect.rs new file mode 100644 index 00000000..84cf1a81 --- /dev/null +++ b/src/dialect.rs @@ -0,0 +1,55 @@ +use crate::allocator::{Allocator, NodePtr}; +use crate::cost::Cost; +use crate::reduction::Response; +use crate::run_program::{OperatorHandler, PreEval, RunProgramContext}; + +pub struct Dialect { + quote_kw: Vec, + apply_kw: Vec, + op_handler: Box, +} + +impl OperatorHandler for Dialect { + fn op( + &self, + allocator: &mut Allocator, + op: NodePtr, + args: NodePtr, + max_cost: Cost, + ) -> Response { + self.op_handler.op(allocator, op, args, max_cost) + } +} + +impl Dialect { + pub fn new(quote_kw: &[u8], apply_kw: &[u8], op_handler: Box) -> Self { + Dialect { + quote_kw: quote_kw.to_owned(), + apply_kw: apply_kw.to_owned(), + op_handler, + } + } + + pub fn run_program_with_pre_eval( + &self, + allocator: &mut Allocator, + program: NodePtr, + args: NodePtr, + max_cost: Cost, + pre_eval: Option, + ) -> Response { + let mut rpc = + RunProgramContext::new(allocator, &self.quote_kw, &self.apply_kw, self, pre_eval); + rpc.run_program(program, args, max_cost) + } + + pub fn run_program( + &self, + allocator: &mut Allocator, + program: NodePtr, + args: NodePtr, + max_cost: Cost, + ) -> Response { + self.run_program_with_pre_eval(allocator, program, args, max_cost, None) + } +} diff --git a/src/lib.rs b/src/lib.rs index 936e7bfb..1ed2a712 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,19 +1,21 @@ -mod allocator; -mod core_ops; -mod cost; -mod err_utils; -mod f_table; +pub mod allocator; +pub mod chia_dialect_factory; +pub mod core_ops; +pub mod cost; +pub mod dialect; +pub mod err_utils; +pub mod f_table; mod gen; -mod int_to_bytes; -mod more_ops; -mod node; -mod number; -mod op_utils; +pub mod int_to_bytes; +pub mod more_ops; +pub mod node; +pub mod number; +pub mod op_utils; #[cfg(not(any(test, target_family = "wasm")))] mod py; -mod reduction; -mod run_program; -mod serialize; +pub mod reduction; +pub mod run_program; +pub mod serialize; mod sha2; #[cfg(test)] diff --git a/src/run_program.rs b/src/run_program.rs index 1c5846da..abf2f9f5 100644 --- a/src/run_program.rs +++ b/src/run_program.rs @@ -142,7 +142,7 @@ fn augment_cost_errors(r: Result, max_cost: NodePtr) -> Result RunProgramContext<'a> { - fn new( + pub fn new( allocator: &'a mut Allocator, quote_kw: &'a [u8], apply_kw: &'a [u8], @@ -178,9 +178,7 @@ impl<'a> RunProgramContext<'a> { self.push(p); Ok(0) } -} -impl<'a> RunProgramContext<'a> { fn eval_op_atom( &mut self, op_buf: &AtomBuf,