From ea6827ffd1fe5b5ebc5687d2aa9fbd76df4e45e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=B3=E5=8D=9A=E6=96=87?= Date: Sat, 6 Jan 2024 22:50:39 +0800 Subject: [PATCH] feat: Add uuid for functions --- Cargo.lock | 60 +++++++++++++++++ lib/Cargo.toml | 1 + lib/src/ast/declaration_statement.rs | 14 ++++ lib/src/ast/function_declaration.rs | 1 - lib/src/ast/mod.rs | 22 +++++++ lib/src/backend/lua/bytecode.rs | 5 ++ lib/src/backend/lua/mod.rs | 1 + lib/src/backend/lua/vm.rs | 1 + lib/src/context/mod.rs | 2 + lib/src/context/module_context.rs | 72 ++++++++++++++++++++- lib/src/context/task.rs | 5 ++ lib/src/lib.rs | 2 + viewer/src/column_object.rs | 16 +++++ viewer/src/main.rs | 6 ++ viewer/src/stc_viewer.rs | 4 ++ viewer/src/storage.rs | 12 +++- viewer/test_projects/example1/test_proj.xml | 2 +- 17 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 lib/src/backend/lua/vm.rs create mode 100644 lib/src/context/task.rs diff --git a/Cargo.lock b/Cargo.lock index ebd6fae..f863a84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1243,6 +1243,12 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "precomputed-hash" version = "0.1.1" @@ -1331,6 +1337,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1569,6 +1605,7 @@ dependencies = [ "regex", "smallmap", "smallvec", + "uuid", ] [[package]] @@ -1999,6 +2036,29 @@ dependencies = [ "serde", ] +[[package]] +name = "uuid" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +dependencies = [ + "getrandom", + "rand", + "serde", + "uuid-macro-internal", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49e7f3f3db8040a100710a11932239fd30697115e2ba4107080d8252939845e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "valuable" version = "0.1.0" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 05e6b97..61f7a7f 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -25,6 +25,7 @@ smallvec = { version = "*", features = ["union", "const_generics", "const_new"] smallmap = "*" log = "*" indexmap = "*" +uuid = { version = "*", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] } [build-dependencies] cbindgen = "*" diff --git a/lib/src/ast/declaration_statement.rs b/lib/src/ast/declaration_statement.rs index 8321ba4..2c158a4 100644 --- a/lib/src/ast/declaration_statement.rs +++ b/lib/src/ast/declaration_statement.rs @@ -19,6 +19,20 @@ pub struct Declaration { pub kind: DeclKind, } +impl HasAttribute for Declaration { + fn set_attribute, V: Into>(&mut self, k: K, v: V) { + todo!() + } + + fn get_attribute_value>(&self, attr: &S) -> Option<&String> { + todo!() + } + + fn remove_attribute>(&mut self, k: K) -> Option { + todo!() + } +} + impl Declaration { pub fn identifier(&self) -> &StString { match self.kind { diff --git a/lib/src/ast/function_declaration.rs b/lib/src/ast/function_declaration.rs index 6e9c88c..3849ab6 100644 --- a/lib/src/ast/function_declaration.rs +++ b/lib/src/ast/function_declaration.rs @@ -6,7 +6,6 @@ use std::rc::Rc; #[derive(Debug)] pub struct FunctionDeclare { name: StString, - #[allow(dead_code)] decl_class: DeclareClass, return_type: Option>>, parameters: SmallVec<[Rc; 8]>, diff --git a/lib/src/ast/mod.rs b/lib/src/ast/mod.rs index 750443f..b6b0771 100644 --- a/lib/src/ast/mod.rs +++ b/lib/src/ast/mod.rs @@ -157,6 +157,28 @@ impl Display for dyn Type { } } +bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] + pub struct CompilePassFlags: u32 { + const NONE = 0b0000_0000_0000_0000; + + // HasError + const HAS_ERROR = 0b0001_0000_0000_0001; + // TypeChecked + const TYPE_CHECKED = 0b0000_0000_0000_0010; + } +} + +bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] + pub struct FunctionFlags: u32 { + const NONE = 0b0000_0000_0000_0000; + + // This Function generated by compiler + const COMPILER_GENERATED = 0b0000_0000_0000_0001; + } +} + bitflags! { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct VariableFlags: u32 { diff --git a/lib/src/backend/lua/bytecode.rs b/lib/src/backend/lua/bytecode.rs index ba812e2..793ae50 100644 --- a/lib/src/backend/lua/bytecode.rs +++ b/lib/src/backend/lua/bytecode.rs @@ -57,6 +57,8 @@ pub enum LuaByteCode { LoadI(u8, u32), /// A B C: R[A] := R[B] + R[C] Add(u8, u8, u8), + /// A sB k: if ((R[A] >= sB) ~= k) then pc++ + Gei(u8, u8, u8), } impl LuaByteCode { @@ -69,6 +71,7 @@ impl LuaByteCode { LuaByteCode::Move(..) => "MOVE", LuaByteCode::LoadI(..) => "LOADI", LuaByteCode::Add(..) => "ADD", + LuaByteCode::Gei(..) => "GEI", } } @@ -81,6 +84,7 @@ impl LuaByteCode { LuaByteCode::Move(..) => LuaOpCode::OP_MOVE, LuaByteCode::LoadI(..) => LuaOpCode::OP_LOADI, LuaByteCode::Add(..) => LuaOpCode::OP_ADD, + LuaByteCode::Gei(..) => LuaOpCode::OP_GEI, } } } @@ -101,6 +105,7 @@ impl LuaCode { LuaByteCode::Call(a, b, c) | LuaByteCode::GetTabUp(a, b, c) | LuaByteCode::SetTabUp(a, b, c) + | LuaByteCode::Gei(a, b, c) | LuaByteCode::Add(a, b, c) => { write!(s, "{a} {b} {c}").unwrap(); } diff --git a/lib/src/backend/lua/mod.rs b/lib/src/backend/lua/mod.rs index 3b595ca..7486fae 100644 --- a/lib/src/backend/lua/mod.rs +++ b/lib/src/backend/lua/mod.rs @@ -6,6 +6,7 @@ use bytecode::*; mod encoding; mod register; mod utils; +mod vm; use crate::backend::lua::register::{RegisterId, RegisterManager}; use crate::backend::lua::utils::try_fit_sbx; diff --git a/lib/src/backend/lua/vm.rs b/lib/src/backend/lua/vm.rs new file mode 100644 index 0000000..128244f --- /dev/null +++ b/lib/src/backend/lua/vm.rs @@ -0,0 +1 @@ +pub struct LuaVM {} diff --git a/lib/src/context/mod.rs b/lib/src/context/mod.rs index be3f2bb..db71c4d 100644 --- a/lib/src/context/mod.rs +++ b/lib/src/context/mod.rs @@ -5,6 +5,8 @@ mod units_manager; pub use units_manager::UnitsManager; mod scope; +mod task; + pub use scope::Scope; pub enum ModuleContextScope { diff --git a/lib/src/context/module_context.rs b/lib/src/context/module_context.rs index f649dd9..2e94dc2 100644 --- a/lib/src/context/module_context.rs +++ b/lib/src/context/module_context.rs @@ -1,9 +1,12 @@ use crate::ast::*; use crate::backend::TargetCode; +use crate::context::task::TaskInfo; use crate::context::ModuleContextScope; use crate::parser::StString; use indexmap::IndexMap; +use log::warn; use once_cell::sync::Lazy; +use smallvec::smallvec; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::fmt::{Display, Formatter}; @@ -12,6 +15,7 @@ use std::ops::Deref; use std::rc::Rc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; +use uuid::Uuid; static CONTEXT_ID: Lazy = Lazy::new(|| AtomicUsize::new(0)); static DECLARATION_ID: Lazy = Lazy::new(|| AtomicUsize::new(0)); @@ -57,6 +61,12 @@ impl Prototype { inner: Rc::new(RwLock::new(PrototypeImpl::new(decl))), } } + + fn with_object_id(decl: Declaration, id: Uuid) -> Self { + Self { + inner: Rc::new(RwLock::new(PrototypeImpl::with_object_id(decl, id))), + } + } } #[derive(Clone)] @@ -79,6 +89,12 @@ impl Function { } } + fn with_prototype(proto: &Prototype, function: Statement) -> Self { + Self { + inner: Rc::new(RwLock::new(FunctionImpl::with_prototype(proto, function))), + } + } + pub fn read(&self) -> RwLockReadGuard<'_, FunctionImpl> { self.inner.read().unwrap() } @@ -90,6 +106,7 @@ impl Function { pub struct PrototypeImpl { id: usize, + object_id: Uuid, decl: Declaration, } @@ -97,10 +114,23 @@ impl PrototypeImpl { fn new(decl: Declaration) -> Self { Self { id: get_next_declaration_id(), + object_id: Uuid::nil(), decl, } } + fn with_object_id(decl: Declaration, id: Uuid) -> Self { + Self { + id: get_next_declaration_id(), + object_id: id, + decl, + } + } + + pub fn object_id(&self) -> Uuid { + self.object_id + } + pub fn decl(&self) -> &Declaration { &self.decl } @@ -194,6 +224,7 @@ impl Display for PrototypeImpl { pub struct FunctionImpl { decl_id: usize, + object_id: Uuid, parse_tree: Statement, compiled_code: Option>, } @@ -202,11 +233,27 @@ impl FunctionImpl { fn new(decl_id: usize, function: Statement) -> Self { Self { decl_id, + object_id: Uuid::nil(), parse_tree: function, compiled_code: None, } } + fn with_prototype(proto: &Prototype, function: Statement) -> Self { + let proto = proto.read().unwrap(); + + Self { + decl_id: proto.id, + object_id: proto.object_id(), + parse_tree: function, + compiled_code: None, + } + } + + pub fn object_id(&self) -> Uuid { + self.object_id + } + pub fn decl_id(&self) -> usize { self.decl_id } @@ -251,6 +298,7 @@ impl ModuleContext { declaration_name_map: HashMap::new(), function_id_map: IndexMap::new(), toplevel_global_variable_declarations: HashSet::new(), + task_info: smallvec![], })), } } @@ -271,6 +319,7 @@ pub struct ModuleContextImpl { declaration_name_map: HashMap, function_id_map: IndexMap, toplevel_global_variable_declarations: HashSet, + task_info: SmallVec8, } impl ModuleContextImpl { @@ -282,7 +331,7 @@ impl ModuleContextImpl { &self.scope } - pub fn add_declaration(&mut self, decl: Declaration) -> usize { + pub fn add_declaration(&mut self, decl: Declaration, id: Uuid) -> usize { let name = decl.identifier().clone(); let mut toplevel_global_variable_declaration = false; @@ -292,7 +341,7 @@ impl ModuleContextImpl { } } - let decl = Prototype::new(decl); + let decl = Prototype::with_object_id(decl, id); let proto_id = decl.read().unwrap().id; self.declaration_id_map.insert(proto_id, decl.clone()); @@ -306,7 +355,24 @@ impl ModuleContextImpl { } pub fn add_function(&mut self, decl_id: usize, fun: Statement) -> Option { - let fun = Function::new(decl_id, fun); + let fun = match self.get_declaration_by_id(decl_id) { + Some(decl) => Function::with_prototype(decl, fun), + _ => { + warn!("Declaration of function {decl_id} not found"); + Function::new(decl_id, fun) + } + }; + + self.function_id_map.insert(decl_id, fun) + } + + pub fn add_function_with_proto( + &mut self, + proto: &Prototype, + fun: Statement, + ) -> Option { + let decl_id = proto.read().unwrap().id; + let fun = Function::with_prototype(proto, fun); self.function_id_map.insert(decl_id, fun) } diff --git a/lib/src/context/task.rs b/lib/src/context/task.rs new file mode 100644 index 0000000..178ddde --- /dev/null +++ b/lib/src/context/task.rs @@ -0,0 +1,5 @@ +use uuid::Uuid; + +pub(crate) struct TaskInfo { + pub entry_object_id: Uuid, +} diff --git a/lib/src/lib.rs b/lib/src/lib.rs index b0d6384..b4cd2b7 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -12,6 +12,8 @@ pub mod prelude { pub use crate::ast::*; pub use crate::context::*; pub use crate::parser::StString; + + pub use uuid::Uuid; } #[cfg(test)] diff --git a/viewer/src/column_object.rs b/viewer/src/column_object.rs index 608cb4c..a737284 100644 --- a/viewer/src/column_object.rs +++ b/viewer/src/column_object.rs @@ -63,6 +63,14 @@ impl Display for ColumnObjectData { Self::Prototype(proto) => { let proto = proto.read().unwrap(); + // Prototype properties + let uuid = proto.object_id(); + if !uuid.is_nil() { + writeln!(f, "ObjectId: {}", uuid)?; + } + writeln!(f, "Id: {}", proto.id())?; + writeln!(f)?; + // name : return_value write!(f, "{}", proto.name())?; if let Some(ty) = proto.return_value().and_then(|x| x.ty()) { @@ -79,6 +87,14 @@ impl Display for ColumnObjectData { Self::Function(func) => { let func = func.read(); + // Function properties + let uuid = func.object_id(); + if !uuid.is_nil() { + writeln!(f, "ObjectId: {}", uuid)?; + } + writeln!(f, "DeclId: {}", func.decl_id())?; + writeln!(f)?; + if let Some(code) = func.compiled_code() { writeln!(f, "{}", code) } else { diff --git a/viewer/src/main.rs b/viewer/src/main.rs index f0e5609..bde743b 100644 --- a/viewer/src/main.rs +++ b/viewer/src/main.rs @@ -78,6 +78,7 @@ fn build_ui(app: &Application, mgr: UnitsManager) { let button_layout = gtk::Box::new(Orientation::Horizontal, 0); button_layout.add(&stc_app.refresh_button); button_layout.add(&stc_app.compile_button); + button_layout.add(&stc_app.run_button); let right_layout = gtk::Box::new(Orientation::Vertical, 0); right_layout.add(&button_layout); @@ -99,6 +100,11 @@ fn build_ui(app: &Application, mgr: UnitsManager) { .compile_button .connect_clicked(move |_| app_copy.lock().unwrap().compile()); + let app_copy = stc_app.clone(); + app_lock + .run_button + .connect_clicked(move |_| app_copy.lock().unwrap().run()); + let app_copy = stc_app.clone(); app_lock.tree_view.connect_cursor_changed(move |_| { if let Ok(app) = app_copy.try_lock() { diff --git a/viewer/src/stc_viewer.rs b/viewer/src/stc_viewer.rs index 0b83d07..e4c149d 100644 --- a/viewer/src/stc_viewer.rs +++ b/viewer/src/stc_viewer.rs @@ -33,6 +33,7 @@ pub struct StcViewerApp { pub search_entry: SearchEntry, pub refresh_button: Button, pub compile_button: Button, + pub run_button: Button, } impl StcViewerApp { @@ -58,6 +59,7 @@ impl StcViewerApp { search_entry: SearchEntry::new(), refresh_button: Button::with_label("Refresh"), compile_button: Button::with_label("Compile"), + run_button: Button::with_label("Run"), }; (r, rx) @@ -196,4 +198,6 @@ impl StcViewerApp { CodeGenerator::new(self.mgr.clone(), app_id).unwrap(); println!("CodeGen: {:?}", code_gen.build_application()); } + + pub fn run(&mut self) {} } diff --git a/viewer/src/storage.rs b/viewer/src/storage.rs index 491f83e..2075e98 100644 --- a/viewer/src/storage.rs +++ b/viewer/src/storage.rs @@ -1,6 +1,7 @@ use serde::{Deserialize, Serialize}; use stc::parser::{StDeclarationParser, StFunctionParser, StLexerBuilder}; use stc::prelude::*; +use std::str::FromStr; #[derive(Serialize, Deserialize, Debug)] pub enum AppType { @@ -37,7 +38,12 @@ impl From for ModuleContext { for pou in app.pou_list.pou { let lexer = StLexerBuilder::new().build_str(&pou.interface.content); let decl = StDeclarationParser::new().parse(lexer).unwrap(); - let func = ctx_write.add_declaration(decl); + let func = ctx_write.add_declaration( + decl, + pou.uuid_text + .and_then(|s| Uuid::from_str(&s).ok()) + .unwrap_or(Uuid::nil()), + ); if let Some(body) = pou.body { let lexer = StLexerBuilder::new().build_str(&body.content); @@ -59,8 +65,8 @@ pub struct POUList { #[derive(Serialize, Deserialize, Debug)] #[allow(clippy::upper_case_acronyms)] pub struct POU { - #[serde(rename = "@guid-text")] - pub guid_text: Option, + #[serde(rename = "@uuid-text")] + pub uuid_text: Option, pub interface: POUInterface, pub body: Option, } diff --git a/viewer/test_projects/example1/test_proj.xml b/viewer/test_projects/example1/test_proj.xml index 3aacf22..e68ab34 100644 --- a/viewer/test_projects/example1/test_proj.xml +++ b/viewer/test_projects/example1/test_proj.xml @@ -9,7 +9,7 @@ - + program prg: int VAR