diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..92a8d7c Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 088ba6b..945c20d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,12 @@ # Generated by Cargo # will have compiled files and executables -/target/ + +**/target # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html Cargo.lock + # These are backup files generated by rustfmt **/*.rs.bk diff --git a/assignment_2/calculator_macro/Cargo.toml b/assignment_2/calculator_macro/Cargo.toml new file mode 100644 index 0000000..bc3e70c --- /dev/null +++ b/assignment_2/calculator_macro/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "hello_macro" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +derive_macro = { path = "./derive_macro" } diff --git a/assignment_2/calculator_macro/Readme.md b/assignment_2/calculator_macro/Readme.md new file mode 100644 index 0000000..1824358 --- /dev/null +++ b/assignment_2/calculator_macro/Readme.md @@ -0,0 +1,22 @@ +## Calculator Macro + +### Description + +This is a derive macro for calculator. This macro implements the functionalities of addition, subtraction, multiplication and modulus. + +### Usage + +create a necessary methods + +``` +#[derive(Calculator)] +#[Operation = Addition] +pub struct Task1{ + op1 : i32, + op2 : i32, +} +``` + +### References + +- [Macros](https://doc.rust-lang.org/reference/procedural-macros.html) diff --git a/assignment_2/calculator_macro/derive_macro/Cargo.toml b/assignment_2/calculator_macro/derive_macro/Cargo.toml new file mode 100644 index 0000000..738e6b4 --- /dev/null +++ b/assignment_2/calculator_macro/derive_macro/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "derive_macro" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +proc-macro = true + +[dependencies] +syn = {version="1.0.95",features = ["extra-traits"]} +quote = "1.0.18" +# proc-macro2 = "1.0.64" diff --git a/assignment_2/calculator_macro/derive_macro/src/add.rs b/assignment_2/calculator_macro/derive_macro/src/add.rs new file mode 100644 index 0000000..ba55c3e --- /dev/null +++ b/assignment_2/calculator_macro/derive_macro/src/add.rs @@ -0,0 +1,19 @@ +use super::*; +use syn::Ident; + +pub fn impl_add(struct_name: Ident) -> TokenStream { + + let methods = quote! { + impl #struct_name{ + + pub fn add(&self) -> i32 { + self.op1 + self.op2 + } + pub fn run(&self) -> i32{ + self.add() + } + + } + }; +methods.into() +} \ No newline at end of file diff --git a/assignment_2/calculator_macro/derive_macro/src/lib.rs b/assignment_2/calculator_macro/derive_macro/src/lib.rs new file mode 100644 index 0000000..3d6f160 --- /dev/null +++ b/assignment_2/calculator_macro/derive_macro/src/lib.rs @@ -0,0 +1,65 @@ +use std::collections::HashMap; +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, DeriveInput}; +mod add; +use add::*; +mod sub; +use sub::*; +mod mul; +use mul::*; +mod modul; +use modul::*; + + +#[proc_macro_derive(Calculator, attributes(Operation))] +pub fn calculator(input: TokenStream) -> TokenStream { +let ast = parse_macro_input!(input as DeriveInput); +impl_calculator(ast) +} + +fn impl_calculator(ast: DeriveInput) -> TokenStream { + let calc = ast.ident.clone(); + let attribute_args = ast.attrs; + + let mut property_map: HashMap = HashMap::new(); + + for attribute in attribute_args.into_iter() { + let (path, value) = match attribute.parse_meta().unwrap() { + syn::Meta::NameValue(syn::MetaNameValue { + path, + lit: syn::Lit::Str(s), + .. + }) => (path, s.value()), + _ => (syn::Path::into(attribute.path), "".to_string()), + }; + + for segment in path.segments { + property_map.insert(segment.ident.to_string(), value.clone()); + } + } + + let operation = property_map["Operation"].clone(); + + let mut methods = quote! {}; + + if operation == "addition" { + methods = impl_add(calc).into(); + } else if operation == "subtraction" { + methods = impl_sub(calc).into(); + } else if operation == "multiplication" { + methods = impl_mul(calc).into(); + } else if operation == "modulus" { + methods = impl_modul(calc).into(); + } else { + } + + // methods.into() + + let ast= quote! { + #methods + }; + ast.into() + + +} diff --git a/assignment_2/calculator_macro/derive_macro/src/modul.rs b/assignment_2/calculator_macro/derive_macro/src/modul.rs new file mode 100644 index 0000000..bfeecc3 --- /dev/null +++ b/assignment_2/calculator_macro/derive_macro/src/modul.rs @@ -0,0 +1,18 @@ +use super::*; +use syn::Ident; + +pub fn impl_modul(struct_name: Ident) -> TokenStream { + + let methods = quote! { + impl #struct_name{ + + pub fn modu(&self) -> i32 { + self.op1 / self.op2 + } + pub fn run(&self) -> i32{ + self.modu() + } + } + }; +methods.into() +} \ No newline at end of file diff --git a/assignment_2/calculator_macro/derive_macro/src/mul.rs b/assignment_2/calculator_macro/derive_macro/src/mul.rs new file mode 100644 index 0000000..8bc0089 --- /dev/null +++ b/assignment_2/calculator_macro/derive_macro/src/mul.rs @@ -0,0 +1,18 @@ +use super::*; +use syn::Ident; + +pub fn impl_mul(struct_name: Ident) -> TokenStream { + + let methods = quote! { + impl #struct_name{ + + pub fn mul(&self) -> i32 { + self.op1 * self.op2 + } + pub fn run(&self) -> i32{ + self.mul() + } + } + }; +methods.into() +} \ No newline at end of file diff --git a/assignment_2/calculator_macro/derive_macro/src/sub.rs b/assignment_2/calculator_macro/derive_macro/src/sub.rs new file mode 100644 index 0000000..6b81607 --- /dev/null +++ b/assignment_2/calculator_macro/derive_macro/src/sub.rs @@ -0,0 +1,18 @@ +use super::*; +use syn::Ident; + +pub fn impl_sub(struct_name: Ident) -> TokenStream { + + let methods = quote! { + impl #struct_name{ + + pub fn sub(&self) -> i32 { + self.op1 - self.op2 + } + pub fn run(&self) -> i32{ + self.sub() + } + } + }; +methods.into() +} \ No newline at end of file diff --git a/assignment_2/calculator_macro/src/main.rs b/assignment_2/calculator_macro/src/main.rs new file mode 100644 index 0000000..1e671ab --- /dev/null +++ b/assignment_2/calculator_macro/src/main.rs @@ -0,0 +1,83 @@ +use derive_macro::Calculator; + +trait Calc{ + fn execute(&self) -> i32 ; +} + +#[derive(Debug)] +#[derive(Calculator)] +#[Operation = "addition"] +struct Task1 { + op1 : i32, + op2 : i32, +} + +impl Calc for Task1{ + fn execute( &self) -> i32{ + println!("Addition of two numbers {},{} is {}", self.op1, self.op2, self.run()); + return self.run() + } +} + +#[derive(Calculator)] +#[Operation = "subtraction"] +struct Task2{ + op1 : i32, + op2 : i32, +} + +impl Calc for Task2{ + fn execute(&self) -> i32{ + println!("Subtracion of two numbers {},{} is {} ", self.op1, self.op2, self.run()); + return self.run() + } +} + +#[derive(Calculator)] +#[Operation = "multiplication"] +struct Task3{ + op1 : i32, + op2 : i32, +} + +impl Calc for Task3{ + fn execute(&self) -> i32{ + println!("Multiplication of two numbers {},{} is {}", self.op1, self.op2, self.run()); + return self.run() + } + } + +#[derive(Calculator)] +#[Operation = "modulus"] +struct Task4{ + op1 : i32, + op2 : i32, +} + +impl Calc for Task4{ + fn execute(&self) -> i32{ + println!("Modulus of two numbers {},{} is {}", self.op1, self.op2, self.run()); + return self.run() + } + } + +fn main() { + + let mut array: Vec> = Vec::new(); + + let add = Task1 {op1:2, op2:2}; + let sub = Task2 {op1:2, op2:2}; + let mul = Task3 {op1:3, op2:3}; + let modul = Task4 {op1:2, op2:2}; + + array.push(Box::new(add)); + array.push(Box::new(sub)); + array.push(Box::new(mul)); + array.push(Box::new(modul)); + + for i in array{ + i.execute(); + } + + +}