Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ members = [
"rula-lib",
"rula-parser",
"rula-exec",
"ruleset-ir",
"tests-e2e"
]
1 change: 0 additions & 1 deletion doc/design.md

This file was deleted.

8 changes: 8 additions & 0 deletions doc/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# RuLa Specification
...

## Lifetime and Scope
Scope names:

\_\_@global\_\_ ... A global scope

3 changes: 2 additions & 1 deletion rula-exec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ description = "Generate executable Rust code for RuLa program"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rula_parser = { path = "../rula-parser" }
rula-parser = { path = "../rula-parser" }
ruleset-ir = {path = "../ruleset-ir"}
# (rula_ast -> rula_program(rust syntax tree) -> quote -> rust_source)
quote = "1.0"
syn = {version = "1.0", features = ["full"]}
Expand Down
5 changes: 5 additions & 0 deletions rula-exec/src/generator/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[derive(Debug)]
pub enum CompileError{
ParentScopeNotFoundError,
ParentScopeDroppedError,
}
103 changes: 103 additions & 0 deletions rula-exec/src/generator/generator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use super::scope::Scope;
use super::{symbol_table::SymbolTable, IResult};
use rula_parser::parser::ast::*;
use ruleset_ir::instructions::*;
use ruleset_ir::RuleSetIR;
use std::cell::RefCell;
use std::rc::Rc;

// Create symbol table to track new symbols
// type RefSymbolTable = RefCell<SymbolTable>;
type RcRefCellScope = Rc<RefCell<Scope>>;

// Convert RuLa expressions into RuleSet IR
pub fn generate_ir(ast_tree: &AstNode) -> IResult<RuleSetIR> {
// create symbol table to track new symbols
// let symbol_table = RefCell::new(SymbolTable::new());
// Prepare a root global scope
let global_scope = Rc::new(RefCell::new(Scope::new("__@global")));
global_scope.borrow_mut().set_root();

// Generate ir segment
let mut ir_segment = RuleSetIR::new();
let mut generated_ir = match ast_tree {
AstNode::RuLa(rula) => generate_rula_ir(rula, &global_scope).unwrap(),
AstNode::PlaceHolder => todo!(),
};

ir_segment.merge(&mut generated_ir);
Ok(ir_segment)
}

fn generate_rula_ir(rula: &RuLa, parent_scope: &RcRefCellScope) -> IResult<RuleSetIR> {
// At this level, new scope is not introduced.
// Ir segment for rula_ir
let mut rula_ir_segment = RuleSetIR::new();
let mut generated_ir = match &*rula.rula {
RuLaKind::Program(program) => generate_program_ir(program, &parent_scope).unwrap(),
RuLaKind::Ignore => {
let mut ignorant_ir = RuleSetIR::new();
ignorant_ir.add_instruction(Box::new(NOP::new(None)));
ignorant_ir
}
_ => todo!(),
};
rula_ir_segment.merge(&mut generated_ir);
Ok(rula_ir_segment)
}

fn generate_program_ir(program: &Program, parent_scope: &RcRefCellScope) -> IResult<RuleSetIR> {
// For program level ir, prepare segment ir for all the program asts
let mut program_ir_segment = RuleSetIR::new();
for prog in program.programs.iter() {
let mut generated_ir = match prog {
ProgramKind::Import(import) => generate_import_ir(import, parent_scope).unwrap(),
ProgramKind::RuleSetExpr(ruleset) => {
generate_ruleset_expr_ir(ruleset, parent_scope).unwrap()
}
ProgramKind::RuleExpr(rule) => generate_rule_expr_ir(rule, parent_scope).unwrap(),
ProgramKind::Repeaters => {
todo!()
}
};

program_ir_segment.merge(&mut generated_ir)
}
Ok(program_ir_segment)
}

fn generate_import_ir(import: &Import, parent_scope: &RcRefCellScope) -> IResult<RuleSetIR> {


Ok(RuleSetIR::new())
}

