diff --git a/Cargo.lock b/Cargo.lock index ea12932..77834f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.8.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", "humantime", diff --git a/Cargo.toml b/Cargo.toml index 267034d..e8dbe06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ rand = {version = "0.7.3"} rand_chacha = "*" clap = { version = "3.2.8", features = ["derive"] } uuid = { version = "0.8.1", features = ["serde", "v4"] } -log = "0.4.0" -env_logger = "0.8.4" +log = "0.4.17" +env_logger = "0.9.0" serde = { version = "1.0", features = ["derive"] } serde_json = "*" diff --git a/client.gpsl b/client.gpsl index 2a5fd0e..c81eee0 100644 --- a/client.gpsl +++ b/client.gpsl @@ -1,4 +1,9 @@ -fn main() { - send("test"); - println(receive()); + +#[server(ip = "localhost:8080")] +fn add(a: num, b: num) { + return a + b; +} + +fn main() { + println(add(1, 2)); } diff --git a/server.gpsl b/server.gpsl index 8caaea0..5aaa61a 100644 --- a/server.gpsl +++ b/server.gpsl @@ -1,3 +1,4 @@ +#[server(ip = "localhost:8080")] fn main() { send(receive()); } diff --git a/src/gpsl/external_function.rs b/src/gpsl/external_function.rs index a2d9fc4..2aa3285 100644 --- a/src/gpsl/external_function.rs +++ b/src/gpsl/external_function.rs @@ -1,4 +1,4 @@ -use serde::Deserializer; +use serde::{Deserialize, Deserializer, Serialize}; use crate::gpsl::{permission::Permission, variable::Variable}; use std::{ @@ -7,7 +7,7 @@ use std::{ sync::{Arc, Mutex}, }; -#[derive(PartialEq)] +#[derive(PartialEq, Debug, Serialize, Deserialize)] pub enum ExternalFuncStatus { SUCCESS, NOTFOUND, @@ -15,23 +15,19 @@ pub enum ExternalFuncStatus { REJECTED, } +#[derive(Debug, Serialize, Deserialize)] pub struct ExternalFuncReturn { pub status: ExternalFuncStatus, pub value: Option, } -pub struct ExternalFuncCallData { - pub stream: Arc>>, -} - #[allow(dead_code)] pub const STD_FUNC: fn( String, Vec, Vec, Vec, - Option, -) -> ExternalFuncReturn = |name, args, accept, reject, data| { +) -> ExternalFuncReturn = |name, args, accept, reject| { let name = name.as_str(); match name { "println" => { @@ -69,42 +65,42 @@ pub const STD_FUNC: fn( value: None, } } - } + } /* "receive" => { - println!("Waiting for client..."); - let mut buffer = String::default(); - let data = data.unwrap(); - let mut stream = data.stream.lock().unwrap(); + println!("Waiting for client..."); + let mut buffer = String::default(); + let data = data.unwrap(); + let mut stream = data.stream.lock().unwrap(); - let stream = match &mut *stream { - Some(stream) => stream, - None => panic!("Cannot access to tcp stream"), - }; - let mut reader = BufReader::new(stream); - reader.read_line(&mut buffer).unwrap(); - ExternalFuncReturn { - status: ExternalFuncStatus::SUCCESS, - value: Some(serde_json::from_str(&buffer).unwrap()), - } + let stream = match &mut *stream { + Some(stream) => stream, + None => panic!("Cannot access to tcp stream"), + }; + let mut reader = BufReader::new(stream); + reader.read_line(&mut buffer).unwrap(); + ExternalFuncReturn { + status: ExternalFuncStatus::SUCCESS, + value: Some(serde_json::from_str(&buffer).unwrap()), + } } "send" => { - let data = data.unwrap(); - let mut stream = data.stream.lock().unwrap(); + let data = data.unwrap(); + let mut stream = data.stream.lock().unwrap(); - let stream = match &mut *stream { - Some(stream) => stream, - None => panic!("Cannot access to tcp stream"), - }; + let stream = match &mut *stream { + Some(stream) => stream, + None => panic!("Cannot access to tcp stream"), + }; - let value = serde_json::to_string(&args[0]).unwrap(); + let value = serde_json::to_string(&args[0]).unwrap(); - stream.write_fmt(format_args!("{}\n", value)).unwrap(); + stream.write_fmt(format_args!("{}\n", value)).unwrap(); - ExternalFuncReturn { - status: ExternalFuncStatus::SUCCESS, - value: None, - } + ExternalFuncReturn { + status: ExternalFuncStatus::SUCCESS, + value: None, } + }*/ _ => ExternalFuncReturn { status: ExternalFuncStatus::NOTFOUND, value: None, diff --git a/src/gpsl/grammar/GpslParser.g4 b/src/gpsl/grammar/GpslParser.g4 index 1c460c0..31a8f49 100644 --- a/src/gpsl/grammar/GpslParser.g4 +++ b/src/gpsl/grammar/GpslParser.g4 @@ -3,7 +3,7 @@ options { tokenVocab = GpslLexer; } gpslFile: function* EOF ; -function: FN IDENT LPAREN (IDENT COLON IDENT COMMA?)* RPAREN (ARROW IDENT)? block ; +function: attribute? FN IDENT LPAREN (IDENT COLON IDENT COMMA?)* RPAREN (ARROW IDENT)? block ; program: stmt* ; @@ -23,6 +23,8 @@ if: IF LPAREN expr RPAREN stmt (ELSE stmt)? ; while: WHILE LPAREN expr RPAREN stmt ; for: FOR LPAREN expr? SEMICOLON expr? SEMICOLON expr? RPAREN stmt ; + +attribute: SHARP LBRACKET IDENT (assign COMMA?)* RBRACKET ; mode: SHARP IDENT ; permission: DOLLER LPAREN ( IDENT LBRACKET ( IDENT COMMA? )* RBRACKET COMMA? )* RPAREN ; diff --git a/src/gpsl/node.rs b/src/gpsl/node.rs index e8594f6..b67d95c 100644 --- a/src/gpsl/node.rs +++ b/src/gpsl/node.rs @@ -1,6 +1,8 @@ use std::collections::HashMap; -#[derive(Debug, PartialEq, Clone)] +use serde::{Deserialize, Serialize}; + +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub enum NodeKind { ASSIGN, ADD, @@ -13,12 +15,18 @@ pub enum NodeKind { LE, // <= } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum Node { Function { name: String, - args: HashMap, + args_name: Vec, + args_type: Vec, body: Vec>, + attribute: Option>, + }, + Attribute { + name: String, + args: Vec>, }, Mode { mode: String, @@ -87,4 +95,24 @@ impl Node { pub fn new_lvar_node(value: String) -> Box { Box::new(Node::Lvar { value }) } + + pub fn extract_string(&self) -> String { + match self { + Node::Text { value } => value.clone(), + Node::Number { value } => value.to_string(), + Node::Lvar { value } => value.clone(), + _ => String::new(), + } + } + + pub fn extract_function_args(&self) -> (Vec, Vec) { + match self { + Node::Function { + args_name, + args_type, + .. + } => (args_name.clone(), args_type.clone()), + _ => (Vec::new(), Vec::new()), + } + } } diff --git a/src/gpsl/parser.rs b/src/gpsl/parser.rs index a5c017c..fbcf16d 100644 --- a/src/gpsl/parser.rs +++ b/src/gpsl/parser.rs @@ -1,7 +1,9 @@ use crate::gpsl::node::*; use crate::gpsl::token::*; use crate::gpsl::tokenizer::*; +use env_logger; use log::*; +use log::{debug, error, info, warn}; use std::collections::HashMap; #[derive(Clone)] @@ -29,40 +31,57 @@ impl Parser { function: FN IDENT LPAREN (IDENT COLON IDENT COMMA?)* RPAREN (ARROW IDENT)? block ; */ pub fn function(&mut self) -> Result, String> { + // parse attribute + let attribute = if self.tokenizer.current_token().str == String::from("#") { + println!("{:?}", self.tokenizer.current_token()); + Some(self.attribute()?) + } else { + Some(Box::new(Node::Attribute { + name: String::from(""), + args: vec![], + })) + }; + + println!("{:?}", self.tokenizer.current_token()); + if self .tokenizer .consume_kind_str(TokenKind::RESERVED, String::from("fn")) { - debug!("parsing function"); + debug!("{}: parsing function", line!()); let func_name = self.tokenizer.current_token().clone(); self.tokenizer.expect_kind(TokenKind::IDENT)?; - let mut args = HashMap::new(); + let mut args_name = vec![]; + let mut args_type = vec![]; self.tokenizer.expect(String::from("("))?; - debug!("parsing args"); + debug!("{}: parsing args", line!()); while !self .tokenizer .consume_kind_str(TokenKind::RESERVED, String::from(")")) { - debug!("consume argument"); + debug!("{}: consume argument", line!()); let name = self.tokenizer.expect_ident()?; self.tokenizer .consume_kind_str(TokenKind::RESERVED, String::from(":")); let type_str = self.tokenizer.expect_ident()?; self.tokenizer .consume_kind_str(TokenKind::RESERVED, String::from(",")); - args.insert(name, type_str); + args_name.push(name); + args_type.push(type_str); } let mut nodes: Vec> = vec![]; - debug!("parsing body node"); + debug!("{}: parsing body node", line!()); loop { nodes.push(self.stmt()?); - debug!("body nodes parsed"); + debug!("{}: body nodes parsed", line!()); //self.tokenizer.expect(String::from("}"))?; return Ok(Box::new(Node::Function { name: func_name.str, - args, + args_name, + args_type, body: nodes, + attribute, })); } } else { @@ -112,14 +131,14 @@ impl Parser { })); } - debug!("parsing permission"); + debug!("{}: parsing permission", line!()); let permission = if self.tokenizer.current_token().str == "$" { Some(self.permission()?) } else { None }; - debug!("parsing mode"); + debug!("{}: parsing mode", line!()); let mode = if self.tokenizer.current_token().str == "#" { Some(self.mode()?) } else { @@ -228,6 +247,33 @@ impl Parser { return node; } + /* + attribute: SHARP LBRACKET IDENT LPAREN (assign COMMA?)* RPAREN RBRACKET ; + */ + pub fn attribute(&mut self) -> Result, String> { + self.tokenizer.expect(String::from("#"))?; + self.tokenizer.expect(String::from("["))?; + let name = self.tokenizer.current_token().clone(); + self.tokenizer.expect_kind(TokenKind::IDENT)?; + self.tokenizer.expect(String::from("("))?; + let mut args: Vec> = vec![]; + loop { + if self.tokenizer.current_token().str == String::from(")") { + self.tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(")")); + break; + } + args.push(self.assign()?); + self.tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(",")); + } + self.tokenizer.expect(String::from("]"))?; + return Ok(Box::new(Node::Attribute { + name: name.str, + args, + })); + } + /* mode: SHARP IDENT ; */ diff --git a/src/gpsl/source.rs b/src/gpsl/source.rs index e827619..fd54725 100644 --- a/src/gpsl/source.rs +++ b/src/gpsl/source.rs @@ -1,4 +1,4 @@ -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Source { pub src: Vec, pub pos: usize, diff --git a/src/gpsl/vm/gpsl.rs b/src/gpsl/vm/gpsl.rs index 2995e07..a5b9a64 100644 --- a/src/gpsl/vm/gpsl.rs +++ b/src/gpsl/vm/gpsl.rs @@ -1,12 +1,12 @@ -use crate::gpsl::external_function::{ - ExternalFuncCallData, ExternalFuncReturn, ExternalFuncStatus, -}; +use crate::gpsl::external_function::{ExternalFuncReturn, ExternalFuncStatus}; use crate::gpsl::node::*; use crate::gpsl::permission::Permission; use crate::gpsl::source::Source; use crate::gpsl::variable::*; use log::*; +use serde::{Deserialize, Serialize}; use std::collections::{HashMap, VecDeque}; +use std::io::{BufRead, BufReader, Read, Write}; use std::net::TcpStream; use std::string::*; use std::sync::{Arc, Mutex}; @@ -19,21 +19,16 @@ pub struct Block { pub is_split: bool, } +#[derive(Debug)] pub struct GPSL { pub functions: Option>>, + pub server_functions: Option>>>, + pub servers: Option>>>, pub global_variables: Vec, pub source: Source, pub blocks: VecDeque, - pub tcp_stream: Arc>>, - pub external_func: Vec< - fn( - String, - Vec, - Vec, - Vec, - Option, - ) -> ExternalFuncReturn, - >, + pub external_func: + Vec, Vec, Vec) -> ExternalFuncReturn>, } #[derive(Clone, Debug)] @@ -48,6 +43,12 @@ pub struct VariableStatus { pub initialized: bool, } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ServerFunctionCall { + pub name: String, + pub args: HashMap, +} + impl VariableStatus { pub fn default() -> VariableStatus { VariableStatus { initialized: false } @@ -58,23 +59,19 @@ impl GPSL { pub fn new( source: Source, functions: Option>>, - tcp_sream: Arc>>, + server_functions: Option>>>, + servers: Option>>>, external_func: Vec< - fn( - String, - Vec, - Vec, - Vec, - Option, - ) -> ExternalFuncReturn, + fn(String, Vec, Vec, Vec) -> ExternalFuncReturn, >, ) -> GPSL { GPSL { source, functions, + server_functions, + servers, global_variables: vec![], blocks: VecDeque::new(), - tcp_stream: tcp_sream, external_func, } } @@ -128,6 +125,50 @@ impl GPSL { } } + debug!( + "Searching server function: {}, ({:?})", + &function_name, args_value + ); + + for server in self.server_functions.clone().unwrap() { + for function in server.1 { + if function.0 == function_name { + let mut servers = self.servers.clone().unwrap(); + let stream = servers.get_mut(&server.0).unwrap(); + let mut stream = stream.lock().unwrap(); + + let function_args = function.1.extract_function_args(); + let mut args: HashMap = HashMap::new(); + for (i, arg_name) in function_args.0.iter().enumerate() { + args.insert(arg_name.clone(), args_value[i].clone()); + } + + let server_function_call = serde_json::to_string(&ServerFunctionCall { + name: function_name.clone(), + args: args.clone(), + }) + .unwrap(); + println!("{}", server_function_call); + + stream + .write_fmt(format_args!("{}\n", server_function_call)) + .unwrap(); + let mut buf = String::new(); + debug!("try clone"); + BufReader::new(stream.try_clone().unwrap()) + .read_line(&mut buf) + .unwrap(); + let res: ExternalFuncReturn = serde_json::from_str(&buf).unwrap(); + if res.status == ExternalFuncStatus::SUCCESS { + return Ok(res.value); + } + if res.status == ExternalFuncStatus::REJECTED { + return Err("Server function rejected.".to_string()); + } + } + } + } + if let Some(functions) = self.functions.clone() { debug!( "functions: {:?}", @@ -185,9 +226,6 @@ impl GPSL { args_value.clone(), block.accept.clone(), block.reject.clone(), - Some(ExternalFuncCallData { - stream: self.tcp_stream.clone(), - }), ); if res.status == ExternalFuncStatus::SUCCESS { return Ok(res.value); @@ -499,15 +537,33 @@ impl GPSL { } } - pub fn run(&mut self, function_name: String, _: Vec>) -> Result { + pub fn run( + &mut self, + function_name: String, + args: HashMap, + ) -> Result { debug!("functions: {:?}", self.functions); debug!("searching {}", function_name); + + let mut local_variables = HashMap::new(); + for (name, value) in args { + local_variables.insert( + name.clone(), + LocalVariable { + name: name.clone(), + value, + status: VariableStatus::default(), + }, + ); + } + self.blocks.push_front(Block { accept: vec![Permission::Administrator, Permission::StdIo], reject: vec![], - variables: HashMap::new(), + variables: local_variables, is_split: true, }); + if let Some(functions) = self.functions.clone() { if let Node::Function { body, .. } = &*(functions[&function_name]) { for program in body { diff --git a/src/lib.rs b/src/lib.rs index 9ccc515..05f5de4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ pub mod common; pub mod elliptic_curve; pub mod gpsl; -#[macro_use] -extern crate log; diff --git a/src/main.rs b/src/main.rs index 0da6359..e4ec2eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,16 @@ mod gpsl; +use gpsl::external_function::ExternalFuncReturn; +use gpsl::external_function::ExternalFuncStatus; +use gpsl::node::Node; +use gpsl::node::NodeKind; use gpsl::variable::Variable; +use gpsl::vm::gpsl::ServerFunctionCall; use gpsl::{external_function::STD_FUNC, parser::*, source::*, tokenizer::*, vm::gpsl::*}; -use primitive_types::U512; +use log::*; +use std::env; +use std::io::BufRead; +use std::io::BufReader; +use std::io::Write; use std::net::{TcpListener, TcpStream}; use std::sync::{Arc, Mutex}; use std::{collections::HashMap, fs}; @@ -55,10 +64,13 @@ struct Args { mode: String, #[clap(short, long, value_parser)] - file: String, + file: Option, #[clap(short, long, value_parser)] ip: Option, + + #[clap(short, long, value_parser)] + port: Option, } fn listen_tcp_server(port: u16) -> TcpStream { @@ -79,7 +91,66 @@ fn listen_tcp_server(port: u16) -> TcpStream { fn main() { let args = Args::parse(); - let mut source = Source::new(fs::read_to_string(&(args.file)).expect("Cannot read file.")); + match &*args.mode { + "server" => { + server(args); + } + "client" => { + client(args); + } + _ => { + println!("Unknown mode"); + } + } +} + +fn server(args: Args) { + let mut stream = listen_tcp_server(args.port.unwrap()); + + debug!("Receiving functions..."); + let mut buf = String::default(); + BufReader::new(stream.try_clone().unwrap()) + .read_line(&mut buf) + .unwrap(); + + let functions: HashMap> = serde_json::from_str(&buf).unwrap(); + debug!("Received: {:?}", functions); + + let mut gpsl = GPSL::new( + Source::new(String::default()), + Some(functions), + Some(HashMap::new()), + Some(HashMap::new()), + vec![STD_FUNC], + ); + + debug!("Receiving function call..."); + BufReader::new(stream.try_clone().unwrap()) + .read_line(&mut buf) + .unwrap(); + debug!("Received"); + debug!("{}", buf); + + let function_call: ServerFunctionCall = serde_json::from_str(&buf).unwrap(); + + let result = gpsl.run(function_call.name, function_call.args); + let external_function_return = ExternalFuncReturn { + status: ExternalFuncStatus::SUCCESS, + value: Some(result.unwrap()), + }; + + debug!("Sending result..."); + stream + .write_fmt(format_args!( + "{}\n", + serde_json::to_string(&external_function_return).unwrap() + )) + .unwrap(); +} + +fn client(args: Args) { + let mut source = + Source::new(fs::read_to_string(&(args.file.unwrap())).expect("Cannot read file.")); let mut tokenizer = Tokenizer::new(); tokenizer.tokenize(&mut source).unwrap(); @@ -89,19 +160,70 @@ fn main() { local_vars: HashMap::new(), }; - let stream = match &*args.mode { - "server" => listen_tcp_server(8080), - "client" => TcpStream::connect(args.ip.unwrap()).unwrap(), - _ => panic!("Cannot start tcp stream."), - }; + let functions = parser.functions().unwrap(); + let mut server_functions: HashMap>> = HashMap::new(); + for function in functions.clone() { + match *function.clone().1 { + Node::Function { attribute, .. } => match *(attribute.unwrap()) { + Node::Attribute { name, args } => { + if name == String::from("server") { + println!("{:?}", function); + let ip = { + let mut t_ip = None; + for arg in args { + let ip = match *arg { + Node::Operator { kind, lhs, rhs } => { + if kind == NodeKind::ASSIGN { + if lhs.extract_string() == String::from("ip") { + println!("IP: {}", rhs.extract_string()); + Some(rhs.extract_string()) + } else { + None + } + } else { + None + } + } + _ => None, + }; + if ip.is_some() { + t_ip = ip; + break; + } + } + t_ip.unwrap() + }; + + let t_functions = server_functions.entry(ip).or_insert(HashMap::new()); + t_functions.insert(function.clone().0.clone(), function.clone().1.clone()); + } + } + _ => {} + }, + _ => {} + } + } + + let mut servers: HashMap>> = HashMap::new(); + for (ip, functions) in server_functions.clone() { + let mut stream = TcpStream::connect(ip.clone()).unwrap(); + stream + .write_fmt(format_args!( + "{}\n", + serde_json::to_string(&functions).unwrap() + )) + .unwrap(); + servers.insert(ip, Arc::new(Mutex::new(stream))); + } let mut gpsl = GPSL::new( source, - Some(parser.functions().unwrap()), - Arc::new(Mutex::new(Some(stream))), + Some(functions), + Some(server_functions), + Some(servers), vec![STD_FUNC], ); - let res = gpsl.run("main".to_string(), vec![]); + let res = gpsl.run("main".to_string(), HashMap::new()); if let Err(err) = res { println!("Error: {:?}", err); }