add server function call

This commit is contained in:
Masato Imai
2022-07-21 16:04:00 +09:00
parent be3bd2572e
commit 660ed217be
12 changed files with 351 additions and 97 deletions

4
Cargo.lock generated
View File

@ -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",

View File

@ -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 = "*"

View File

@ -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));
}

View File

@ -1,3 +1,4 @@
#[server(ip = "localhost:8080")]
fn main() {
send(receive());
}

View File

@ -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<Variable>,
}
pub struct ExternalFuncCallData {
pub stream: Arc<Mutex<Option<TcpStream>>>,
}
#[allow(dead_code)]
pub const STD_FUNC: fn(
String,
Vec<Variable>,
Vec<Permission>,
Vec<Permission>,
Option<ExternalFuncCallData>,
) -> ExternalFuncReturn = |name, args, accept, reject, data| {
) -> ExternalFuncReturn = |name, args, accept, reject| {
let name = name.as_str();
match name {
"println" => {
@ -69,7 +65,7 @@ pub const STD_FUNC: fn(
value: None,
}
}
}
} /*
"receive" => {
println!("Waiting for client...");
let mut buffer = String::default();
@ -104,7 +100,7 @@ pub const STD_FUNC: fn(
status: ExternalFuncStatus::SUCCESS,
value: None,
}
}
}*/
_ => ExternalFuncReturn {
status: ExternalFuncStatus::NOTFOUND,
value: None,

View File

@ -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 ;

View File

@ -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<String, String>,
args_name: Vec<String>,
args_type: Vec<String>,
body: Vec<Box<Node>>,
attribute: Option<Box<Node>>,
},
Attribute {
name: String,
args: Vec<Box<Node>>,
},
Mode {
mode: String,
@ -87,4 +95,24 @@ impl Node {
pub fn new_lvar_node(value: String) -> Box<Node> {
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<String>, Vec<String>) {
match self {
Node::Function {
args_name,
args_type,
..
} => (args_name.clone(), args_type.clone()),
_ => (Vec::new(), Vec::new()),
}
}
}

View File

@ -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<Box<Node>, 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<Box<Node>> = 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<Box<Node>, 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<Box<Node>> = 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 ;
*/

View File

@ -1,4 +1,4 @@
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Source {
pub src: Vec<char>,
pub pos: usize,

View File

@ -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<HashMap<String, Box<Node>>>,
pub server_functions: Option<HashMap<String, HashMap<String, Box<Node>>>>,
pub servers: Option<HashMap<String, Arc<Mutex<TcpStream>>>>,
pub global_variables: Vec<Variable>,
pub source: Source,
pub blocks: VecDeque<Block>,
pub tcp_stream: Arc<Mutex<Option<TcpStream>>>,
pub external_func: Vec<
fn(
String,
Vec<Variable>,
Vec<Permission>,
Vec<Permission>,
Option<ExternalFuncCallData>,
) -> ExternalFuncReturn,
>,
pub external_func:
Vec<fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> 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<String, Variable>,
}
impl VariableStatus {
pub fn default() -> VariableStatus {
VariableStatus { initialized: false }
@ -58,23 +59,19 @@ impl GPSL {
pub fn new(
source: Source,
functions: Option<HashMap<String, Box<Node>>>,
tcp_sream: Arc<Mutex<Option<TcpStream>>>,
server_functions: Option<HashMap<String, HashMap<String, Box<Node>>>>,
servers: Option<HashMap<String, Arc<Mutex<TcpStream>>>>,
external_func: Vec<
fn(
String,
Vec<Variable>,
Vec<Permission>,
Vec<Permission>,
Option<ExternalFuncCallData>,
) -> ExternalFuncReturn,
fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> 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<String, Variable> = 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<Box<Node>>) -> Result<Variable, String> {
pub fn run(
&mut self,
function_name: String,
args: HashMap<String, Variable>,
) -> Result<Variable, String> {
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 {

View File

@ -1,5 +1,3 @@
pub mod common;
pub mod elliptic_curve;
pub mod gpsl;
#[macro_use]
extern crate log;

View File

@ -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<String>,
#[clap(short, long, value_parser)]
ip: Option<String>,
#[clap(short, long, value_parser)]
port: Option<u16>,
}
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<String, Box<Node>> = 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<String, HashMap<String, Box<Node>>> = 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<String, Arc<Mutex<TcpStream>>> = 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);
}