diff --git a/client.gpsl b/client.gpsl index 7a25963..3ba6205 100644 --- a/client.gpsl +++ b/client.gpsl @@ -9,6 +9,14 @@ fn add(a: num, b: num) { return a + b; } +fn rec(a: num, b: num) { + if b > 0 { + return rec(a + 2, b - 1); + } else { + return a; + } +} + fn main() { print("Input a: ") let a = to_u512(read_line()) @@ -16,8 +24,6 @@ fn main() { print("Input b: ") let b = to_u512(read_line()) - println("ใƒ†ใ‚นใƒˆ"); - let enc_a = encrypt(a) let enc_b = encrypt(b) diff --git a/src/gpsl/gpsl_type.rs b/src/gpsl/gpsl_type.rs new file mode 100644 index 0000000..367359d --- /dev/null +++ b/src/gpsl/gpsl_type.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct GPSLType { + pub type_str: String, + pub child: Vec, +} diff --git a/src/gpsl/grammar/GpslParser.g4 b/src/gpsl/grammar/GpslParser.g4 index 95767af..05fa179 100644 --- a/src/gpsl/grammar/GpslParser.g4 +++ b/src/gpsl/grammar/GpslParser.g4 @@ -3,7 +3,7 @@ options { tokenVocab = GpslLexer; } gpslFile: function* EOF ; -function: attribute? FN IDENT LPAREN (IDENT COLON IDENT COMMA?)* RPAREN (ARROW IDENT)? block ; +function: attribute? FN IDENT LPAREN (IDENT COLON type COMMA?)* RPAREN (ARROW type)? block ; program: stmt* ; @@ -16,14 +16,14 @@ stmt: let | expr SEMICOLON ; -let: LET IDENT ((COLON IDENT (EQ expr)?) | EQ expr) SEMICOLON ; +let: LET IDENT ((COLON type (EQ expr)?) | EQ expr) SEMICOLON ; block: permission? LCURL stmt* RCURL ; return: RETURN expr? SEMICOLON ; -if: IF LPAREN expr RPAREN stmt (ELSE stmt)? ; -while: WHILE LPAREN expr RPAREN stmt ; +if: IF expr stmt (ELSE stmt)? ; +while: WHILE expr stmt ; for: FOR LPAREN expr? SEMICOLON expr? SEMICOLON expr? RPAREN stmt ; - +type: IDENT (LT (type COMMA?)+ BT)? ; 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/mod.rs b/src/gpsl/mod.rs index 394e03e..d40e48a 100644 --- a/src/gpsl/mod.rs +++ b/src/gpsl/mod.rs @@ -1,4 +1,5 @@ pub mod external_function; +pub mod gpsl_type; pub mod node; pub mod parser; pub mod permission; diff --git a/src/gpsl/node.rs b/src/gpsl/node.rs index 5c96b80..06ffa57 100644 --- a/src/gpsl/node.rs +++ b/src/gpsl/node.rs @@ -1,5 +1,7 @@ use serde::{Deserialize, Serialize}; +use super::gpsl_type::GPSLType; + #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub enum NodeKind { ASSIGN, @@ -18,10 +20,13 @@ pub enum Node { Function { name: String, args_name: Vec, - args_type: Vec, + args_type: Vec, body: Vec>, attribute: Option>, }, + GPSLType { + value: GPSLType, + }, Attribute { name: String, args: Vec>, @@ -72,7 +77,7 @@ pub enum Node { }, Define { name: String, - var_type: Option, + var_type: Option, value: Option>, }, Call { @@ -104,7 +109,7 @@ impl Node { } } - pub fn extract_function_args(&self) -> (Vec, Vec) { + pub fn extract_function_args(&self) -> (Vec, Vec) { match self { Node::Function { args_name, diff --git a/src/gpsl/parser.rs b/src/gpsl/parser.rs index 9ffcbde..d230f6b 100644 --- a/src/gpsl/parser.rs +++ b/src/gpsl/parser.rs @@ -4,6 +4,8 @@ use crate::gpsl::tokenizer::*; use log::debug; use std::collections::HashMap; +use super::gpsl_type::GPSLType; + #[derive(Clone)] pub struct Parser { pub tokenizer: Tokenizer, @@ -58,11 +60,11 @@ impl Parser { let name = self.tokenizer.expect_ident()?; self.tokenizer .consume_kind_str(TokenKind::RESERVED, String::from(":")); - let type_str = self.tokenizer.expect_ident()?; + let gpsl_type = self.gpsl_type()?; self.tokenizer .consume_kind_str(TokenKind::RESERVED, String::from(",")); args_name.push(name); - args_type.push(type_str); + args_type.push(gpsl_type); } let mut nodes: Vec> = vec![]; @@ -121,9 +123,8 @@ impl Parser { .tokenizer .consume_kind_str(TokenKind::RESERVED, String::from(":")) { - let var_type = self.tokenizer.current_token().clone(); - self.tokenizer.expect_kind(TokenKind::IDENT)?; - Some(var_type.str) + let var_type = self.gpsl_type()?; + Some(var_type) } else { None }; @@ -198,9 +199,7 @@ impl Parser { match &*self.tokenizer.current_token().str { "if" => { self.tokenizer.cursor += 1; - self.tokenizer.expect(String::from("("))?; let condition = self.expr()?; - self.tokenizer.expect(String::from(")"))?; let stmt = self.stmt()?; let mut else_stmt: Option> = None; if self @@ -217,9 +216,7 @@ impl Parser { } "while" => { self.tokenizer.cursor += 1; - self.tokenizer.expect(String::from("("))?; let condition = self.expr()?; - self.tokenizer.expect(String::from(")"))?; let stmt = self.stmt()?; return Ok(Box::new(Node::While { condition, stmt })); } @@ -271,6 +268,49 @@ impl Parser { return node; } + /* + type: IDENT (LT (type COMMA?)+ BT)? ; + */ + pub fn gpsl_type(&mut self) -> Result { + let ident = self.tokenizer.current_token().clone(); + self.tokenizer.expect_kind(TokenKind::IDENT)?; + if self + .tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from("<")) + { + let mut types: Vec = vec![]; + loop { + if self + .tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(">")) + { + return Ok(GPSLType { + type_str: ident.str, + child: types, + }); + } else { + types.push(self.gpsl_type()?); + if self + .tokenizer + .consume_kind_str(TokenKind::RESERVED, String::from(",")) + { + continue; + } else { + return Ok(GPSLType { + type_str: ident.str, + child: types, + }); + } + } + } + } else { + return Ok(GPSLType { + type_str: ident.str, + child: vec![], + }); + } + } + /* attribute: SHARP LBRACKET IDENT LPAREN (assign COMMA?)* RPAREN RBRACKET ; */ diff --git a/src/gpsl/variable.rs b/src/gpsl/variable.rs index 4cb6353..ae528d2 100644 --- a/src/gpsl/variable.rs +++ b/src/gpsl/variable.rs @@ -13,6 +13,7 @@ pub enum Variable { PureEncrypted { value: EncryptedEllipticCurvePoint }, PairedEncrypted { value: FiniteFieldElement }, U512 { value: U512 }, + Vec { value: Vec }, None {}, } @@ -25,6 +26,14 @@ impl Variable { Variable::PureEncrypted { .. } => "eep".to_string(), Variable::PairedEncrypted { .. } => "eep_p".to_string(), Variable::U512 { .. } => "U512".to_string(), + Variable::Vec { value } => { + let mut type_str = "Vec<".to_string(); + for v in value { + type_str += &v.get_type(); + } + type_str += ">"; + type_str + } Variable::None { .. } => "none".to_string(), } }