mirror of
https://github.com/mii443/encrypt.git
synced 2025-08-22 15:05:33 +00:00
add security
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
use gpsl::{
|
||||
gpsl::GPSL,
|
||||
vm::gpsl::GPSL,
|
||||
source::Source,
|
||||
std::*,
|
||||
external_function::*,
|
||||
tokenizer::Tokenizer,
|
||||
parser::Parser
|
||||
};
|
||||
@ -14,7 +14,7 @@ fn main() {
|
||||
let mut source = Source::new(fs::read_to_string(&(args.last().unwrap())).expect("Cannot read file."));
|
||||
|
||||
let mut tokenizer = Tokenizer::new();
|
||||
tokenizer.tokenize(&mut source);
|
||||
tokenizer.tokenize(&mut source).unwrap();
|
||||
|
||||
let mut parser = Parser {
|
||||
tokenizer,
|
||||
@ -26,4 +26,4 @@ fn main() {
|
||||
if let Err(err) = res {
|
||||
println!("Error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
19
src/bin/test.rs
Normal file
19
src/bin/test.rs
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
fn main() {
|
||||
println!("testing binary");
|
||||
|
||||
let mut queue: VecDeque<i64> = VecDeque::new();
|
||||
|
||||
queue.push_back(1i64);
|
||||
queue.push_back(2i64);
|
||||
queue.push_back(3i64);
|
||||
|
||||
for x in 0..queue.len() {
|
||||
println!("{}", queue[x]);
|
||||
}
|
||||
|
||||
println!("{:?}", queue);
|
||||
println!("{:?}", queue.len());
|
||||
}
|
63
src/external_function.rs
Normal file
63
src/external_function.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use crate::{variable::Variable, permission::Permission};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum ExternalFuncStatus {
|
||||
SUCCESS,
|
||||
NOTFOUND,
|
||||
ERROR,
|
||||
REJECTED,
|
||||
}
|
||||
|
||||
pub struct ExternalFuncReturn {
|
||||
pub status: ExternalFuncStatus,
|
||||
pub value: Option<Variable>
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const STD_FUNC: fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> ExternalFuncReturn = |name, args, accept, reject| {
|
||||
let name = name.as_str();
|
||||
match name {
|
||||
"println" => {
|
||||
if accept.contains(&Permission::StdIo) && !reject.contains(&Permission::StdIo) {
|
||||
match &args[0] {
|
||||
Variable::Text { value } => println!("{}", value),
|
||||
Variable::Number { value } => println!("{}", value),
|
||||
_ => {}
|
||||
}
|
||||
ExternalFuncReturn {
|
||||
status: ExternalFuncStatus::SUCCESS,
|
||||
value: None
|
||||
}
|
||||
} else {
|
||||
ExternalFuncReturn {
|
||||
status: ExternalFuncStatus::REJECTED,
|
||||
value: None
|
||||
}
|
||||
}
|
||||
}
|
||||
"print" => {
|
||||
if accept.contains(&Permission::StdIo) && !reject.contains(&Permission::StdIo) {
|
||||
match &args[0] {
|
||||
Variable::Text { value } => print!("{}", value),
|
||||
Variable::Number { value } => print!("{}", value),
|
||||
_ => {}
|
||||
}
|
||||
ExternalFuncReturn {
|
||||
status: ExternalFuncStatus::SUCCESS,
|
||||
value: None
|
||||
}
|
||||
} else {
|
||||
ExternalFuncReturn {
|
||||
status: ExternalFuncStatus::REJECTED,
|
||||
value: None
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
ExternalFuncReturn {
|
||||
status: ExternalFuncStatus::NOTFOUND,
|
||||
value: None
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -5,6 +5,7 @@ WS
|
||||
-> skip
|
||||
;
|
||||
|
||||
DOLLER: '$' ;
|
||||
ADD: '+' ;
|
||||
SUB: '-' ;
|
||||
MUL: '*' ;
|
||||
@ -31,6 +32,8 @@ LPAREN: '(' ;
|
||||
RPAREN: ')' ;
|
||||
LCURL: '{' ;
|
||||
RCURL: '}' ;
|
||||
LBRACKET: '[' ;
|
||||
RBRACKET: ']' ;
|
||||
ARROW: '->' ;
|
||||
|
||||
FN: 'fn' ;
|
||||
|
@ -7,22 +7,24 @@ function: FN IDENT LPAREN (IDENT COLON IDENT COMMA?)* RPAREN (ARROW IDENT)? bloc
|
||||
|
||||
program: stmt* ;
|
||||
|
||||
stmt: let
|
||||
| block
|
||||
| return
|
||||
| if
|
||||
| while
|
||||
| for
|
||||
| expr SEMICOLON
|
||||
stmt: let
|
||||
| block
|
||||
| return
|
||||
| if
|
||||
| while
|
||||
| for
|
||||
| expr SEMICOLON
|
||||
;
|
||||
|
||||
let: LET IDENT COLON IDENT SEMICOLON ;
|
||||
block: LCURL stmt* RCURL ;
|
||||
block: permission? LCURL stmt* RCURL ;
|
||||
return: RETURN expr? SEMICOLON ;
|
||||
if: IF LPAREN expr RPAREN stmt (ELSE stmt)? ;
|
||||
while: WHILE LPAREN expr RPAREN stmt ;
|
||||
for: FOR LPAREN expr? SEMICOLON expr? SEMICOLON expr? RPAREN stmt ;
|
||||
|
||||
permission: DOLLER LPAREN ( IDENT LBRACKET ( IDENT COMMA? )* RBRACKET COMMA? )* RPAREN ;
|
||||
|
||||
expr: assign ;
|
||||
assign: equality (EQ assign)? ;
|
||||
equality: relational (EQEQ relational | NE relational | CONJ)* ;
|
||||
@ -33,7 +35,7 @@ mul: unary (MUL unary | DIV unary | DIV_ASSIGNMENT unary | MUL_ASSIGNMENT unary)
|
||||
primary: LPAREN expr RPAREN | function_call | TEXT | NUM ;
|
||||
function_call: IDENT LPAREN (unary COMMA?)* RPAREN ;
|
||||
|
||||
unary: ADD primary
|
||||
| SUB primary
|
||||
| primary
|
||||
unary: ADD primary
|
||||
| SUB primary
|
||||
| primary
|
||||
;
|
||||
|
@ -1,10 +1,11 @@
|
||||
pub mod node;
|
||||
pub mod parser;
|
||||
pub mod gpsl;
|
||||
pub mod vm;
|
||||
pub mod source;
|
||||
pub mod token;
|
||||
pub mod tokenizer;
|
||||
pub mod variable;
|
||||
pub mod std;
|
||||
pub mod external_function;
|
||||
pub mod permission;
|
||||
#[macro_use]
|
||||
extern crate log;
|
12
src/node.rs
12
src/node.rs
@ -20,6 +20,10 @@ pub enum Node {
|
||||
args: HashMap<String, String>,
|
||||
body: Vec<Box<Node>>
|
||||
},
|
||||
Permission {
|
||||
accept: Vec<String>,
|
||||
reject: Vec<String>
|
||||
},
|
||||
Operator {
|
||||
kind: NodeKind,
|
||||
lhs: Box<Node>,
|
||||
@ -54,15 +58,17 @@ pub enum Node {
|
||||
},
|
||||
Block {
|
||||
stmts: Vec<Box<Node>>,
|
||||
permission: Option<Box<Node>>
|
||||
},
|
||||
Define {
|
||||
name: String,
|
||||
var_type: String,
|
||||
},
|
||||
Call {
|
||||
name: String,
|
||||
args: Vec<Box<Node>>,
|
||||
}
|
||||
name: String,
|
||||
args: Vec<Box<Node>>,
|
||||
},
|
||||
None
|
||||
}
|
||||
|
||||
impl Node {
|
||||
|
@ -10,11 +10,14 @@ pub struct Parser {
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
pub fn functions(&mut self) -> Result<Vec<Box<Node>>, String> {
|
||||
let mut nodes: Vec<Box<Node>> = vec![];
|
||||
pub fn functions(&mut self) -> Result<HashMap<String, Box<Node>>, String> {
|
||||
let mut nodes: HashMap<String, Box<Node>> = HashMap::new();
|
||||
loop {
|
||||
if self.tokenizer.current_token().kind != TokenKind::EOF {
|
||||
nodes.push(self.function()?);
|
||||
let function = self.function()?;
|
||||
if let Node::Function{name, .. } = *function.clone() {
|
||||
nodes.insert(name, function);
|
||||
}
|
||||
} else {
|
||||
return Ok(nodes);
|
||||
}
|
||||
@ -40,6 +43,7 @@ impl Parser {
|
||||
self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(","));
|
||||
args.insert(name, type_str);
|
||||
}
|
||||
|
||||
let mut nodes: Vec<Box<Node>> = vec![];
|
||||
debug!("parsing body node");
|
||||
loop {
|
||||
@ -73,13 +77,13 @@ impl Parser {
|
||||
}
|
||||
|
||||
/*
|
||||
stmt: let
|
||||
| block
|
||||
| return
|
||||
| if
|
||||
| while
|
||||
| for
|
||||
| expr SEMICOLON
|
||||
stmt: let
|
||||
| block
|
||||
| return
|
||||
| if
|
||||
| while
|
||||
| for
|
||||
| expr SEMICOLON
|
||||
;
|
||||
*/
|
||||
pub fn stmt(&mut self) -> Result<Box<Node>, String> {
|
||||
@ -99,9 +103,16 @@ impl Parser {
|
||||
}));
|
||||
}
|
||||
|
||||
debug!("parsing permission");
|
||||
let permission = if self.tokenizer.current_token().str == "$" {
|
||||
Some(self.permission()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if self
|
||||
.tokenizer
|
||||
.consume_kind_str(TokenKind::RESERVED, String::from("{"))
|
||||
.consume_kind_str(TokenKind::RESERVED, String::from("{")) || permission != None
|
||||
{
|
||||
let mut stmts: Vec<Box<Node>> = vec![];
|
||||
loop {
|
||||
@ -109,7 +120,7 @@ impl Parser {
|
||||
.tokenizer
|
||||
.consume_kind_str(TokenKind::RESERVED, String::from("}"))
|
||||
{
|
||||
return Ok(Box::new(Node::Block { stmts }));
|
||||
return Ok(Box::new(Node::Block { stmts, permission: permission }));
|
||||
} else {
|
||||
stmts.push(self.stmt()?);
|
||||
}
|
||||
@ -196,6 +207,39 @@ impl Parser {
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
permission: DOLLER LPAREN ( IDENT LBRACKET ( IDENT COMMA? )* RBRACKET COMMA? )* RPAREN ;
|
||||
*/
|
||||
pub fn permission(&mut self) -> Result<Box<Node>, String> {
|
||||
self.tokenizer.expect(String::from("$"))?;
|
||||
self.tokenizer.expect(String::from("("))?;
|
||||
|
||||
let mut accept: Vec<String> = vec![];
|
||||
let mut reject: Vec<String> = vec![];
|
||||
|
||||
while !self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(")")) {
|
||||
let name = self.tokenizer.expect_ident()?;
|
||||
if name != "accept" && name != "reject" {
|
||||
return Err(String::from(format!("Unexpected: {}", name)));
|
||||
}
|
||||
self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from("["));
|
||||
while !self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from("]")) {
|
||||
let permission = self.tokenizer.expect_ident()?;
|
||||
self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(","));
|
||||
|
||||
if name == "accept" {
|
||||
accept.push(permission);
|
||||
} else if name == "reject" {
|
||||
reject.push(permission);
|
||||
}
|
||||
}
|
||||
|
||||
self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(","));
|
||||
}
|
||||
|
||||
Ok(Box::new(Node::Permission { accept, reject }))
|
||||
}
|
||||
|
||||
/*
|
||||
expr: assign ;
|
||||
*/
|
||||
@ -329,11 +373,11 @@ impl Parser {
|
||||
args.push(self.unary()?);
|
||||
self.tokenizer.consume(String::from(","));
|
||||
}
|
||||
|
||||
|
||||
self.tokenizer.expect(String::from(")"))?;
|
||||
return Ok(Box::new(Node::Call {
|
||||
name: node.clone(),
|
||||
args: args,
|
||||
name: node.clone(),
|
||||
args: args,
|
||||
}))
|
||||
}
|
||||
return Ok(Node::new_lvar_node(node.clone()));
|
||||
@ -351,9 +395,9 @@ impl Parser {
|
||||
}
|
||||
|
||||
/*
|
||||
unary: ADD primary
|
||||
| SUB primary
|
||||
| primary
|
||||
unary: ADD primary
|
||||
| SUB primary
|
||||
| primary
|
||||
;
|
||||
*/
|
||||
pub fn unary(&mut self) -> Result<Box<Node>, String> {
|
||||
|
16
src/permission.rs
Normal file
16
src/permission.rs
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Permission {
|
||||
Administrator,
|
||||
StdIo
|
||||
}
|
||||
|
||||
impl Permission {
|
||||
pub fn from_string(permission: &str) -> Self {
|
||||
match permission {
|
||||
"Administrator" => Self::Administrator,
|
||||
"StdIo" => Self::StdIo,
|
||||
_ => panic!("Permission not found.")
|
||||
}
|
||||
}
|
||||
}
|
37
src/std.rs
37
src/std.rs
@ -1,37 +0,0 @@
|
||||
use crate::variable::Variable;
|
||||
use crate::gpsl::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const STD_FUNC: fn(String, Vec<Variable>) -> ExternalFuncReturn = |name, args| {
|
||||
let name = name.as_str();
|
||||
match name {
|
||||
"println" => {
|
||||
match &args[0] {
|
||||
Variable::Text { value } => println!("{}", value),
|
||||
Variable::Number { value } => println!("{}", value),
|
||||
_ => {}
|
||||
}
|
||||
ExternalFuncReturn {
|
||||
status: ExternalFuncStatus::SUCCESS,
|
||||
value: None
|
||||
}
|
||||
}
|
||||
"print" => {
|
||||
match &args[0] {
|
||||
Variable::Text { value } => print!("{}", value),
|
||||
Variable::Number { value } => print!("{}", value),
|
||||
_ => {}
|
||||
}
|
||||
ExternalFuncReturn {
|
||||
status: ExternalFuncStatus::SUCCESS,
|
||||
value: None
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
ExternalFuncReturn {
|
||||
status: ExternalFuncStatus::NOTFOUND,
|
||||
value: None
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -113,6 +113,7 @@ impl Tokenizer {
|
||||
String::from("-="),
|
||||
String::from("*="),
|
||||
String::from("/="),
|
||||
String::from("$"),
|
||||
String::from("+"),
|
||||
String::from("-"),
|
||||
String::from("*"),
|
||||
@ -123,6 +124,8 @@ impl Tokenizer {
|
||||
String::from("}"),
|
||||
String::from("("),
|
||||
String::from(")"),
|
||||
String::from("["),
|
||||
String::from("]"),
|
||||
String::from("=="),
|
||||
String::from("!="),
|
||||
String::from(">="),
|
||||
@ -152,7 +155,7 @@ impl Tokenizer {
|
||||
Ok(t) => t,
|
||||
Err(_) => String::from(""),
|
||||
};
|
||||
source.get_char(is('"'));
|
||||
source.get_char(is('"'))?;
|
||||
self.tokens.push(Token {
|
||||
kind: TokenKind::TEXT,
|
||||
str: text,
|
||||
|
@ -1,38 +1,35 @@
|
||||
use crate::external_function::{ExternalFuncReturn, ExternalFuncStatus};
|
||||
use crate::node::*;
|
||||
use crate::parser::*;
|
||||
use crate::permission::Permission;
|
||||
use crate::source::Source;
|
||||
use crate::tokenizer::*;
|
||||
use crate::variable::*;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::string::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum ExternalFuncStatus {
|
||||
SUCCESS,
|
||||
NOTFOUND,
|
||||
ERROR,
|
||||
}
|
||||
|
||||
pub struct ExternalFuncReturn {
|
||||
pub status: ExternalFuncStatus,
|
||||
pub value: Option<Variable>
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Block {
|
||||
pub accept: Vec<Permission>,
|
||||
pub reject: Vec<Permission>,
|
||||
pub variables: HashMap<String, LocalVariable>,
|
||||
pub is_split: bool
|
||||
}
|
||||
|
||||
pub struct GPSL {
|
||||
pub functions: Option<Vec<Box<Node>>>,
|
||||
pub functions: Option<HashMap<String, Box<Node>>>,
|
||||
pub global_variables: Vec<Variable>,
|
||||
pub source: Source,
|
||||
pub l_vars: HashMap<String, LocalVariable>,
|
||||
pub external_func: Vec<fn(String, Vec<Variable>) -> ExternalFuncReturn>
|
||||
pub blocks: VecDeque<Block>,
|
||||
pub external_func: Vec<fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> ExternalFuncReturn>
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LocalVariable {
|
||||
pub name: String,
|
||||
pub value: Variable,
|
||||
pub status: VariableStatus,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VariableStatus {
|
||||
pub initialized: bool,
|
||||
}
|
||||
@ -44,16 +41,46 @@ impl VariableStatus {
|
||||
}
|
||||
|
||||
impl GPSL {
|
||||
pub fn new(source: Source, functions: Option<Vec<Box<Node>>>, external_func: Vec<fn(String, Vec<Variable>) -> ExternalFuncReturn>) -> GPSL {
|
||||
pub fn new(source: Source, functions: Option<HashMap<String, Box<Node>>>, external_func: Vec<fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> ExternalFuncReturn>) -> GPSL {
|
||||
GPSL {
|
||||
source,
|
||||
functions,
|
||||
global_variables: vec![],
|
||||
l_vars: HashMap::new(),
|
||||
blocks: VecDeque::new(),
|
||||
external_func
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_local_var_mut(&mut self, name: &String) -> Option<&mut LocalVariable> {
|
||||
for x in 0..self.blocks.len() {
|
||||
if self.blocks[x].variables.contains_key(name) {
|
||||
return self.blocks[x].variables.get_mut(name);
|
||||
}
|
||||
|
||||
if self.blocks[x].is_split {
|
||||
break
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_local_var(&mut self, name: &String) -> Option<LocalVariable> {
|
||||
for x in 0..self.blocks.len() {
|
||||
if self.blocks[x].variables.contains_key(name) {
|
||||
if let Some(var) = self.blocks[x].variables.get(name).clone() {
|
||||
return Some(var.clone());
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
if self.blocks[x].is_split {
|
||||
break
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn extract_number(node: Variable) -> Result<usize, String> {
|
||||
match node {
|
||||
Variable::Number { value } => {
|
||||
@ -78,33 +105,54 @@ impl GPSL {
|
||||
}
|
||||
|
||||
if let Some(functions) = self.functions.clone() {
|
||||
for function in functions {
|
||||
match *function {
|
||||
Node::Function { name, body, args } => {
|
||||
if name == function_name {
|
||||
for program in body {
|
||||
if let Ok(Some(res)) = self.evaluate(program) {
|
||||
match res {
|
||||
Variable::Return { value } => {
|
||||
return Ok(Some(*value));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
debug!("functions: {:?}", functions.iter().map(|f| format!("{},", f.0)).collect::<String>());
|
||||
debug!("{}: {}", &function_name, functions.contains_key(&function_name));
|
||||
if functions.contains_key(&function_name) {
|
||||
if let Node::Function { body, .. } = &*(functions[&function_name]) {
|
||||
for program in body {
|
||||
let block = {
|
||||
let blocks = self.blocks.clone();
|
||||
blocks.front().unwrap().clone()
|
||||
};
|
||||
|
||||
self.blocks.push_front(Block {
|
||||
accept: block.accept.clone(),
|
||||
reject: block.reject.clone(),
|
||||
variables: HashMap::new(),
|
||||
is_split: true
|
||||
});
|
||||
|
||||
let res = self.evaluate(Box::new(*program.clone()));
|
||||
|
||||
if let Ok(Some(res)) = res {
|
||||
match res {
|
||||
Variable::Return { value } => {
|
||||
return Ok(Some(*value));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return Ok(None);
|
||||
} else if let Err(err) = res {
|
||||
return Err(err);
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
|
||||
self.blocks.pop_front();
|
||||
}
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Searching external: {}, ({:?})", &function_name, args_value);
|
||||
|
||||
for func in f {
|
||||
let res = func(function_name.clone(), args_value.clone());
|
||||
let block = self.blocks.front().unwrap();
|
||||
let res = func(function_name.clone(), args_value.clone(), block.accept.clone(), block.reject.clone());
|
||||
if res.status == ExternalFuncStatus::SUCCESS {
|
||||
return Ok(res.value);
|
||||
}
|
||||
if res.status == ExternalFuncStatus::REJECTED {
|
||||
return Err("External function rejected.".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
Err(format!("Function not found: {}", function_name))
|
||||
@ -121,13 +169,15 @@ impl GPSL {
|
||||
}
|
||||
Node::Operator { kind, lhs, rhs } => {
|
||||
if kind == NodeKind::ASSIGN {
|
||||
debug!("Assign: {:?}", self.blocks.front());
|
||||
|
||||
let rhs = self.evaluate(rhs);
|
||||
|
||||
if let Ok(Some(rhs)) = rhs {
|
||||
match *(lhs.clone()) {
|
||||
Node::Lvar { value } => {
|
||||
self.l_vars.get_mut(&value).unwrap().value = rhs;
|
||||
self.l_vars.get_mut(&value).unwrap().status.initialized = true
|
||||
self.get_local_var_mut(&value).unwrap().value = rhs;
|
||||
self.get_local_var_mut(&value).unwrap().status.initialized = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -201,7 +251,7 @@ impl GPSL {
|
||||
Err(err) => { Err(err) }
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
NodeKind::EQ => {
|
||||
if lhs == rhs {
|
||||
Ok(Some(Variable::Number {
|
||||
@ -276,7 +326,7 @@ impl GPSL {
|
||||
}
|
||||
}
|
||||
Node::Lvar { value } => {
|
||||
return Ok(Some(self.l_vars.get(&value).unwrap().value.clone()));
|
||||
return Ok(Some(self.get_local_var(&value).unwrap().value.clone()));
|
||||
}
|
||||
Node::Return { lhs } => {
|
||||
if let Ok(Some(lhs)) = self.evaluate(lhs) {
|
||||
@ -299,7 +349,7 @@ impl GPSL {
|
||||
} {
|
||||
if let Ok(Some(res)) = self.evaluate(stmt) {
|
||||
match res.clone() {
|
||||
Variable::Return { value } => {
|
||||
Variable::Return { .. } => {
|
||||
return Ok(Some(res));
|
||||
}
|
||||
_ => {}
|
||||
@ -310,7 +360,7 @@ impl GPSL {
|
||||
Some(else_stmt) => {
|
||||
if let Ok(Some(res)) = self.evaluate(else_stmt) {
|
||||
match res.clone() {
|
||||
Variable::Return { value } => {
|
||||
Variable::Return { .. } => {
|
||||
return Ok(Some(res));
|
||||
}
|
||||
_ => {}
|
||||
@ -370,13 +420,13 @@ impl GPSL {
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
None => {
|
||||
Variable::Number {
|
||||
value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
while match cond {
|
||||
Variable::Number { value } => value == 1,
|
||||
_ => false
|
||||
@ -398,28 +448,46 @@ impl GPSL {
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
None => {
|
||||
Variable::Number {
|
||||
value: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
Node::Block { stmts } => {
|
||||
Node::Block { stmts, permission } => {
|
||||
let accept = self.blocks.front().unwrap().accept.clone();
|
||||
let reject = self.blocks.front().unwrap().reject.clone();
|
||||
let (accept, reject) = if let Node::Permission { accept, reject } = *permission.unwrap_or(Box::new(Node::None)) {
|
||||
(accept.iter().map(|p| Permission::from_string(p)).collect(), reject.iter().map(|p| Permission::from_string(p)).collect())
|
||||
} else {
|
||||
(accept, reject)
|
||||
};
|
||||
|
||||
self.blocks.push_front(Block {
|
||||
accept: accept,
|
||||
reject: reject,
|
||||
variables: HashMap::new(),
|
||||
is_split: false
|
||||
});
|
||||
|
||||
for stmt in stmts {
|
||||
let ret = self.evaluate(stmt)?;
|
||||
if let Some(ret) = ret {
|
||||
match ret.clone() {
|
||||
Variable::Return { value } => {
|
||||
Variable::Return { .. } => {
|
||||
return Ok(Some(ret));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.blocks.pop_front();
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
Node::Define { name, var_type } => {
|
||||
@ -434,7 +502,7 @@ impl GPSL {
|
||||
} else {
|
||||
return Err(format!("{}: 未知の型です。", var_type));
|
||||
};
|
||||
self.l_vars.insert(
|
||||
self.blocks.front_mut().unwrap().variables.insert(
|
||||
name.clone(),
|
||||
LocalVariable {
|
||||
name,
|
||||
@ -442,34 +510,38 @@ impl GPSL {
|
||||
status: VariableStatus::default(),
|
||||
},
|
||||
);
|
||||
|
||||
debug!("Define: {:?}", self.blocks.front());
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
_ => { Ok(None) },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&mut self, function_name: String, function_args: Vec<Box<Node>>) -> Result<Variable, String> {
|
||||
pub fn run(&mut self, function_name: String, _: Vec<Box<Node>>) -> Result<Variable, String> {
|
||||
debug!("functions: {:?}", self.functions);
|
||||
debug!("searching {}", function_name);
|
||||
|
||||
self.blocks.push_front(Block {
|
||||
accept: vec![Permission::Administrator, Permission::StdIo],
|
||||
reject: vec![],
|
||||
variables: HashMap::new(),
|
||||
is_split: true
|
||||
});
|
||||
if let Some(functions) = self.functions.clone() {
|
||||
for function in functions {
|
||||
match *function {
|
||||
Node::Function { name, body, args } => {
|
||||
if name == function_name {
|
||||
debug!("running: {}", function_name);
|
||||
for program in body {
|
||||
if let Ok(Some(res)) = self.evaluate(program) {
|
||||
match res {
|
||||
Variable::Return { value } => {
|
||||
return Ok(*value);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if let Node::Function { body, .. } = &*(functions[&function_name]) {
|
||||
for program in body {
|
||||
let res = self.evaluate(Box::new(*program.clone()));
|
||||
if let Ok(Some(res)) = res {
|
||||
match res {
|
||||
Variable::Return { value } => {
|
||||
return Ok(*value);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
} else if let Err(err) = res {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
src/vm/mod.rs
Normal file
1
src/vm/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod gpsl;
|
Reference in New Issue
Block a user