fn generate_ruleset_expr_ir(
ruleset_expr: &RuleSetExpr,
parent_scope: &RcRefCellScope,
) -> IResult<RuleSetIR> {
let ruleset_name = &*ruleset_expr.name.name;

// Introduce a new scope for ruleset clause
let ruleset_scope_name = String::from("__@ruleset_") + ruleset_name;
let ruleset_scope = Rc::new(RefCell::new(Scope::new(&ruleset_scope_name)));
ruleset_scope.borrow_mut().set_parent(Rc::downgrade(&parent_scope));

//
Ok(RuleSetIR::new())
}

fn generate_rule_expr_ir(
rule_expr: &RuleExpr,
parent_scope: &RcRefCellScope,
) -> IResult<RuleSetIR> {
let rule_name = &*rule_expr.name.name;

// Introduce a new scope for rule clause
let rule_scope_name = String::from("__@rule_") + rule_name;
let rule_scope = Rc::new(RefCell::new(Scope::new(&rule_scope_name)));
rule_scope.borrow_mut().set_parent(Rc::downgrade(&parent_scope));


Ok(RuleSetIR::new())
}
103 changes: 103 additions & 0 deletions rula-exec/src/generator/scope.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use std::collections::HashMap;

use super::IResult;
use super::error::CompileError;
use super::symbol_table::SymbolInfo;
use std::cell::RefCell;
use std::rc::{Rc, Weak};

type SymbolName = String;

// Scope Tree Node can only have one parent and could have multiple children
#[derive(Debug)]
pub struct Scope {
pub root: bool,
pub scope_name: String,
pub symbols: HashMap<SymbolName, SymbolInfo>,
// child scope cannot make changes on parent scope
pub parent: Option<Weak<RefCell<Scope>>>,
// child scope might be changed
pub children: RefCell<Vec<Rc<RefCell<Scope>>>>,
}

impl Scope {
pub fn new(scope_name: &str) -> Self {
Scope {
root: false,
// Default scope name set in the first node
scope_name: scope_name.to_string(),
symbols: HashMap::new(),
parent: None,
children: RefCell::new(vec![]),
}
}

pub fn set_root(&mut self) {
match &self.parent {
Some(_parent) => {
panic!("A scope that has parent scope cannot be a root scope")
}
None => {
self.root = true;
}
}
}

pub fn add_child(&self, child: Rc<RefCell<Scope>>) -> IResult<()> {
// If there is no parent scope found, return error
match &child.borrow_mut().parent {
// Parent information must be set before added
Some(_parent) => { /*found parent scope */ }
None => return Err(CompileError::ParentScopeNotFoundError),
}
self.children.borrow_mut().push(child);
Ok(())
}

pub fn set_parent(&mut self, parent: Weak<RefCell<Scope>>) {
self.parent = Some(parent);
}

pub fn ref_parent(&self) -> IResult<Option<Rc<RefCell<Scope>>>> {
match &self.parent {
Some(parent_ref) => {
// check if the parent is still alive
match parent_ref.upgrade() {
Some(parent) => Ok(Some(parent)),
None => Err(CompileError::ParentScopeDroppedError),
}
}
// Root node
None => Ok(None),
}
}

pub fn add_symbol(&mut self, symbol_name: &str, symbol_info: SymbolInfo) {
self.symbols.insert(symbol_name.to_string(), symbol_info);
}

pub fn get_symbol_info(&self, symbol_name: &str) -> Option<SymbolInfo> {
// found in the current scope
match self.symbols.get(symbol_name) {
Some(symbol_info) => Some(symbol_info.clone()),
None => {
// get parent node
// FIXME: Don't wanna clone
match self.ref_parent().unwrap() {
Some(parent_node) => {
let symbol = parent_node
.borrow()
.get_symbol_info(symbol_name)
.expect("Failed to find the symbol")
.clone();
return Some(symbol);
}
None => {
// No more parent here
return None;
}
}
}
}
}
}
80 changes: 80 additions & 0 deletions rula-exec/src/generator/symbol_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use super::scope::Scope;
use super::types::Types;

