From f6b5965cf132c7ab2473ba2ae4ae4a93148a043d Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Mon, 17 Apr 2023 14:12:29 +0900 Subject: [PATCH 01/11] added macro to generate ruleset ir --- Cargo.toml | 1 + rula-exec/src/ruleset_gen/condition.rs | 2 +- rula-exec/src/ruleset_gen/conf_parser.rs | 6 +-- rula-exec/src/ruleset_gen/types.rs | 8 ++-- rula-lib/src/prelude.rs | 4 +- rula-parser/src/lib.rs | 2 - rula/src/main.rs | 3 ++ ruleset-ir/Cargo.toml | 8 ++++ ruleset-ir/src/instructions.rs | 5 ++ ruleset-ir/src/lib.rs | 58 ++++++++++++++++++++++++ 10 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 ruleset-ir/Cargo.toml create mode 100644 ruleset-ir/src/instructions.rs create mode 100644 ruleset-ir/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index efe3d5d..23e6373 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ members = [ "rula-lib", "rula-parser", "rula-exec", + "ruleset-ir", "tests-e2e" ] \ No newline at end of file diff --git a/rula-exec/src/ruleset_gen/condition.rs b/rula-exec/src/ruleset_gen/condition.rs index d5f44e0..44f3955 100644 --- a/rula-exec/src/ruleset_gen/condition.rs +++ b/rula-exec/src/ruleset_gen/condition.rs @@ -1,6 +1,6 @@ use super::ruleset::{PartnerAddr, ProtocolMessages}; -use serde::{Deserialize, Serialize}; use crate::ruleset_gen::ruleset::AddressKind; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] pub struct Condition { diff --git a/rula-exec/src/ruleset_gen/conf_parser.rs b/rula-exec/src/ruleset_gen/conf_parser.rs index 6ed16f9..7b6e11f 100644 --- a/rula-exec/src/ruleset_gen/conf_parser.rs +++ b/rula-exec/src/ruleset_gen/conf_parser.rs @@ -1,6 +1,6 @@ -use crate::ruleset_gen::ruleset::AddressKind; use super::types::Repeater; use super::IResult; +use crate::ruleset_gen::ruleset::AddressKind; use serde::{Deserialize, Serialize}; @@ -24,7 +24,7 @@ pub fn parse_config(file_path: &PathBuf) -> IResult> { // Initiator (#1) < --- > Responder (#fin) // 1. Generate all repeaters let mut repeaters = vec![]; - for (index, content) in config.repeaters.iter().enumerate(){ + for (index, content) in config.repeaters.iter().enumerate() { let mut repeater = Repeater::new(&content.name); repeater.update_index(index as u64); repeater.update_address(content.address.clone()); @@ -60,8 +60,8 @@ fn deserialize_config(file_path: &PathBuf) -> IResult { #[cfg(test)] mod tests { use super::*; - use std::cell::RefCell; use crate::ruleset_gen::tracker::Tracker; + use std::cell::RefCell; #[test] fn test_parse_config() { diff --git a/rula-exec/src/ruleset_gen/types.rs b/rula-exec/src/ruleset_gen/types.rs index 485b182..658129a 100644 --- a/rula-exec/src/ruleset_gen/types.rs +++ b/rula-exec/src/ruleset_gen/types.rs @@ -1,8 +1,8 @@ use super::condition::*; use super::ruleset::Rule; +use crate::ruleset_gen::ruleset::AddressKind; use std::cell::RefCell; use std::rc::Rc; -use crate::ruleset_gen::ruleset::AddressKind; // Possible Type values in RuLa #[derive(Debug, Clone, PartialEq)] @@ -115,7 +115,7 @@ pub type RuleVec = Rc>>>; pub struct Repeater { // A readable name of this repeater pub name: String, - // An index of this repeater. + // An index of this repeater. // This is just for internal use to identify which repeater is which. pub index: u64, // A public address exposed to outer world @@ -137,11 +137,11 @@ impl Repeater { } } - pub fn update_index(&mut self, new_index: u64){ + pub fn update_index(&mut self, new_index: u64) { self.index = new_index } - pub fn update_address(&mut self, address: AddressKind){ + pub fn update_address(&mut self, address: AddressKind) { self.address = address } diff --git a/rula-lib/src/prelude.rs b/rula-lib/src/prelude.rs index 89964a5..341d37c 100644 --- a/rula-lib/src/prelude.rs +++ b/rula-lib/src/prelude.rs @@ -82,7 +82,9 @@ pub fn wait( pub fn recv(rules: RuleVec, source_repeater: &Repeater) -> Message { for rule in rules.borrow().iter() { rule.borrow_mut() - .add_condition_clause(ConditionClauses::Recv(Recv::new(source_repeater.address.clone()))); + .add_condition_clause(ConditionClauses::Recv(Recv::new( + source_repeater.address.clone(), + ))); } let mut new_message = Message::place_holder(); new_message.update_source(source_repeater.address.clone()); diff --git a/rula-parser/src/lib.rs b/rula-parser/src/lib.rs index 8afc0bd..faec25a 100644 --- a/rula-parser/src/lib.rs +++ b/rula-parser/src/lib.rs @@ -7,7 +7,6 @@ extern crate pest_derive; #[grammar = "parser/rula.pest"] pub struct RuLaParser; -use once_cell::sync::OnceCell; use std::path::PathBuf; use parser::ast::AstNode; @@ -15,7 +14,6 @@ use parser::error::RuLaError; use parser::IResult; use pest::Parser; -use std::fs; use crate::parser::build_ast_from_rula; diff --git a/rula/src/main.rs b/rula/src/main.rs index c4140f0..1c20e5b 100644 --- a/rula/src/main.rs +++ b/rula/src/main.rs @@ -21,6 +21,9 @@ struct Args { /// RuLa configuration config: PathBuf, + /// Output format of the RuleSet + output_format: Option, + /// Output directory path output_dir_path: Option, diff --git a/ruleset-ir/Cargo.toml b/ruleset-ir/Cargo.toml new file mode 100644 index 0000000..749878e --- /dev/null +++ b/ruleset-ir/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ruleset-ir" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/ruleset-ir/src/instructions.rs b/ruleset-ir/src/instructions.rs new file mode 100644 index 0000000..8e6089c --- /dev/null +++ b/ruleset-ir/src/instructions.rs @@ -0,0 +1,5 @@ +use crate::inst; +use crate::IR; +use crate::RSIR; + +inst!(Add, val: i32); diff --git a/ruleset-ir/src/lib.rs b/ruleset-ir/src/lib.rs new file mode 100644 index 0000000..e595909 --- /dev/null +++ b/ruleset-ir/src/lib.rs @@ -0,0 +1,58 @@ +#[allow(dead_code)] +pub mod instructions; +// pub mod ir_trait; + +// use crate::ir_trait::IR; +// use crate::ir_trait::RSIR; +pub type IR = String; + +// All the ruleset instructions needs to implement this trait RuleSet IR (RSIR). +// This trait implements `gen_ir` that returns a text format instruction for RuleSet +pub trait RSIR { + fn gen_ir() -> IR; +} + + +#[macro_export] +macro_rules! inst { + ($inst_name: ident, $($args: ident: $typedef: ty),* ) => { + #[derive(Debug)] + struct $inst_name{ + $( + $args: $typedef, + )* + } + + impl $inst_name{ + #[allow(dead_code)] + pub fn new($($args: $typedef),*) -> Self{ + $inst_name{ + $( + $args: $args, + )* + } + } + } + + impl RSIR for $inst_name{ + fn gen_ir() -> IR { + "test".to_string() + } + } + } +} + +// this function is to see the contents of inst! macro +#[allow(dead_code)] +fn expand() { + inst!(TestInstruction, test: String, test2: String); +} + +#[cfg(test)] +mod macro_test { + use super::*; + #[test] + fn macro_expansion() { + inst!(TestInstruction, test: String); + } +} From 342205147a36a34b90eb58b37b409e838190ccbb Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Tue, 18 Apr 2023 12:21:08 +0900 Subject: [PATCH 02/11] added instructions implemented in QuISP --- ruleset-ir/src/instructions.rs | 89 +++++++++++++++++++++++++++++++++- ruleset-ir/src/lib.rs | 83 +++++++++++++++++++------------ ruleset-ir/src/types.rs | 53 ++++++++++++++++++++ 3 files changed, 193 insertions(+), 32 deletions(-) create mode 100644 ruleset-ir/src/types.rs diff --git a/ruleset-ir/src/instructions.rs b/ruleset-ir/src/instructions.rs index 8e6089c..459ef94 100644 --- a/ruleset-ir/src/instructions.rs +++ b/ruleset-ir/src/instructions.rs @@ -1,5 +1,92 @@ use crate::inst; use crate::IR; use crate::RSIR; +use crate::types::*; -inst!(Add, val: i32); +// These inst!uctions are expanded to the structures +// The inst!uction named with "_DUP" will be renamed into a name without "_DUP" for QuISP +// READ and WRITE are just annotations to know which arguments are written or read + +// arithmetic +inst!(ADD, WRITE reg0: RegId, READ reg1: RegId, READ val: i64); +inst!(ADD_DUP, WRITE reg0: RegId, READ reg1: RegId, READ reg2: RegId); // In QuISP, this is the same as `Add` +inst!(SUB, WRITE reg0: RegId, READ reg1: RegId, READ val: i64); +inst!(SUB_DUP, WRITE reg0: RegId, READ reg1: RegId, READ reg2: RegId); // In QuISP, this is the same as `Sub` +inst!(INC, WR reg0: RegId); +inst!(SET, WRITE reg0: RegId, READ val: i64); +// arithmetic bitwise +inst!(BITWISE_AND, WRITE reg0: RegId, READ reg1: RegId, READ val: i64); +inst!(BITWISE_AND_DUP, WRITE reg0: RegId, READ reg1: RegId, READ reg2: RegId); // In QuISP, this is the same as `BITWISE_AND` +inst!(BITWISE_OR, WRITE reg0: RegId, READ reg1: RegId, READ val: i64); +inst!(BITWISE_OR_DUP, WRITE reg0: RegId, READ reg1: RegId, READ reg2: RegId); +inst!(BITWISE_XOR, WRITE reg0: RegId, READ reg1: RegId, READ reg2: RegId); +inst!(BITWISE_XOR_DUP, WRITE reg0: RegId, READ reg1: RegId, READ val: i64); +// in place operation +inst!(BITWISE_AND_INP, WRITE reg0: RegId, READ reg1: RegId ); // in-place operation: first_reg = first_reg | second_reg (bitwise and); +inst!(BITWISE_AND_INP_DUP, WRITE reg0: RegId , READ val: i64 ); // in-place operation: first_reg = first_reg | int (bitwise and); +inst!(BITWISE_OR_INP, WRITE reg0: RegId , READ reg1: RegId ); // in-place operation: first_reg = first_reg | second_reg (bitwise or); +inst!(BITWISE_OR_INP_DUP, WRITE reg0: RegId, READ val: i64 ); // in-place operation: first_reg = first_reg | int (bitwise or); +inst!(BITWISE_XOR_INP, WRITE reg0: RegId, READ reg1: RegId ); // in-place operation: first_reg = first_reg | second_reg (bitwise xor); +inst!(BITWISE_XOR_INP_DUP, WRITE reg0: RegId, READ reg1: i64 ); // in-place operation: first_reg = first_reg | int (bitwise xor); + +// control flow +inst!(BEQ, LABEL label: Label, READ reg0: RegId, READ reg1: RegId); // branch if the reg values are same +inst!(BEQ_DUP, LABEL label: Label, READ reg0: RegId, READ val: i64); // branch if the reg value is equal to the int value +inst!(BEZ, LABEL label: Label, READ reg0: RegId); // branch if the reg value is zero +inst!(BNZ, LABEL label: Label, READ reg0: RegId); // branch if the reg value is not zero +inst!(BLT, LABEL label: Label, READ reg0: RegId, READ val: i64); // branch if the reg value is less than the int value +inst!(BRANCH_IF_LOCKED, LABEL label: Label, READ reg: RegId); +inst!(BRANCH_IF_QUBIT_FOUND, LABEL label: Label); +inst!(BRANCH_IF_MESSAGE_FOUND, LABEL label: Label); +inst!(JMP, LABEL label: Label); +inst!(ERROR, message: String); // stop execution and show error +inst!(RET, code: ReturnCode); // stop execution with the ReturnCode + +// memory operations +inst!(LOAD, WRITE reg0: RegId, READ mem_key: MemoryKey); +inst!(STORE, WRITE mem_key: MemoryKey, READ reg0: RegId); +inst!(STORE_DUP, WRITE mem_key: MemoryKey, READ val: i64); + +inst!(LOAD_LEFT_OP, WRITE reg0: RegId, READ mem_key: MemoryKey); // READ memkey? +inst!(LOAD_RIGHT_OP, WRITE reg0: RegId, READ mem_key: MemoryKey); + +// qubit retrieval operations +inst!(GET_QUBIT, WRITE qubit0: QubitId, READ qnode_addr0: QNodeAddr, READ val: i64); // may throw "no qubit error" +inst!(GET_QUBIT_R_DUP, WRITE qubit0: QubitId, READ partner_addr: QNodeAddr, READ reg0: RegId); // may throw "no qubit error" +inst!(GET_QUBIT_RQ_DUP, WRITE reg0: RegId, READ partner_addr: QNodeAddr, READ qubit_index: RegId); +inst!(GET_QUBIT_BY_SEQ_NO, WRITE reg0: RegId, READ partner_addr: QNodeAddr, READ sequence_number: RegId); +inst!(GET_QUBIT_BY_SEQ_NO_DUP, WRITE qubit: QubitId, READ partner_addr: QNodeAddr, READ sequence_number: RegId); + +// qubit quantum gate operations +inst!(MEASURE_RANDOM, WRITE reg0: MemoryKey, READ target_qubit: QubitId); +inst!(MEASURE, WRITE reg0: MemoryKey, READ target_qubit: QubitId, READ meas_basis: Basis); +inst!(MEASURE_R_DUP, WRITE reg0: RegId, READ target_qubit: QubitId, READ meas_basis: Basis); +inst!(MEASURE_RQ_DUP, WRITE reg0: RegId, READ bit: i64, READ target_qubit: QubitId, READ meas_basis: Basis); // this will store the result at index (bitset); of the RegId specified by the int +inst!(GATE_X, READ target_qubit: QubitId); +inst!(GATE_Z, READ target_qubit: QubitId); +inst!(GATE_Y, READ target_qubit: QubitId); +inst!(GATE_CNOT, READ control_qubit: QubitId, READ target_qubit: QubitId); +// circuit operations +inst!(PURIFY_X, WRITE reg0: RegId, READ val: i64, READ keep_qubit_id: QubitId, READ trash_qubit_id: QubitId); +inst!(PURIFY_Z, WRITE reg0: RegId, READ val: i64, READ keep_qubit_id: QubitId, READ trash_qubit_id: QubitId); +inst!(PURIFY_Y, WRITE reg0: RegId, READ val: i64, READ keep_qubit_id: QubitId, READ trash_qubit_id: QubitId); + +// resource management operations +// inst!uctions we would want later: crucial for entanglement pumping, banding, and multipartite states +// inst!(SET_NAME, QubitId, {new_name: string | RegId }); // when using partner as name is not enough +inst!(FREE_QUBIT, READ qubit: QubitId); +inst!(PROMOTE, READ qubit: QubitId); +inst!(PROMOTE_DUP, READ qubit: QubitId, READ reg0: RegId); // promote with new partner/new name +inst!(LOCK_QUBIT, READ qubit: QubitId, READ reg0_action_index: RegId); + +// message operations +inst!(GET_MESSAGE_SEQ, WRITE sequence_number: RegId, READ message_index: RegId); +inst!(COUNT_MESSAGE, WRITE count: RegId, READ sequence_number: RegId); +inst!(GET_MESSAGE, WRITE reg_content: RegId, READ sequence_number: RegId, READ message_index: i64); // for purification [result] +inst!(GET_MESSAGE_DUP, WRITE content0: RegId, WRITE content1: RegId, READ sequence_number: RegId, READ message_index: i64); // for swapping [correction_op, new_partner] +inst!(DELETE_MESSAGE, READ sequence_number: RegId); // delete all messages with this sequence number + +// send classical messages +inst!(SEND_LINK_TOMOGRAPHY_RESULT, READ partner_addr: QNodeAddr, READ reg0: RegId, READ mem_key: MemoryKey, READ val: i64, READ time: Time); // partner addr, current count reg_id, outcome key, max_count, start_time +inst!(SEND_PURIFICATION_RESULT, READ partner_addr: QNodeAddr, READ reg0: RegId /* measurement_result encoded in int */, READ reg1: RegId /* sequence_number */, READ pur_type: PurType); +inst!(SEND_SWAPPING_RESULT, READ partner_addr: QNodeAddr /* receipient */, READ reg0: RegId /* pauli_op */, READ new_partner_addr: QNodeAddr /* new partner*/, READ sequence_number: RegId /* sequence_number */); diff --git a/ruleset-ir/src/lib.rs b/ruleset-ir/src/lib.rs index e595909..74ecf73 100644 --- a/ruleset-ir/src/lib.rs +++ b/ruleset-ir/src/lib.rs @@ -1,9 +1,10 @@ #[allow(dead_code)] +#[allow(non_camel_case_types)] pub mod instructions; -// pub mod ir_trait; -// use crate::ir_trait::IR; -// use crate::ir_trait::RSIR; +pub mod types; + +// will be removed pub type IR = String; // All the ruleset instructions needs to implement this trait RuleSet IR (RSIR). @@ -12,47 +13,67 @@ pub trait RSIR { fn gen_ir() -> IR; } - #[macro_export] macro_rules! inst { - ($inst_name: ident, $($args: ident: $typedef: ty),* ) => { - #[derive(Debug)] - struct $inst_name{ - $( - $args: $typedef, - )* - } + // with annotation + ($inst_name: ident, $($mode: ident $args: ident: $typedef: ty),* ) => { + #[derive(Debug)] + struct $inst_name { + $( + $args: $typedef, + )* + } - impl $inst_name{ - #[allow(dead_code)] - pub fn new($($args: $typedef),*) -> Self{ - $inst_name{ - $( - $args: $args, - )* - } + impl $inst_name { + #[allow(dead_code)] + pub fn new($($args: $typedef),*) -> Self { + $inst_name { + $( + $args: $args, + )* } } + } - impl RSIR for $inst_name{ - fn gen_ir() -> IR { - "test".to_string() + impl RSIR for $inst_name { + fn gen_ir() -> IR { + "test".to_string() + } + } + }; + // without annotation (need refactor) + ($inst_name: ident, $($args: ident: $typedef: ty),* ) => { + #[derive(Debug)] + struct $inst_name { + $( + $args: $typedef, + )* + } + + impl $inst_name { + #[allow(dead_code)] + pub fn new($($args: $typedef),*) -> Self { + $inst_name { + $( + $args: $args, + )* } } } + + impl RSIR for $inst_name { + fn gen_ir() -> IR { + "test".to_string() + } + } + }; } + // this function is to see the contents of inst! macro #[allow(dead_code)] fn expand() { - inst!(TestInstruction, test: String, test2: String); + inst!(TestInstruction, READ test: String, WRITE test2: String); } -#[cfg(test)] -mod macro_test { - use super::*; - #[test] - fn macro_expansion() { - inst!(TestInstruction, test: String); - } -} + diff --git a/ruleset-ir/src/types.rs b/ruleset-ir/src/types.rs new file mode 100644 index 0000000..60f1689 --- /dev/null +++ b/ruleset-ir/src/types.rs @@ -0,0 +1,53 @@ +#[derive(Debug)] +pub enum RegId{ + Reg0, // Register 0 + Reg1, + Reg2, + Reg3, + Reg4, +} + +#[derive(Debug)] +pub struct Label{ + val: String +} + +#[derive(Debug)] +pub enum ReturnCode { + Nothing, + CondFailed, + CondPassed, + RsTerminated, + Error, +} + +#[derive(Debug)] +pub struct MemoryKey{ + key: String +} + +#[derive(Debug)] +pub struct QNodeAddr{ + val: i64 +} + +#[derive(Debug, Hash)] +pub struct QubitId{ + val: i64 +} + +#[derive(Debug)] +pub enum Basis{ + Z, + Y, + X, + Random, +} + +// Used in ver.1 Ruleset +// This must be compatible with omnetpp simtime. +#[derive(Debug)] +pub struct Time; + +#[derive(Debug)] +pub struct PurType; \ No newline at end of file From ff9d0b704a7e125f2b2f6a63863a8c7f89f101ba Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Tue, 18 Apr 2023 14:40:35 +0900 Subject: [PATCH 03/11] cleaned up warnings --- rula-exec/Cargo.toml | 3 +- rula-exec/src/lib.rs | 1 + rula-exec/src/ruleset_gen/action.rs | 2 +- rula-exec/src/ruleset_gen/conf_parser.rs | 2 +- rula-exec/src/ruleset_gen/generator.rs | 1 + .../src/ruleset_gen/ruleset_generator.rs | 4 +- .../src/ruleset_gen/test_ruleset_generator.rs | 1 - rula-exec/src/ruleset_gen/tracker.rs | 9 +--- rula-exec/src/ruleset_gen/types.rs | 2 +- rula-lib/src/lib.rs | 1 - rula-lib/src/operation.rs | 2 - rula-lib/src/prelude.rs | 8 ++-- rula-parser/Cargo.toml | 2 +- rula-parser/src/lib.rs | 1 - rula-parser/src/parser.rs | 4 +- rula-parser/src/parser/ast.rs | 1 - rula/Cargo.toml | 2 +- rula/src/main.rs | 2 +- ruleset-ir/src/instructions.rs | 46 +++++++++---------- ruleset-ir/src/lib.rs | 5 +- ruleset-ir/src/types.rs | 22 ++++----- tests-e2e/Cargo.toml | 2 +- 22 files changed, 53 insertions(+), 70 deletions(-) create mode 100644 rula-exec/src/ruleset_gen/generator.rs diff --git a/rula-exec/Cargo.toml b/rula-exec/Cargo.toml index 02cad0e..98dcf4b 100644 --- a/rula-exec/Cargo.toml +++ b/rula-exec/Cargo.toml @@ -7,7 +7,8 @@ description = "Generate executable Rust code for RuLa program" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rula_parser = { path = "../rula-parser" } +rula-parser = { path = "../rula-parser" } +ruleset-ir = {path = "../ruleset-ir"} # (rula_ast -> rula_program(rust syntax tree) -> quote -> rust_source) quote = "1.0" syn = {version = "1.0", features = ["full"]} diff --git a/rula-exec/src/lib.rs b/rula-exec/src/lib.rs index cd71403..80dc94a 100644 --- a/rula-exec/src/lib.rs +++ b/rula-exec/src/lib.rs @@ -11,6 +11,7 @@ pub mod ruleset_gen { pub mod condition; pub mod conf_parser; pub mod factory; + pub mod generator; pub mod ruleset; pub mod ruleset_generator; pub mod tracker; diff --git a/rula-exec/src/ruleset_gen/action.rs b/rula-exec/src/ruleset_gen/action.rs index 70f4e63..51f074f 100644 --- a/rula-exec/src/ruleset_gen/action.rs +++ b/rula-exec/src/ruleset_gen/action.rs @@ -1,4 +1,4 @@ -use super::{ruleset::ProtocolMessages, types::RuLaResult}; +use super::ruleset::ProtocolMessages; use core::time::Duration; use serde::{Deserialize, Serialize}; diff --git a/rula-exec/src/ruleset_gen/conf_parser.rs b/rula-exec/src/ruleset_gen/conf_parser.rs index 7b6e11f..0d3818d 100644 --- a/rula-exec/src/ruleset_gen/conf_parser.rs +++ b/rula-exec/src/ruleset_gen/conf_parser.rs @@ -77,7 +77,7 @@ mod tests { fn test_repeater_resolve() { // #1 < -- > #2 < -- > #3 < -- > #4 < -- > #5 let config_path = PathBuf::from("../examples/v2/config.json"); - let tracker = RefCell::new(Tracker::new()); + let _tracker = RefCell::new(Tracker::new()); let repeater_list = parse_config(&config_path).unwrap(); assert_eq!(repeater_list.len(), 5); diff --git a/rula-exec/src/ruleset_gen/generator.rs b/rula-exec/src/ruleset_gen/generator.rs new file mode 100644 index 0000000..4d24753 --- /dev/null +++ b/rula-exec/src/ruleset_gen/generator.rs @@ -0,0 +1 @@ +// generate ruleset IR diff --git a/rula-exec/src/ruleset_gen/ruleset_generator.rs b/rula-exec/src/ruleset_gen/ruleset_generator.rs index c929950..ef36b1e 100644 --- a/rula-exec/src/ruleset_gen/ruleset_generator.rs +++ b/rula-exec/src/ruleset_gen/ruleset_generator.rs @@ -1101,8 +1101,8 @@ pub(super) fn generate_rep_call_arg( RepeaterCallArg::Term(term) => { generate_term_expr(term, tracker, scope, in_ruledef).unwrap() } - RepeaterCallArg::Ident(ident) => (generate_ident(ident, tracker, scope).unwrap()), - RepeaterCallArg::IntegerLit(int_lit) => (generate_int_lit(int_lit).unwrap()), + RepeaterCallArg::Ident(ident) => generate_ident(ident, tracker, scope).unwrap(), + RepeaterCallArg::IntegerLit(int_lit) => generate_int_lit(int_lit).unwrap(), RepeaterCallArg::PlaceHolder => return Err(RuleSetGenError::InitializationError), }; Ok((quote!(__factory.borrow().repeaters.at(#arg)), quote!(#arg))) diff --git a/rula-exec/src/ruleset_gen/test_ruleset_generator.rs b/rula-exec/src/ruleset_gen/test_ruleset_generator.rs index 9a785e1..e0ca582 100644 --- a/rula-exec/src/ruleset_gen/test_ruleset_generator.rs +++ b/rula-exec/src/ruleset_gen/test_ruleset_generator.rs @@ -109,7 +109,6 @@ mod tests { #[cfg(test)] mod term_expr_tests { - use super::*; #[test] fn simple_term_expr() { diff --git a/rula-exec/src/ruleset_gen/tracker.rs b/rula-exec/src/ruleset_gen/tracker.rs index c58e606..c8dc86b 100644 --- a/rula-exec/src/ruleset_gen/tracker.rs +++ b/rula-exec/src/ruleset_gen/tracker.rs @@ -1,13 +1,6 @@ -use serde_json::Value; - -use super::ruleset::{RuleSet, Stage}; -use super::ruleset_generator::{Scope, ValueTracker}; -use super::types::{Repeater, RuLaValue, Types}; -use std::cell::RefCell; +use super::types::Types; use std::collections::{HashMap, HashSet}; -use std::rc::Rc; -type NodeNumber = usize; type RuleName = String; // Track all global state in generation diff --git a/rula-exec/src/ruleset_gen/types.rs b/rula-exec/src/ruleset_gen/types.rs index 658129a..3aef374 100644 --- a/rula-exec/src/ruleset_gen/types.rs +++ b/rula-exec/src/ruleset_gen/types.rs @@ -45,7 +45,7 @@ pub enum RuLaValue { } impl RuLaValue { - pub fn wrap(val: &T) -> Self { + pub fn wrap(_val: &T) -> Self { match std::any::type_name::() { // "Repeater" => {RuLaValue::Repeater(val as Repeater)} _ => todo!(), diff --git a/rula-lib/src/lib.rs b/rula-lib/src/lib.rs index c25dfce..77c1590 100644 --- a/rula-lib/src/lib.rs +++ b/rula-lib/src/lib.rs @@ -5,5 +5,4 @@ pub mod time; // use ruleset::action::v2::ActionClauses; // use ruleset::ruleset::Rule; -use std::cell::RefCell; use std::rc::Rc; diff --git a/rula-lib/src/operation.rs b/rula-lib/src/operation.rs index 7521118..c2a1e65 100644 --- a/rula-lib/src/operation.rs +++ b/rula-lib/src/operation.rs @@ -1,5 +1,3 @@ -use std::borrow::BorrowMut; - use super::*; // use crate::qubit::QubitInterface; use rula_exec::ruleset_gen::{ diff --git a/rula-lib/src/prelude.rs b/rula-lib/src/prelude.rs index 341d37c..545f952 100644 --- a/rula-lib/src/prelude.rs +++ b/rula-lib/src/prelude.rs @@ -2,8 +2,6 @@ use rula_exec::ruleset_gen::action::*; use rula_exec::ruleset_gen::condition::*; use rula_exec::ruleset_gen::ruleset::*; use rula_exec::ruleset_gen::types::*; -use std::cell::RefCell; -use std::collections::HashSet; pub fn res( rules: RuleVec, @@ -35,7 +33,7 @@ pub fn free(rules: RuleVec, qubit: &Qubit) { } } -pub fn check_timer(rules: RuleVec, timer_id: String) { +pub fn check_timer(rules: RuleVec, _timer_id: String) { for rule in rules.borrow().iter() { rule.borrow_mut() .add_condition_clause(ConditionClauses::Timer(10.0)); @@ -43,11 +41,11 @@ pub fn check_timer(rules: RuleVec, timer_id: String) { todo!("Need fix"); } -pub fn cmp(rules: RuleVec) { +pub fn cmp(_rules: RuleVec) { todo!("Add!") } -pub fn set_timer(rules: RuleVec) { +pub fn set_timer(_rules: RuleVec) { todo!("Add timer"); } diff --git a/rula-parser/Cargo.toml b/rula-parser/Cargo.toml index 0214f96..d01171a 100644 --- a/rula-parser/Cargo.toml +++ b/rula-parser/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rula_parser" +name = "rula-parser" version = "0.1.0" edition = "2021" description = "A parser for RuLa programming language" diff --git a/rula-parser/src/lib.rs b/rula-parser/src/lib.rs index faec25a..e1117d4 100644 --- a/rula-parser/src/lib.rs +++ b/rula-parser/src/lib.rs @@ -14,7 +14,6 @@ use parser::error::RuLaError; use parser::IResult; use pest::Parser; - use crate::parser::build_ast_from_rula; // Interface function to parse rula code diff --git a/rula-parser/src/parser.rs b/rula-parser/src/parser.rs index e6bbc19..028f0bf 100644 --- a/rula-parser/src/parser.rs +++ b/rula-parser/src/parser.rs @@ -2,8 +2,6 @@ pub mod ast; pub mod error; mod util; -use std::env; - use crate::{parse, Rule}; // RuLa use ast::*; @@ -303,7 +301,7 @@ fn extract_rule( } Ok(target_rule) } - _ => return panic!("Program Kind?"), + _ => unreachable!(), } } AstNode::PlaceHolder => panic!("AST does not contain RuLa AST node"), diff --git a/rula-parser/src/parser/ast.rs b/rula-parser/src/parser/ast.rs index 11188b9..df0efee 100644 --- a/rula-parser/src/parser/ast.rs +++ b/rula-parser/src/parser/ast.rs @@ -1,4 +1,3 @@ -use std::iter::Iterator; use std::path::PathBuf; /** diff --git a/rula/Cargo.toml b/rula/Cargo.toml index 6d378a0..708e55c 100644 --- a/rula/Cargo.toml +++ b/rula/Cargo.toml @@ -11,5 +11,5 @@ clap = { version = "4.0.10", features = ["derive"] } toml = "0.5.9" proc-macro2 = "1.0" # serde = "1.0" -rula_parser = {path="../rula-parser"} +rula-parser = {path="../rula-parser"} rula-exec = {path="../rula-exec"} diff --git a/rula/src/main.rs b/rula/src/main.rs index 1c20e5b..0c540fc 100644 --- a/rula/src/main.rs +++ b/rula/src/main.rs @@ -1,9 +1,9 @@ use proc_macro2::TokenStream; +use std::env; use std::fs::File; use std::io::{Read, Write}; use std::path::PathBuf; use std::process::Command; -use std::{env, fs}; use clap::Parser; diff --git a/ruleset-ir/src/instructions.rs b/ruleset-ir/src/instructions.rs index 459ef94..a540165 100644 --- a/ruleset-ir/src/instructions.rs +++ b/ruleset-ir/src/instructions.rs @@ -1,7 +1,7 @@ use crate::inst; +use crate::types::*; use crate::IR; use crate::RSIR; -use crate::types::*; // These inst!uctions are expanded to the structures // The inst!uction named with "_DUP" will be renamed into a name without "_DUP" for QuISP @@ -22,37 +22,37 @@ inst!(BITWISE_OR_DUP, WRITE reg0: RegId, READ reg1: RegId, READ reg2: RegId); inst!(BITWISE_XOR, WRITE reg0: RegId, READ reg1: RegId, READ reg2: RegId); inst!(BITWISE_XOR_DUP, WRITE reg0: RegId, READ reg1: RegId, READ val: i64); // in place operation -inst!(BITWISE_AND_INP, WRITE reg0: RegId, READ reg1: RegId ); // in-place operation: first_reg = first_reg | second_reg (bitwise and); -inst!(BITWISE_AND_INP_DUP, WRITE reg0: RegId , READ val: i64 ); // in-place operation: first_reg = first_reg | int (bitwise and); -inst!(BITWISE_OR_INP, WRITE reg0: RegId , READ reg1: RegId ); // in-place operation: first_reg = first_reg | second_reg (bitwise or); -inst!(BITWISE_OR_INP_DUP, WRITE reg0: RegId, READ val: i64 ); // in-place operation: first_reg = first_reg | int (bitwise or); -inst!(BITWISE_XOR_INP, WRITE reg0: RegId, READ reg1: RegId ); // in-place operation: first_reg = first_reg | second_reg (bitwise xor); -inst!(BITWISE_XOR_INP_DUP, WRITE reg0: RegId, READ reg1: i64 ); // in-place operation: first_reg = first_reg | int (bitwise xor); +inst!(BITWISE_AND_INP, WRITE reg0: RegId, READ reg1: RegId ); // in-place operation: first_reg = first_reg | second_reg (bitwise and); +inst!(BITWISE_AND_INP_DUP, WRITE reg0: RegId , READ val: i64 ); // in-place operation: first_reg = first_reg | int (bitwise and); +inst!(BITWISE_OR_INP, WRITE reg0: RegId , READ reg1: RegId ); // in-place operation: first_reg = first_reg | second_reg (bitwise or); +inst!(BITWISE_OR_INP_DUP, WRITE reg0: RegId, READ val: i64 ); // in-place operation: first_reg = first_reg | int (bitwise or); +inst!(BITWISE_XOR_INP, WRITE reg0: RegId, READ reg1: RegId ); // in-place operation: first_reg = first_reg | second_reg (bitwise xor); +inst!(BITWISE_XOR_INP_DUP, WRITE reg0: RegId, READ reg1: i64 ); // in-place operation: first_reg = first_reg | int (bitwise xor); // control flow -inst!(BEQ, LABEL label: Label, READ reg0: RegId, READ reg1: RegId); // branch if the reg values are same -inst!(BEQ_DUP, LABEL label: Label, READ reg0: RegId, READ val: i64); // branch if the reg value is equal to the int value -inst!(BEZ, LABEL label: Label, READ reg0: RegId); // branch if the reg value is zero -inst!(BNZ, LABEL label: Label, READ reg0: RegId); // branch if the reg value is not zero -inst!(BLT, LABEL label: Label, READ reg0: RegId, READ val: i64); // branch if the reg value is less than the int value +inst!(BEQ, LABEL label: Label, READ reg0: RegId, READ reg1: RegId); // branch if the reg values are same +inst!(BEQ_DUP, LABEL label: Label, READ reg0: RegId, READ val: i64); // branch if the reg value is equal to the int value +inst!(BEZ, LABEL label: Label, READ reg0: RegId); // branch if the reg value is zero +inst!(BNZ, LABEL label: Label, READ reg0: RegId); // branch if the reg value is not zero +inst!(BLT, LABEL label: Label, READ reg0: RegId, READ val: i64); // branch if the reg value is less than the int value inst!(BRANCH_IF_LOCKED, LABEL label: Label, READ reg: RegId); inst!(BRANCH_IF_QUBIT_FOUND, LABEL label: Label); inst!(BRANCH_IF_MESSAGE_FOUND, LABEL label: Label); inst!(JMP, LABEL label: Label); -inst!(ERROR, message: String); // stop execution and show error -inst!(RET, code: ReturnCode); // stop execution with the ReturnCode +inst!(ERROR, message: String); // stop execution and show error +inst!(RET, code: ReturnCode); // stop execution with the ReturnCode // memory operations inst!(LOAD, WRITE reg0: RegId, READ mem_key: MemoryKey); inst!(STORE, WRITE mem_key: MemoryKey, READ reg0: RegId); inst!(STORE_DUP, WRITE mem_key: MemoryKey, READ val: i64); -inst!(LOAD_LEFT_OP, WRITE reg0: RegId, READ mem_key: MemoryKey); // READ memkey? +inst!(LOAD_LEFT_OP, WRITE reg0: RegId, READ mem_key: MemoryKey); // READ memkey? inst!(LOAD_RIGHT_OP, WRITE reg0: RegId, READ mem_key: MemoryKey); // qubit retrieval operations -inst!(GET_QUBIT, WRITE qubit0: QubitId, READ qnode_addr0: QNodeAddr, READ val: i64); // may throw "no qubit error" -inst!(GET_QUBIT_R_DUP, WRITE qubit0: QubitId, READ partner_addr: QNodeAddr, READ reg0: RegId); // may throw "no qubit error" +inst!(GET_QUBIT, WRITE qubit0: QubitId, READ qnode_addr0: QNodeAddr, READ val: i64); // may throw "no qubit error" +inst!(GET_QUBIT_R_DUP, WRITE qubit0: QubitId, READ partner_addr: QNodeAddr, READ reg0: RegId); // may throw "no qubit error" inst!(GET_QUBIT_RQ_DUP, WRITE reg0: RegId, READ partner_addr: QNodeAddr, READ qubit_index: RegId); inst!(GET_QUBIT_BY_SEQ_NO, WRITE reg0: RegId, READ partner_addr: QNodeAddr, READ sequence_number: RegId); inst!(GET_QUBIT_BY_SEQ_NO_DUP, WRITE qubit: QubitId, READ partner_addr: QNodeAddr, READ sequence_number: RegId); @@ -61,7 +61,7 @@ inst!(GET_QUBIT_BY_SEQ_NO_DUP, WRITE qubit: QubitId, READ partner_addr: QNodeAdd inst!(MEASURE_RANDOM, WRITE reg0: MemoryKey, READ target_qubit: QubitId); inst!(MEASURE, WRITE reg0: MemoryKey, READ target_qubit: QubitId, READ meas_basis: Basis); inst!(MEASURE_R_DUP, WRITE reg0: RegId, READ target_qubit: QubitId, READ meas_basis: Basis); -inst!(MEASURE_RQ_DUP, WRITE reg0: RegId, READ bit: i64, READ target_qubit: QubitId, READ meas_basis: Basis); // this will store the result at index (bitset); of the RegId specified by the int +inst!(MEASURE_RQ_DUP, WRITE reg0: RegId, READ bit: i64, READ target_qubit: QubitId, READ meas_basis: Basis); // this will store the result at index (bitset); of the RegId specified by the int inst!(GATE_X, READ target_qubit: QubitId); inst!(GATE_Z, READ target_qubit: QubitId); inst!(GATE_Y, READ target_qubit: QubitId); @@ -76,17 +76,17 @@ inst!(PURIFY_Y, WRITE reg0: RegId, READ val: i64, READ keep_qubit_id: QubitId, R // inst!(SET_NAME, QubitId, {new_name: string | RegId }); // when using partner as name is not enough inst!(FREE_QUBIT, READ qubit: QubitId); inst!(PROMOTE, READ qubit: QubitId); -inst!(PROMOTE_DUP, READ qubit: QubitId, READ reg0: RegId); // promote with new partner/new name +inst!(PROMOTE_DUP, READ qubit: QubitId, READ reg0: RegId); // promote with new partner/new name inst!(LOCK_QUBIT, READ qubit: QubitId, READ reg0_action_index: RegId); // message operations inst!(GET_MESSAGE_SEQ, WRITE sequence_number: RegId, READ message_index: RegId); inst!(COUNT_MESSAGE, WRITE count: RegId, READ sequence_number: RegId); -inst!(GET_MESSAGE, WRITE reg_content: RegId, READ sequence_number: RegId, READ message_index: i64); // for purification [result] -inst!(GET_MESSAGE_DUP, WRITE content0: RegId, WRITE content1: RegId, READ sequence_number: RegId, READ message_index: i64); // for swapping [correction_op, new_partner] -inst!(DELETE_MESSAGE, READ sequence_number: RegId); // delete all messages with this sequence number +inst!(GET_MESSAGE, WRITE reg_content: RegId, READ sequence_number: RegId, READ message_index: i64); // for purification [result] +inst!(GET_MESSAGE_DUP, WRITE content0: RegId, WRITE content1: RegId, READ sequence_number: RegId, READ message_index: i64); // for swapping [correction_op, new_partner] +inst!(DELETE_MESSAGE, READ sequence_number: RegId); // delete all messages with this sequence number // send classical messages -inst!(SEND_LINK_TOMOGRAPHY_RESULT, READ partner_addr: QNodeAddr, READ reg0: RegId, READ mem_key: MemoryKey, READ val: i64, READ time: Time); // partner addr, current count reg_id, outcome key, max_count, start_time +inst!(SEND_LINK_TOMOGRAPHY_RESULT, READ partner_addr: QNodeAddr, READ reg0: RegId, READ mem_key: MemoryKey, READ val: i64, READ time: Time); // partner addr, current count reg_id, outcome key, max_count, start_time inst!(SEND_PURIFICATION_RESULT, READ partner_addr: QNodeAddr, READ reg0: RegId /* measurement_result encoded in int */, READ reg1: RegId /* sequence_number */, READ pur_type: PurType); inst!(SEND_SWAPPING_RESULT, READ partner_addr: QNodeAddr /* receipient */, READ reg0: RegId /* pauli_op */, READ new_partner_addr: QNodeAddr /* new partner*/, READ sequence_number: RegId /* sequence_number */); diff --git a/ruleset-ir/src/lib.rs b/ruleset-ir/src/lib.rs index 74ecf73..ff0c980 100644 --- a/ruleset-ir/src/lib.rs +++ b/ruleset-ir/src/lib.rs @@ -66,14 +66,11 @@ macro_rules! inst { "test".to_string() } } - }; + }; } - // this function is to see the contents of inst! macro #[allow(dead_code)] fn expand() { inst!(TestInstruction, READ test: String, WRITE test2: String); } - - diff --git a/ruleset-ir/src/types.rs b/ruleset-ir/src/types.rs index 60f1689..c703ed8 100644 --- a/ruleset-ir/src/types.rs +++ b/ruleset-ir/src/types.rs @@ -1,5 +1,5 @@ #[derive(Debug)] -pub enum RegId{ +pub enum RegId { Reg0, // Register 0 Reg1, Reg2, @@ -8,8 +8,8 @@ pub enum RegId{ } #[derive(Debug)] -pub struct Label{ - val: String +pub struct Label { + _val: String, } #[derive(Debug)] @@ -22,22 +22,22 @@ pub enum ReturnCode { } #[derive(Debug)] -pub struct MemoryKey{ - key: String +pub struct MemoryKey { + _key: String, } #[derive(Debug)] -pub struct QNodeAddr{ - val: i64 +pub struct QNodeAddr { + _val: i64, } #[derive(Debug, Hash)] -pub struct QubitId{ - val: i64 +pub struct QubitId { + _val: i64, } #[derive(Debug)] -pub enum Basis{ +pub enum Basis { Z, Y, X, @@ -50,4 +50,4 @@ pub enum Basis{ pub struct Time; #[derive(Debug)] -pub struct PurType; \ No newline at end of file +pub struct PurType; diff --git a/tests-e2e/Cargo.toml b/tests-e2e/Cargo.toml index d98108e..d2eda5d 100644 --- a/tests-e2e/Cargo.toml +++ b/tests-e2e/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] rula = {path = "../rula"} -rula_parser = { path = "../rula-parser" } +rula-parser = { path = "../rula-parser" } rula-exec = {path="../rula-exec"} rula-lib = {path="../rula-lib"} From 628f61f54a7377a10eb59b8936c28ce849c91ca4 Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Tue, 18 Apr 2023 14:48:29 +0900 Subject: [PATCH 04/11] resolve all warnings --- rula-exec/src/ruleset_gen/ruleset_generator.rs | 3 ++- tests-e2e/Cargo.toml | 1 - tests-e2e/tests/e2e_rulesetgen_test.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rula-exec/src/ruleset_gen/ruleset_generator.rs b/rula-exec/src/ruleset_gen/ruleset_generator.rs index ef36b1e..534989f 100644 --- a/rula-exec/src/ruleset_gen/ruleset_generator.rs +++ b/rula-exec/src/ruleset_gen/ruleset_generator.rs @@ -65,10 +65,11 @@ pub fn generate(ast_tree: &AstNode, config_path: PathBuf) -> IResult Date: Wed, 10 May 2023 14:59:37 +0900 Subject: [PATCH 05/11] added ruleset ir and symbol table --- doc/design.md | 1 - doc/spec.md | 8 +++ rula-exec/src/lib.rs | 7 +- rula-exec/src/ruleset_gen/error.rs | 5 ++ rula-exec/src/ruleset_gen/generator.rs | 28 +++++++- rula-exec/src/ruleset_gen/symbol_table.rs | 79 +++++++++++++++++++++++ rula-exec/tests/ir_gen_test.rs | 17 +++++ rula-lib/src/prelude.rs | 2 + ruleset-ir/src/instructions.rs | 3 +- ruleset-ir/src/lib.rs | 14 ++-- ruleset-ir/src/types.rs | 3 + 11 files changed, 156 insertions(+), 11 deletions(-) delete mode 100644 doc/design.md create mode 100644 doc/spec.md create mode 100644 rula-exec/src/ruleset_gen/symbol_table.rs create mode 100644 rula-exec/tests/ir_gen_test.rs diff --git a/doc/design.md b/doc/design.md deleted file mode 100644 index 37bde7f..0000000 --- a/doc/design.md +++ /dev/null @@ -1 +0,0 @@ -# Design decisions go here \ No newline at end of file diff --git a/doc/spec.md b/doc/spec.md new file mode 100644 index 0000000..fc34661 --- /dev/null +++ b/doc/spec.md @@ -0,0 +1,8 @@ +# RuLa Specification +... + +## Lifetime and Scope +Scope names: + +\_\_@global\_\_ ... A global scope + diff --git a/rula-exec/src/lib.rs b/rula-exec/src/lib.rs index 80dc94a..04623a1 100644 --- a/rula-exec/src/lib.rs +++ b/rula-exec/src/lib.rs @@ -11,16 +11,21 @@ pub mod ruleset_gen { pub mod condition; pub mod conf_parser; pub mod factory; - pub mod generator; pub mod ruleset; + // ruleset_generator generates RuleSet in json format pub mod ruleset_generator; + // generator generateds + pub mod generator; + pub mod symbol_table; pub mod tracker; pub mod types; mod test_ruleset_generator; + use error::InternalError; use error::RuleSetGenError; type IResult = std::result::Result; + type InternalResult = std::result::Result; } #[cfg(test)] diff --git a/rula-exec/src/ruleset_gen/error.rs b/rula-exec/src/ruleset_gen/error.rs index cd5ba0e..58adc50 100644 --- a/rula-exec/src/ruleset_gen/error.rs +++ b/rula-exec/src/ruleset_gen/error.rs @@ -10,3 +10,8 @@ pub enum RuleSetGenError { ArgumentNumberError, NeedIdentifierTypeAnnotationError, } + +#[derive(Debug)] +pub enum InternalError { + ParentScopeNotFoundError, +} diff --git a/rula-exec/src/ruleset_gen/generator.rs b/rula-exec/src/ruleset_gen/generator.rs index 4d24753..8b79bc1 100644 --- a/rula-exec/src/ruleset_gen/generator.rs +++ b/rula-exec/src/ruleset_gen/generator.rs @@ -1 +1,27 @@ -// generate ruleset IR +use super::symbol_table::Scope; +use super::{symbol_table::SymbolTable, IResult}; +use rula_parser::parser::ast::*; +use ruleset_ir::RuleSetIR; +use std::cell::RefCell; +use std::rc::Rc; + +// Create symbol table to track new symbols +type RefSymbolTable = RefCell; + +// Convert RuLa expressions into RuleSet IR +pub fn generate_ir(ast_tree: &AstNode) -> IResult { + // create symbol table to track new symbols + let symbol_table = RefCell::new(SymbolTable::new()); + // prepare global scope + let global_scope = Rc::new(RefCell::new(Scope::new("__@global"))); + let generated_ir = match ast_tree { + AstNode::RuLa(rula) => generate_rula_ir(rula, &symbol_table).unwrap(), + AstNode::PlaceHolder => todo!(), + }; + + Ok(generated_ir) +} + +pub fn generate_rula_ir(rula: &RuLa, symbol_table: &RefSymbolTable) -> IResult { + Ok(RuleSetIR {}) +} diff --git a/rula-exec/src/ruleset_gen/symbol_table.rs b/rula-exec/src/ruleset_gen/symbol_table.rs new file mode 100644 index 0000000..a0a55ab --- /dev/null +++ b/rula-exec/src/ruleset_gen/symbol_table.rs @@ -0,0 +1,79 @@ +use std::collections::HashMap; + +use super::InternalResult; +use super::{error::InternalError, types::Types}; +use std::cell::RefCell; +use std::rc::{Rc, Weak}; + +type SymbolName = String; + +#[derive(Debug)] +pub struct SymbolTable { + // scope hierarchy that can be climbed up to global scope + pub scope_tree: Box, +} + +impl SymbolTable { + pub fn new() -> Self { + SymbolTable { + // default scope name "__@" will be replaced by global scope "__@global" + scope_tree: Box::new(Scope::new("__@")), + } + } +} + +// Scope Tree Node can only have one parent and could have multiple children +#[derive(Debug)] +pub struct Scope { + pub root: bool, + pub scope_name: String, + pub symbols: HashMap, + // child scope cannot make changes on parent scope + pub parent: Option>, + // child scope might be changed + pub children: RefCell>>>, +} + +impl Scope { + pub fn new(scope_name: &str) -> Self { + Scope { + root: false, + // Default scope name set in the first node + scope_name: scope_name.to_string(), + symbols: HashMap::new(), + parent: None, + children: RefCell::new(vec![]), + } + } + + pub fn add_child(&self, child: Rc>) -> InternalResult<()> { + // If there is no parent scope found, return error + match &child.borrow_mut().parent { + Some(_parent) => { /*found parent scope */ } + None => return Err(InternalError::ParentScopeNotFoundError), + } + self.children.borrow_mut().push(child); + Ok(()) + } + + pub fn set_parent(&mut self, parent: Weak){ + self.parent = Some(parent); + } + + pub fn add_symbol(&mut self, symbol_name: &str, symbol_info: SymbolInfo) { + self.symbols.insert(symbol_name.to_string(), symbol_info); + } + + pub fn get_symbol_info(&self, symbol_name: &str) -> &SymbolInfo { + self.symbols + .get(symbol_name) + .unwrap_or_else(|| panic!("Faild to get a symbol {}", symbol_name)) + } +} + +// For one symbol +#[derive(Debug)] +pub struct SymbolInfo { + // Data type used in RuLa + pub data_type: Types, +} diff --git a/rula-exec/tests/ir_gen_test.rs b/rula-exec/tests/ir_gen_test.rs new file mode 100644 index 0000000..a6ced43 --- /dev/null +++ b/rula-exec/tests/ir_gen_test.rs @@ -0,0 +1,17 @@ +use rula_exec::ruleset_gen::generator::*; + +#[cfg(test)] +mod test_generate_rula_ir { + use rula_parser::parser::ast::*; + + use super::*; + + #[test] + fn test_rula_ir() { + let rula = RuLa::new(RuLaKind::Ignore); + // let test = generate_rula_ir(&rula).unwrap(); + // for ir in test.iter(){ + // println!("{:#?}", ir); + // } + } +} diff --git a/rula-lib/src/prelude.rs b/rula-lib/src/prelude.rs index 545f952..4599e78 100644 --- a/rula-lib/src/prelude.rs +++ b/rula-lib/src/prelude.rs @@ -24,6 +24,8 @@ pub fn res( Qubit::new(qubit_index.clone()) } +pub fn __res__() {} + pub fn free(rules: RuleVec, qubit: &Qubit) { for rule in rules.borrow().iter() { rule.borrow_mut() diff --git a/ruleset-ir/src/instructions.rs b/ruleset-ir/src/instructions.rs index a540165..507c488 100644 --- a/ruleset-ir/src/instructions.rs +++ b/ruleset-ir/src/instructions.rs @@ -1,6 +1,6 @@ use crate::inst; use crate::types::*; -use crate::IR; +use crate::RuleSetIR; use crate::RSIR; // These inst!uctions are expanded to the structures @@ -90,3 +90,4 @@ inst!(DELETE_MESSAGE, READ sequence_number: RegId); // delete all messages with inst!(SEND_LINK_TOMOGRAPHY_RESULT, READ partner_addr: QNodeAddr, READ reg0: RegId, READ mem_key: MemoryKey, READ val: i64, READ time: Time); // partner addr, current count reg_id, outcome key, max_count, start_time inst!(SEND_PURIFICATION_RESULT, READ partner_addr: QNodeAddr, READ reg0: RegId /* measurement_result encoded in int */, READ reg1: RegId /* sequence_number */, READ pur_type: PurType); inst!(SEND_SWAPPING_RESULT, READ partner_addr: QNodeAddr /* receipient */, READ reg0: RegId /* pauli_op */, READ new_partner_addr: QNodeAddr /* new partner*/, READ sequence_number: RegId /* sequence_number */); +inst!(NOP, READ nop: Option); diff --git a/ruleset-ir/src/lib.rs b/ruleset-ir/src/lib.rs index ff0c980..612308c 100644 --- a/ruleset-ir/src/lib.rs +++ b/ruleset-ir/src/lib.rs @@ -4,13 +4,13 @@ pub mod instructions; pub mod types; -// will be removed -pub type IR = String; +#[derive(Debug)] +pub struct RuleSetIR; // All the ruleset instructions needs to implement this trait RuleSet IR (RSIR). // This trait implements `gen_ir` that returns a text format instruction for RuleSet pub trait RSIR { - fn gen_ir() -> IR; + fn gen_ir() -> RuleSetIR; } #[macro_export] @@ -36,8 +36,8 @@ macro_rules! inst { } impl RSIR for $inst_name { - fn gen_ir() -> IR { - "test".to_string() + fn gen_ir() -> RuleSetIR { + RuleSetIR{} } } }; @@ -62,8 +62,8 @@ macro_rules! inst { } impl RSIR for $inst_name { - fn gen_ir() -> IR { - "test".to_string() + fn gen_ir() -> RuleSetIR { + RuleSetIR{} } } }; diff --git a/ruleset-ir/src/types.rs b/ruleset-ir/src/types.rs index c703ed8..9ff0362 100644 --- a/ruleset-ir/src/types.rs +++ b/ruleset-ir/src/types.rs @@ -51,3 +51,6 @@ pub struct Time; #[derive(Debug)] pub struct PurType; + +#[derive(Debug)] +pub struct Nop; From 39fbc246af4d0446935873724f75e359bfd07de3 Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Wed, 10 May 2023 16:28:00 +0900 Subject: [PATCH 06/11] added parent reference getter --- rula-exec/src/ruleset_gen/error.rs | 1 + rula-exec/src/ruleset_gen/generator.rs | 4 +- rula-exec/src/ruleset_gen/symbol_table.rs | 46 ++++++++++++++++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/rula-exec/src/ruleset_gen/error.rs b/rula-exec/src/ruleset_gen/error.rs index 58adc50..067ca24 100644 --- a/rula-exec/src/ruleset_gen/error.rs +++ b/rula-exec/src/ruleset_gen/error.rs @@ -14,4 +14,5 @@ pub enum RuleSetGenError { #[derive(Debug)] pub enum InternalError { ParentScopeNotFoundError, + ParentScopeDroppedError, } diff --git a/rula-exec/src/ruleset_gen/generator.rs b/rula-exec/src/ruleset_gen/generator.rs index 8b79bc1..1fabff3 100644 --- a/rula-exec/src/ruleset_gen/generator.rs +++ b/rula-exec/src/ruleset_gen/generator.rs @@ -12,8 +12,10 @@ type RefSymbolTable = RefCell; pub fn generate_ir(ast_tree: &AstNode) -> IResult { // create symbol table to track new symbols let symbol_table = RefCell::new(SymbolTable::new()); - // prepare global scope + // Prepare a root global scope let global_scope = Rc::new(RefCell::new(Scope::new("__@global"))); + global_scope.borrow_mut().root = true; + let generated_ir = match ast_tree { AstNode::RuLa(rula) => generate_rula_ir(rula, &symbol_table).unwrap(), AstNode::PlaceHolder => todo!(), diff --git a/rula-exec/src/ruleset_gen/symbol_table.rs b/rula-exec/src/ruleset_gen/symbol_table.rs index a0a55ab..36707ac 100644 --- a/rula-exec/src/ruleset_gen/symbol_table.rs +++ b/rula-exec/src/ruleset_gen/symbol_table.rs @@ -29,7 +29,7 @@ pub struct Scope { pub scope_name: String, pub symbols: HashMap, // child scope cannot make changes on parent scope - pub parent: Option>, + pub parent: Option>>, // child scope might be changed pub children: RefCell>>>, } @@ -49,6 +49,7 @@ impl Scope { pub fn add_child(&self, child: Rc>) -> InternalResult<()> { // If there is no parent scope found, return error match &child.borrow_mut().parent { + // Parent information must be set before added Some(_parent) => { /*found parent scope */ } None => return Err(InternalError::ParentScopeNotFoundError), } @@ -56,10 +57,26 @@ impl Scope { Ok(()) } - pub fn set_parent(&mut self, parent: Weak){ + pub fn set_parent(&mut self, parent: Weak>) { self.parent = Some(parent); } + pub fn ref_parent(&self) -> InternalResult>>> { + match &self.parent { + Some(parent_ref) => { + // check if the parent is still alive + match parent_ref.upgrade() { + Some(parent) => Ok(Some(parent)), + None => Err(InternalError::ParentScopeDroppedError), + } + } + // Root node + None => Ok(None), + } + } + + pub fn climb_parents(&self) {} + pub fn add_symbol(&mut self, symbol_name: &str, symbol_info: SymbolInfo) { self.symbols.insert(symbol_name.to_string(), symbol_info); } @@ -77,3 +94,28 @@ pub struct SymbolInfo { // Data type used in RuLa pub data_type: Types, } + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_scope_tree_creation() { + // parent scope + let parent = Rc::new(RefCell::new(Scope::new("__@parent"))); + // child scope + let child = Rc::new(RefCell::new(Scope::new("__@child"))); + // register parent scope + child.borrow_mut().set_parent(Rc::downgrade(&parent)); + + // Check if it's possible to refer to the parent from child + let parent_ref = match child.borrow().ref_parent().unwrap() { + Some(paref) => paref, + None => { + panic!("No parents found"); + } + }; + assert_eq!(parent_ref.borrow().scope_name, String::from("__@parent")); + } +} From 07e4edf481b93bd71728c25a1720ee986d7eeb51 Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Mon, 29 May 2023 13:17:59 +0900 Subject: [PATCH 07/11] added symbol info --- rula-exec/src/ruleset_gen/error.rs | 1 + rula-exec/src/ruleset_gen/symbol_table.rs | 60 ++++++++++++++++++++--- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/rula-exec/src/ruleset_gen/error.rs b/rula-exec/src/ruleset_gen/error.rs index 067ca24..a721ce5 100644 --- a/rula-exec/src/ruleset_gen/error.rs +++ b/rula-exec/src/ruleset_gen/error.rs @@ -15,4 +15,5 @@ pub enum RuleSetGenError { pub enum InternalError { ParentScopeNotFoundError, ParentScopeDroppedError, + NoSymbolFoundError, } diff --git a/rula-exec/src/ruleset_gen/symbol_table.rs b/rula-exec/src/ruleset_gen/symbol_table.rs index 36707ac..230f2b6 100644 --- a/rula-exec/src/ruleset_gen/symbol_table.rs +++ b/rula-exec/src/ruleset_gen/symbol_table.rs @@ -75,26 +75,50 @@ impl Scope { } } - pub fn climb_parents(&self) {} - pub fn add_symbol(&mut self, symbol_name: &str, symbol_info: SymbolInfo) { self.symbols.insert(symbol_name.to_string(), symbol_info); } - pub fn get_symbol_info(&self, symbol_name: &str) -> &SymbolInfo { - self.symbols - .get(symbol_name) - .unwrap_or_else(|| panic!("Faild to get a symbol {}", symbol_name)) + pub fn get_symbol_info(&self, symbol_name: &str) -> Option { + // found in the current scope + match self.symbols.get(symbol_name) { + Some(symbol_info) => Some(symbol_info.clone()), + None => { + // get parent node + match self.ref_parent().unwrap() { + Some(parent_node) => { + let symbol = parent_node + .borrow() + .get_symbol_info(symbol_name) + .expect("Failed to find the symbol") + .clone(); + return Some(symbol); + } + None => { + // No more parent here + return None; + } + } + } + } } } // For one symbol -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SymbolInfo { // Data type used in RuLa pub data_type: Types, } +impl SymbolInfo { + pub fn new() -> Self { + SymbolInfo { + data_type: Types::Unknown, + } + } +} + #[cfg(test)] mod tests { @@ -118,4 +142,26 @@ mod tests { }; assert_eq!(parent_ref.borrow().scope_name, String::from("__@parent")); } + + #[test] + fn test_scope_tree_look_up() { + // climb up to root to find a value + // root scope + let root = Rc::new(RefCell::new(Scope::new("__@root"))); + root.borrow_mut() + .add_symbol("root_symbol", SymbolInfo::new()); + // child scope + let child = Rc::new(RefCell::new(Scope::new("__@child"))); + // grandchild + let grand_child = Rc::new(RefCell::new(Scope::new("__@grand_child"))); + + grand_child.borrow_mut().set_parent(Rc::downgrade(&child)); + child.borrow_mut().set_parent(Rc::downgrade(&root)); + + let root_symbol = child + .borrow_mut() + .get_symbol_info("root_symbol") + .expect("Failed to get symbol"); + assert_eq!(root_symbol.data_type, Types::Unknown); + } } From f68f469e6ac58a846ae2d7d74edd4b043c5ce92d Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Tue, 30 May 2023 18:29:11 +0900 Subject: [PATCH 08/11] added functions for ruleset ir --- rula-exec/src/ruleset_gen/generator.rs | 17 ++++- rula-exec/src/ruleset_gen/symbol_table.rs | 1 + ruleset-ir/src/instructions.rs | 1 - ruleset-ir/src/lib.rs | 87 ++++++++++++++++++++--- 4 files changed, 94 insertions(+), 12 deletions(-) diff --git a/rula-exec/src/ruleset_gen/generator.rs b/rula-exec/src/ruleset_gen/generator.rs index 1fabff3..4d083a4 100644 --- a/rula-exec/src/ruleset_gen/generator.rs +++ b/rula-exec/src/ruleset_gen/generator.rs @@ -1,6 +1,7 @@ use super::symbol_table::Scope; use super::{symbol_table::SymbolTable, IResult}; use rula_parser::parser::ast::*; +use ruleset_ir::instructions::*; use ruleset_ir::RuleSetIR; use std::cell::RefCell; use std::rc::Rc; @@ -24,6 +25,18 @@ pub fn generate_ir(ast_tree: &AstNode) -> IResult { Ok(generated_ir) } -pub fn generate_rula_ir(rula: &RuLa, symbol_table: &RefSymbolTable) -> IResult { - Ok(RuleSetIR {}) +fn generate_rula_ir(rula: &RuLa, symbol_table: &RefSymbolTable) -> IResult { + // In rula ast level, there is no scope introduction. It's still global scope + let generated_ir = match &*rula.rula { + RuLaKind::Program(program) => generate_program_ir(program, symbol_table).unwrap(), + // RuLaKind::Ignore => { + // // NOP::new() + // }, + _ => todo!(), + }; + Ok(generated_ir) +} + +fn generate_program_ir(program: &Program, symbol_table: &RefSymbolTable) -> IResult { + Ok(RuleSetIR::new()) } diff --git a/rula-exec/src/ruleset_gen/symbol_table.rs b/rula-exec/src/ruleset_gen/symbol_table.rs index 230f2b6..3d41d2e 100644 --- a/rula-exec/src/ruleset_gen/symbol_table.rs +++ b/rula-exec/src/ruleset_gen/symbol_table.rs @@ -85,6 +85,7 @@ impl Scope { Some(symbol_info) => Some(symbol_info.clone()), None => { // get parent node + // FIXME: Don't wanna clone match self.ref_parent().unwrap() { Some(parent_node) => { let symbol = parent_node diff --git a/ruleset-ir/src/instructions.rs b/ruleset-ir/src/instructions.rs index 507c488..866fcd5 100644 --- a/ruleset-ir/src/instructions.rs +++ b/ruleset-ir/src/instructions.rs @@ -1,6 +1,5 @@ use crate::inst; use crate::types::*; -use crate::RuleSetIR; use crate::RSIR; // These inst!uctions are expanded to the structures diff --git a/ruleset-ir/src/lib.rs b/ruleset-ir/src/lib.rs index 612308c..31fb3dd 100644 --- a/ruleset-ir/src/lib.rs +++ b/ruleset-ir/src/lib.rs @@ -4,13 +4,43 @@ pub mod instructions; pub mod types; -#[derive(Debug)] -pub struct RuleSetIR; +// A structure that stores a set of instructions defined in instructions +pub struct RuleSetIR { + instructions: Vec>, +} + +impl RuleSetIR { + pub fn new() -> Self { + RuleSetIR { + instructions: vec![], + } + } + + pub fn add_instruction(&mut self, instruction: Box) { + self.instructions.push(instruction) + } + + pub fn merge(&mut self, ruleset_ir: &mut RuleSetIR) { + // read rulesets and push back one by one + self.instructions.append(&mut ruleset_ir.instructions); + } + + pub fn export_ir(&self) -> String { + let mut ruleset_ir = String::from(""); + for inst in self.instructions.iter() { + ruleset_ir = ruleset_ir + &inst.export() + "\n"; + } + ruleset_ir + } + + pub fn import_ir(&self, _ruleset_ir: String) {} +} // All the ruleset instructions needs to implement this trait RuleSet IR (RSIR). // This trait implements `gen_ir` that returns a text format instruction for RuleSet pub trait RSIR { - fn gen_ir() -> RuleSetIR; + fn export(&self) -> String; + fn import(&self, ir: String); } #[macro_export] @@ -18,7 +48,7 @@ macro_rules! inst { // with annotation ($inst_name: ident, $($mode: ident $args: ident: $typedef: ty),* ) => { #[derive(Debug)] - struct $inst_name { + pub struct $inst_name { $( $args: $typedef, )* @@ -36,15 +66,20 @@ macro_rules! inst { } impl RSIR for $inst_name { - fn gen_ir() -> RuleSetIR { - RuleSetIR{} + fn export(&self) -> String{ + String::from("") + } + + fn import(&self, _ir: String){ + todo!("IR importing is under construction") } + } }; // without annotation (need refactor) ($inst_name: ident, $($args: ident: $typedef: ty),* ) => { #[derive(Debug)] - struct $inst_name { + pub struct $inst_name { $( $args: $typedef, )* @@ -62,9 +97,14 @@ macro_rules! inst { } impl RSIR for $inst_name { - fn gen_ir() -> RuleSetIR { - RuleSetIR{} + fn export(&self) -> String{ + String::from("") + } + + fn import(&self, _ir: String){ + todo!("IR importing is under construction") } + } }; } @@ -74,3 +114,32 @@ macro_rules! inst { fn expand() { inst!(TestInstruction, READ test: String, WRITE test2: String); } + +#[cfg(test)] +mod tests { + use crate::{ + instructions::{ADD, BITWISE_AND, SET}, + types::RegId, + RuleSetIR, + }; + + #[test] + fn test_ruleset_ir_merging() { + let mut parent_ir = RuleSetIR::new(); + // SET instruction + let set_inst_0 = SET::new(RegId::Reg0, 0); + let set_inst_1 = SET::new(RegId::Reg1, 0); + // ADD instruction + let add_inst = ADD::new(RegId::Reg0, RegId::Reg1, 1); + parent_ir.add_instruction(Box::new(set_inst_0)); + parent_ir.add_instruction(Box::new(set_inst_1)); + parent_ir.add_instruction(Box::new(add_inst)); + let mut child_ir = RuleSetIR::new(); + let bit_wise_and_inst = BITWISE_AND::new(RegId::Reg0, RegId::Reg1, 0); + child_ir.add_instruction(Box::new(bit_wise_and_inst)); + + parent_ir.merge(&mut child_ir); + + assert_eq!(parent_ir.instructions.len(), 4); + } +} From b4861f072cf982040337c0f3238c25047031a159 Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Wed, 31 May 2023 14:21:10 +0900 Subject: [PATCH 09/11] added debug formatter for ir --- ruleset-ir/src/instructions.rs | 1 + ruleset-ir/src/lib.rs | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/ruleset-ir/src/instructions.rs b/ruleset-ir/src/instructions.rs index 866fcd5..d277899 100644 --- a/ruleset-ir/src/instructions.rs +++ b/ruleset-ir/src/instructions.rs @@ -1,5 +1,6 @@ use crate::inst; use crate::types::*; +use crate::InstructionInfo; use crate::RSIR; // These inst!uctions are expanded to the structures diff --git a/ruleset-ir/src/lib.rs b/ruleset-ir/src/lib.rs index 31fb3dd..4404747 100644 --- a/ruleset-ir/src/lib.rs +++ b/ruleset-ir/src/lib.rs @@ -1,3 +1,5 @@ +use std::fmt::Debug; + #[allow(dead_code)] #[allow(non_camel_case_types)] pub mod instructions; @@ -5,6 +7,7 @@ pub mod instructions; pub mod types; // A structure that stores a set of instructions defined in instructions +#[derive(Debug)] pub struct RuleSetIR { instructions: Vec>, } @@ -39,16 +42,32 @@ impl RuleSetIR { // All the ruleset instructions needs to implement this trait RuleSet IR (RSIR). // This trait implements `gen_ir` that returns a text format instruction for RuleSet pub trait RSIR { + fn info(&self) -> InstructionInfo; fn export(&self) -> String; fn import(&self, ir: String); } +impl Debug for dyn RSIR { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let instruction_info = self.info(); + f.debug_struct("InstructionInfo") + .field("instruction name", &instruction_info.name) + .finish() + } +} + +// For debugging (Add arguments and useful information later) +pub struct InstructionInfo { + name: String, +} + #[macro_export] macro_rules! inst { // with annotation ($inst_name: ident, $($mode: ident $args: ident: $typedef: ty),* ) => { #[derive(Debug)] pub struct $inst_name { + instruction_name: String, $( $args: $typedef, )* @@ -58,6 +77,7 @@ macro_rules! inst { #[allow(dead_code)] pub fn new($($args: $typedef),*) -> Self { $inst_name { + instruction_name: stringify!($inst_name).to_string(), $( $args: $args, )* @@ -66,6 +86,12 @@ macro_rules! inst { } impl RSIR for $inst_name { + fn info(&self) -> InstructionInfo{ + InstructionInfo{ + name: self.instruction_name.clone() + } + } + fn export(&self) -> String{ String::from("") } @@ -80,6 +106,7 @@ macro_rules! inst { ($inst_name: ident, $($args: ident: $typedef: ty),* ) => { #[derive(Debug)] pub struct $inst_name { + instruction_name: String, $( $args: $typedef, )* @@ -89,6 +116,7 @@ macro_rules! inst { #[allow(dead_code)] pub fn new($($args: $typedef),*) -> Self { $inst_name { + instruction_name: stringify!($inst_name).to_string(), $( $args: $args, )* @@ -97,6 +125,12 @@ macro_rules! inst { } impl RSIR for $inst_name { + fn info(&self) -> InstructionInfo{ + InstructionInfo{ + name: self.instruction_name.clone() + } + } + fn export(&self) -> String{ String::from("") } @@ -141,5 +175,6 @@ mod tests { parent_ir.merge(&mut child_ir); assert_eq!(parent_ir.instructions.len(), 4); + println!("{:#?}", parent_ir.instructions); } } From c31b7c808f141de45d6341091a4f5784f69f0ac1 Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Wed, 31 May 2023 17:04:54 +0900 Subject: [PATCH 10/11] added program ir generator --- rula-exec/src/ruleset_gen/generator.rs | 56 ++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/rula-exec/src/ruleset_gen/generator.rs b/rula-exec/src/ruleset_gen/generator.rs index 4d083a4..1039280 100644 --- a/rula-exec/src/ruleset_gen/generator.rs +++ b/rula-exec/src/ruleset_gen/generator.rs @@ -17,26 +17,68 @@ pub fn generate_ir(ast_tree: &AstNode) -> IResult { let global_scope = Rc::new(RefCell::new(Scope::new("__@global"))); global_scope.borrow_mut().root = true; - let generated_ir = match ast_tree { + // Generate ir segment + let mut ir_segment = RuleSetIR::new(); + let mut generated_ir = match ast_tree { AstNode::RuLa(rula) => generate_rula_ir(rula, &symbol_table).unwrap(), AstNode::PlaceHolder => todo!(), }; - Ok(generated_ir) + ir_segment.merge(&mut generated_ir); + Ok(ir_segment) } fn generate_rula_ir(rula: &RuLa, symbol_table: &RefSymbolTable) -> IResult { // In rula ast level, there is no scope introduction. It's still global scope - let generated_ir = match &*rula.rula { + // Ir segment for rula_ir + let mut rula_ir_segment = RuleSetIR::new(); + let mut generated_ir = match &*rula.rula { RuLaKind::Program(program) => generate_program_ir(program, symbol_table).unwrap(), - // RuLaKind::Ignore => { - // // NOP::new() - // }, + RuLaKind::Ignore => { + let mut ignorant_ir = RuleSetIR::new(); + ignorant_ir.add_instruction(Box::new(NOP::new(None))); + ignorant_ir + } _ => todo!(), }; - Ok(generated_ir) + rula_ir_segment.merge(&mut generated_ir); + Ok(rula_ir_segment) } fn generate_program_ir(program: &Program, symbol_table: &RefSymbolTable) -> IResult { + // For program level ir, prepare segment ir for all the program asts + let mut program_ir_segment = RuleSetIR::new(); + for prog in program.programs.iter() { + let mut generated_ir = match prog { + ProgramKind::Import(import) => generate_import_ir(import, symbol_table).unwrap(), + ProgramKind::RuleSetExpr(ruleset) => { + generate_ruleset_expr_ir(ruleset, symbol_table).unwrap() + } + ProgramKind::RuleExpr(rule) => generate_rule_expr_ir(rule, symbol_table).unwrap(), + ProgramKind::Repeaters => { + todo!() + } + }; + + program_ir_segment.merge(&mut generated_ir) + } + Ok(RuleSetIR::new()) +} + +fn generate_import_ir(import: &Import, symbol_table: &RefSymbolTable) -> IResult { + Ok(RuleSetIR::new()) +} + +fn generate_ruleset_expr_ir( + ruleset_expr: &RuleSetExpr, + symbol_table: &RefSymbolTable, +) -> IResult { + Ok(RuleSetIR::new()) +} + +fn generate_rule_expr_ir( + rule_expr: &RuleExpr, + symbol_table: &RefSymbolTable, +) -> IResult { Ok(RuleSetIR::new()) } From 136cae4ce2b974f4b1707330cab86517e499a0bc Mon Sep 17 00:00:00 2001 From: Chibikuri Date: Mon, 12 Jun 2023 20:29:09 +0900 Subject: [PATCH 11/11] restructured --- rula-exec/src/generator/error.rs | 5 + .../{ruleset_gen => generator}/generator.rs | 51 ++++++--- .../symbol_table.rs => generator/scope.rs} | 103 ++++-------------- rula-exec/src/generator/symbol_table.rs | 80 ++++++++++++++ rula-exec/src/generator/types.rs | 5 + rula-exec/src/lib.rs | 17 ++- rula-exec/tests/ir_gen_test.rs | 28 ++--- ruleset-ir/src/lib.rs | 31 +++++- 8 files changed, 201 insertions(+), 119 deletions(-) create mode 100644 rula-exec/src/generator/error.rs rename rula-exec/src/{ruleset_gen => generator}/generator.rs (57%) rename rula-exec/src/{ruleset_gen/symbol_table.rs => generator/scope.rs} (52%) create mode 100644 rula-exec/src/generator/symbol_table.rs create mode 100644 rula-exec/src/generator/types.rs diff --git a/rula-exec/src/generator/error.rs b/rula-exec/src/generator/error.rs new file mode 100644 index 0000000..d890de2 --- /dev/null +++ b/rula-exec/src/generator/error.rs @@ -0,0 +1,5 @@ +#[derive(Debug)] +pub enum CompileError{ + ParentScopeNotFoundError, + ParentScopeDroppedError, +} \ No newline at end of file diff --git a/rula-exec/src/ruleset_gen/generator.rs b/rula-exec/src/generator/generator.rs similarity index 57% rename from rula-exec/src/ruleset_gen/generator.rs rename to rula-exec/src/generator/generator.rs index 1039280..3b3e376 100644 --- a/rula-exec/src/ruleset_gen/generator.rs +++ b/rula-exec/src/generator/generator.rs @@ -1,4 +1,4 @@ -use super::symbol_table::Scope; +use super::scope::Scope; use super::{symbol_table::SymbolTable, IResult}; use rula_parser::parser::ast::*; use ruleset_ir::instructions::*; @@ -7,20 +7,21 @@ use std::cell::RefCell; use std::rc::Rc; // Create symbol table to track new symbols -type RefSymbolTable = RefCell; +// type RefSymbolTable = RefCell; +type RcRefCellScope = Rc>; // Convert RuLa expressions into RuleSet IR pub fn generate_ir(ast_tree: &AstNode) -> IResult { // create symbol table to track new symbols - let symbol_table = RefCell::new(SymbolTable::new()); + // let symbol_table = RefCell::new(SymbolTable::new()); // Prepare a root global scope let global_scope = Rc::new(RefCell::new(Scope::new("__@global"))); - global_scope.borrow_mut().root = true; + global_scope.borrow_mut().set_root(); // Generate ir segment let mut ir_segment = RuleSetIR::new(); let mut generated_ir = match ast_tree { - AstNode::RuLa(rula) => generate_rula_ir(rula, &symbol_table).unwrap(), + AstNode::RuLa(rula) => generate_rula_ir(rula, &global_scope).unwrap(), AstNode::PlaceHolder => todo!(), }; @@ -28,12 +29,12 @@ pub fn generate_ir(ast_tree: &AstNode) -> IResult { Ok(ir_segment) } -fn generate_rula_ir(rula: &RuLa, symbol_table: &RefSymbolTable) -> IResult { - // In rula ast level, there is no scope introduction. It's still global scope +fn generate_rula_ir(rula: &RuLa, parent_scope: &RcRefCellScope) -> IResult { + // At this level, new scope is not introduced. // Ir segment for rula_ir let mut rula_ir_segment = RuleSetIR::new(); let mut generated_ir = match &*rula.rula { - RuLaKind::Program(program) => generate_program_ir(program, symbol_table).unwrap(), + RuLaKind::Program(program) => generate_program_ir(program, &parent_scope).unwrap(), RuLaKind::Ignore => { let mut ignorant_ir = RuleSetIR::new(); ignorant_ir.add_instruction(Box::new(NOP::new(None))); @@ -45,16 +46,16 @@ fn generate_rula_ir(rula: &RuLa, symbol_table: &RefSymbolTable) -> IResult IResult { +fn generate_program_ir(program: &Program, parent_scope: &RcRefCellScope) -> IResult { // For program level ir, prepare segment ir for all the program asts let mut program_ir_segment = RuleSetIR::new(); for prog in program.programs.iter() { let mut generated_ir = match prog { - ProgramKind::Import(import) => generate_import_ir(import, symbol_table).unwrap(), + ProgramKind::Import(import) => generate_import_ir(import, parent_scope).unwrap(), ProgramKind::RuleSetExpr(ruleset) => { - generate_ruleset_expr_ir(ruleset, symbol_table).unwrap() + generate_ruleset_expr_ir(ruleset, parent_scope).unwrap() } - ProgramKind::RuleExpr(rule) => generate_rule_expr_ir(rule, symbol_table).unwrap(), + ProgramKind::RuleExpr(rule) => generate_rule_expr_ir(rule, parent_scope).unwrap(), ProgramKind::Repeaters => { todo!() } @@ -62,23 +63,41 @@ fn generate_program_ir(program: &Program, symbol_table: &RefSymbolTable) -> IRes program_ir_segment.merge(&mut generated_ir) } - Ok(RuleSetIR::new()) + Ok(program_ir_segment) } -fn generate_import_ir(import: &Import, symbol_table: &RefSymbolTable) -> IResult { +fn generate_import_ir(import: &Import, parent_scope: &RcRefCellScope) -> IResult { + + Ok(RuleSetIR::new()) } fn generate_ruleset_expr_ir( ruleset_expr: &RuleSetExpr, - symbol_table: &RefSymbolTable, + parent_scope: &RcRefCellScope, ) -> IResult { + let ruleset_name = &*ruleset_expr.name.name; + + // Introduce a new scope for ruleset clause + let ruleset_scope_name = String::from("__@ruleset_") + ruleset_name; + let ruleset_scope = Rc::new(RefCell::new(Scope::new(&ruleset_scope_name))); + ruleset_scope.borrow_mut().set_parent(Rc::downgrade(&parent_scope)); + + // Ok(RuleSetIR::new()) } fn generate_rule_expr_ir( rule_expr: &RuleExpr, - symbol_table: &RefSymbolTable, + parent_scope: &RcRefCellScope, ) -> IResult { + let rule_name = &*rule_expr.name.name; + + // Introduce a new scope for rule clause + let rule_scope_name = String::from("__@rule_") + rule_name; + let rule_scope = Rc::new(RefCell::new(Scope::new(&rule_scope_name))); + rule_scope.borrow_mut().set_parent(Rc::downgrade(&parent_scope)); + + Ok(RuleSetIR::new()) } diff --git a/rula-exec/src/ruleset_gen/symbol_table.rs b/rula-exec/src/generator/scope.rs similarity index 52% rename from rula-exec/src/ruleset_gen/symbol_table.rs rename to rula-exec/src/generator/scope.rs index 3d41d2e..2bfe616 100644 --- a/rula-exec/src/ruleset_gen/symbol_table.rs +++ b/rula-exec/src/generator/scope.rs @@ -1,27 +1,13 @@ use std::collections::HashMap; -use super::InternalResult; -use super::{error::InternalError, types::Types}; +use super::IResult; +use super::error::CompileError; +use super::symbol_table::SymbolInfo; use std::cell::RefCell; use std::rc::{Rc, Weak}; type SymbolName = String; -#[derive(Debug)] -pub struct SymbolTable { - // scope hierarchy that can be climbed up to global scope - pub scope_tree: Box, -} - -impl SymbolTable { - pub fn new() -> Self { - SymbolTable { - // default scope name "__@" will be replaced by global scope "__@global" - scope_tree: Box::new(Scope::new("__@")), - } - } -} - // Scope Tree Node can only have one parent and could have multiple children #[derive(Debug)] pub struct Scope { @@ -46,12 +32,23 @@ impl Scope { } } - pub fn add_child(&self, child: Rc>) -> InternalResult<()> { + pub fn set_root(&mut self) { + match &self.parent { + Some(_parent) => { + panic!("A scope that has parent scope cannot be a root scope") + } + None => { + self.root = true; + } + } + } + + pub fn add_child(&self, child: Rc>) -> IResult<()> { // If there is no parent scope found, return error match &child.borrow_mut().parent { // Parent information must be set before added Some(_parent) => { /*found parent scope */ } - None => return Err(InternalError::ParentScopeNotFoundError), + None => return Err(CompileError::ParentScopeNotFoundError), } self.children.borrow_mut().push(child); Ok(()) @@ -61,13 +58,13 @@ impl Scope { self.parent = Some(parent); } - pub fn ref_parent(&self) -> InternalResult>>> { + pub fn ref_parent(&self) -> IResult>>> { match &self.parent { Some(parent_ref) => { // check if the parent is still alive match parent_ref.upgrade() { Some(parent) => Ok(Some(parent)), - None => Err(InternalError::ParentScopeDroppedError), + None => Err(CompileError::ParentScopeDroppedError), } } // Root node @@ -103,66 +100,4 @@ impl Scope { } } } -} - -// For one symbol -#[derive(Debug, Clone)] -pub struct SymbolInfo { - // Data type used in RuLa - pub data_type: Types, -} - -impl SymbolInfo { - pub fn new() -> Self { - SymbolInfo { - data_type: Types::Unknown, - } - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn test_scope_tree_creation() { - // parent scope - let parent = Rc::new(RefCell::new(Scope::new("__@parent"))); - // child scope - let child = Rc::new(RefCell::new(Scope::new("__@child"))); - // register parent scope - child.borrow_mut().set_parent(Rc::downgrade(&parent)); - - // Check if it's possible to refer to the parent from child - let parent_ref = match child.borrow().ref_parent().unwrap() { - Some(paref) => paref, - None => { - panic!("No parents found"); - } - }; - assert_eq!(parent_ref.borrow().scope_name, String::from("__@parent")); - } - - #[test] - fn test_scope_tree_look_up() { - // climb up to root to find a value - // root scope - let root = Rc::new(RefCell::new(Scope::new("__@root"))); - root.borrow_mut() - .add_symbol("root_symbol", SymbolInfo::new()); - // child scope - let child = Rc::new(RefCell::new(Scope::new("__@child"))); - // grandchild - let grand_child = Rc::new(RefCell::new(Scope::new("__@grand_child"))); - - grand_child.borrow_mut().set_parent(Rc::downgrade(&child)); - child.borrow_mut().set_parent(Rc::downgrade(&root)); - - let root_symbol = child - .borrow_mut() - .get_symbol_info("root_symbol") - .expect("Failed to get symbol"); - assert_eq!(root_symbol.data_type, Types::Unknown); - } -} +} \ No newline at end of file diff --git a/rula-exec/src/generator/symbol_table.rs b/rula-exec/src/generator/symbol_table.rs new file mode 100644 index 0000000..deb0225 --- /dev/null +++ b/rula-exec/src/generator/symbol_table.rs @@ -0,0 +1,80 @@ +use super::scope::Scope; +use super::types::Types; + +#[derive(Debug)] +pub struct SymbolTable { + // scope hierarchy that can be climbed up to global scope + pub scope_tree: Box, +} + +impl SymbolTable { + pub fn new() -> Self { + SymbolTable { + // default scope name "__@" will be replaced by global scope "__@global" + scope_tree: Box::new(Scope::new("__@")), + } + } +} + +// For one symbol +#[derive(Debug, Clone)] +pub struct SymbolInfo { + // Data type used in RuLa + pub data_type: Types, +} + +impl SymbolInfo { + pub fn new() -> Self { + SymbolInfo { + data_type: Types::Unknown, + } + } +} + +#[cfg(test)] +mod tests { + use std::rc::Rc; + use std::cell::RefCell; + use super::*; + + #[test] + fn test_scope_tree_creation() { + // parent scope + let parent = Rc::new(RefCell::new(Scope::new("__@parent"))); + // child scope + let child = Rc::new(RefCell::new(Scope::new("__@child"))); + // register parent scope + child.borrow_mut().set_parent(Rc::downgrade(&parent)); + + // Check if it's possible to refer to the parent from child + let parent_ref = match child.borrow().ref_parent().unwrap() { + Some(paref) => paref, + None => { + panic!("No parents found"); + } + }; + assert_eq!(parent_ref.borrow().scope_name, String::from("__@parent")); + } + + #[test] + fn test_scope_tree_look_up() { + // climb up to root to find a value + // root scope + let root = Rc::new(RefCell::new(Scope::new("__@root"))); + root.borrow_mut() + .add_symbol("root_symbol", SymbolInfo::new()); + // child scope + let child = Rc::new(RefCell::new(Scope::new("__@child"))); + // grandchild + let grand_child = Rc::new(RefCell::new(Scope::new("__@grand_child"))); + + grand_child.borrow_mut().set_parent(Rc::downgrade(&child)); + child.borrow_mut().set_parent(Rc::downgrade(&root)); + + let root_symbol = child + .borrow_mut() + .get_symbol_info("root_symbol") + .expect("Failed to get symbol"); + assert_eq!(root_symbol.data_type, Types::Unknown); + } +} diff --git a/rula-exec/src/generator/types.rs b/rula-exec/src/generator/types.rs new file mode 100644 index 0000000..f934480 --- /dev/null +++ b/rula-exec/src/generator/types.rs @@ -0,0 +1,5 @@ + +#[derive(Debug, Clone, PartialEq)] +pub enum Types{ + Unknown +} \ No newline at end of file diff --git a/rula-exec/src/lib.rs b/rula-exec/src/lib.rs index 04623a1..896a15f 100644 --- a/rula-exec/src/lib.rs +++ b/rula-exec/src/lib.rs @@ -2,7 +2,21 @@ extern crate quote; extern crate syn; +pub mod generator{ + pub mod generator; + pub mod symbol_table; + pub mod scope; + pub mod types; + + #[cfg(not(tarpaulin_include))] + mod error; + + use error::CompileError; + type IResult = std::result::Result; +} + // Generator of ruleset +#[deprecated] pub mod ruleset_gen { #[cfg(not(tarpaulin_include))] mod error; @@ -14,9 +28,6 @@ pub mod ruleset_gen { pub mod ruleset; // ruleset_generator generates RuleSet in json format pub mod ruleset_generator; - // generator generateds - pub mod generator; - pub mod symbol_table; pub mod tracker; pub mod types; diff --git a/rula-exec/tests/ir_gen_test.rs b/rula-exec/tests/ir_gen_test.rs index a6ced43..4874a79 100644 --- a/rula-exec/tests/ir_gen_test.rs +++ b/rula-exec/tests/ir_gen_test.rs @@ -1,17 +1,17 @@ -use rula_exec::ruleset_gen::generator::*; +// use rula_exec::ruleset_gen::generator::*; -#[cfg(test)] -mod test_generate_rula_ir { - use rula_parser::parser::ast::*; +// #[cfg(test)] +// mod test_generate_rula_ir { +// use rula_parser::parser::ast::*; - use super::*; +// use super::*; - #[test] - fn test_rula_ir() { - let rula = RuLa::new(RuLaKind::Ignore); - // let test = generate_rula_ir(&rula).unwrap(); - // for ir in test.iter(){ - // println!("{:#?}", ir); - // } - } -} +// #[test] +// fn test_rula_ir() { +// let rula = RuLa::new(RuLaKind::Ignore); +// // let test = generate_rula_ir(&rula).unwrap(); +// // for ir in test.iter(){ +// // println!("{:#?}", ir); +// // } +// } +// } diff --git a/ruleset-ir/src/lib.rs b/ruleset-ir/src/lib.rs index 4404747..6ca5fcd 100644 --- a/ruleset-ir/src/lib.rs +++ b/ruleset-ir/src/lib.rs @@ -152,8 +152,8 @@ fn expand() { #[cfg(test)] mod tests { use crate::{ - instructions::{ADD, BITWISE_AND, SET}, - types::RegId, + instructions::{ADD, BITWISE_AND, RET, SET}, + types::{RegId, ReturnCode}, RuleSetIR, }; @@ -177,4 +177,31 @@ mod tests { assert_eq!(parent_ir.instructions.len(), 4); println!("{:#?}", parent_ir.instructions); } + + #[test] + fn test_merging_multiple_ruleset_ir() { + let mut parent_ir = RuleSetIR::new(); + // RET instruction + let ret_inst = RET::new(ReturnCode::Nothing); + parent_ir.add_instruction(Box::new(ret_inst)); + + let mut child_ir1 = RuleSetIR::new(); + child_ir1.add_instruction(Box::new(ADD::new(RegId::Reg0, RegId::Reg1, 1))); + + let mut child_ir2 = RuleSetIR::new(); + child_ir2.add_instruction(Box::new(ADD::new(RegId::Reg0, RegId::Reg1, 1))); + + let mut child_ir3 = RuleSetIR::new(); + child_ir3.add_instruction(Box::new(ADD::new(RegId::Reg1, RegId::Reg2, 1))); + + let ruleset_irs = vec![child_ir1, child_ir2, child_ir3]; + + for mut ir in ruleset_irs.into_iter() { + parent_ir.merge(&mut ir); + } + + // The number of instrucitons must be 4 () + assert_eq!(parent_ir.instructions.len(), 4); + println!("{:#?}", parent_ir.instructions); + } }