#[derive(Debug)]
pub struct SymbolTable {
// scope hierarchy that can be climbed up to global scope
pub scope_tree: Box<Scope>,
}

impl SymbolTable {
pub fn new() -> Self {
SymbolTable {
// default scope name "__@" will be replaced by global scope "__@global"
scope_tree: Box::new(Scope::new("__@")),
}
}
}

// For one symbol
#[derive(Debug, Clone)]
pub struct SymbolInfo {
// Data type used in RuLa
pub data_type: Types,
}

impl SymbolInfo {
pub fn new() -> Self {
SymbolInfo {
data_type: Types::Unknown,
}
}
}

#[cfg(test)]
mod tests {
use std::rc::Rc;
use std::cell::RefCell;
use super::*;

#[test]
fn test_scope_tree_creation() {
// parent scope
let parent = Rc::new(RefCell::new(Scope::new("__@parent")));
// child scope
let child = Rc::new(RefCell::new(Scope::new("__@child")));
// register parent scope
child.borrow_mut().set_parent(Rc::downgrade(&parent));

// Check if it's possible to refer to the parent from child
let parent_ref = match child.borrow().ref_parent().unwrap() {
Some(paref) => paref,
None => {
panic!("No parents found");
}
};
assert_eq!(parent_ref.borrow().scope_name, String::from("__@parent"));
}

#[test]
fn test_scope_tree_look_up() {
// climb up to root to find a value
// root scope
let root = Rc::new(RefCell::new(Scope::new("__@root")));
root.borrow_mut()
.add_symbol("root_symbol", SymbolInfo::new());
// child scope
let child = Rc::new(RefCell::new(Scope::new("__@child")));
// grandchild
let grand_child = Rc::new(RefCell::new(Scope::new("__@grand_child")));

grand_child.borrow_mut().set_parent(Rc::downgrade(&child));
child.borrow_mut().set_parent(Rc::downgrade(&root));

let root_symbol = child
.borrow_mut()
.get_symbol_info("root_symbol")
.expect("Failed to get symbol");
assert_eq!(root_symbol.data_type, Types::Unknown);
}
}
5 changes: 5 additions & 0 deletions rula-exec/src/generator/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

#[derive(Debug, Clone, PartialEq)]
pub enum Types{
Unknown
}
17 changes: 17 additions & 0 deletions rula-exec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,21 @@
extern crate quote;
extern crate syn;

pub mod generator{
pub mod generator;
pub mod symbol_table;
pub mod scope;
pub mod types;

#[cfg(not(tarpaulin_include))]
mod error;

use error::CompileError;
type IResult<T> = std::result::Result<T, CompileError>;
}

// Generator of ruleset
#[deprecated]
pub mod ruleset_gen {
#[cfg(not(tarpaulin_include))]
mod error;
Expand All @@ -12,14 +26,17 @@ pub mod ruleset_gen {
pub mod conf_parser;
pub mod factory;
pub mod ruleset;
// ruleset_generator generates RuleSet in json format
pub mod ruleset_generator;
pub mod tracker;
pub mod types;

mod test_ruleset_generator;

use error::InternalError;
use error::RuleSetGenError;
type IResult<T> = std::result::Result<T, RuleSetGenError>;
type InternalResult<T> = std::result::Result<T, InternalError>;
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion rula-exec/src/ruleset_gen/action.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{ruleset::ProtocolMessages, types::RuLaResult};
use super::ruleset::ProtocolMessages;
use core::time::Duration;
use serde::{Deserialize, Serialize};

Expand Down
2 changes: 1 addition & 1 deletion rula-exec/src/ruleset_gen/condition.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::ruleset::{PartnerAddr, ProtocolMessages};
use serde::{Deserialize, Serialize};
use crate::ruleset_gen::ruleset::AddressKind;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct Condition {
Expand Down
Loading