From 9ab283d20074e2666ce670328a4f93fd028f422b Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 31 May 2023 16:27:44 +0200 Subject: [PATCH 01/17] update feature cardinality --- uvls/src/core/ast.rs | 6 ++++++ uvls/src/core/ast/def.rs | 5 +++++ uvls/src/core/ast/transform.rs | 7 +++++-- uvls/src/core/config.rs | 7 +++++++ uvls/src/smt/smt_lib.rs | 2 ++ uvls/src/webview.rs | 5 ++++- uvls/src/webview/frontend.rs | 29 +++++++++++++++++++++++++++++ 7 files changed, 58 insertions(+), 3 deletions(-) diff --git a/uvls/src/core/ast.rs b/uvls/src/core/ast.rs index eb797416..96b23757 100644 --- a/uvls/src/core/ast.rs +++ b/uvls/src/core/ast.rs @@ -430,6 +430,12 @@ impl AstDocument { _ => None, } } + // pub fn get_cardinality(&self, sym: Symbol) -> Option { + // match sym { + // Symbol::Feature(i) => Some(self.ast.features[i].cardinality), + // _ => None, + // } + // } pub fn find(&self, offset: usize) -> Option { self.ast.find(offset) } diff --git a/uvls/src/core/ast/def.rs b/uvls/src/core/ast/def.rs index d4e1197f..9373bc87 100644 --- a/uvls/src/core/ast/def.rs +++ b/uvls/src/core/ast/def.rs @@ -43,6 +43,10 @@ impl Path { } } + +type Min = f64; +type Max = f64; + //Type definitions for symbols #[bitflags] #[repr(u8)] @@ -55,6 +59,7 @@ pub enum Type { Bool, Void, Namespace, + Range } #[derive(Clone, Debug)] diff --git a/uvls/src/core/ast/transform.rs b/uvls/src/core/ast/transform.rs index 07189a65..411ff085 100644 --- a/uvls/src/core/ast/transform.rs +++ b/uvls/src/core/ast/transform.rs @@ -909,16 +909,16 @@ fn visit_attributes(state: &mut VisitorState, parent: Symbol) { } } -fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, ty: Type) { +fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, mut ty: Type) { match parent { Symbol::Feature(..) => { state.push_error(40, "features have to be separated by groups"); } _ => {} } + let feature = Feature { name, - ty, cardinality: state .node() .parent() @@ -926,8 +926,11 @@ fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, ty: .child_by_field_name("cardinality") .and_then(|n| { check_langlvls(state, LanguageLevel::SMT(vec![LanguageLevelSMT::FeatureCardinality])); + ty = Type::Range; opt_cardinality(n, state) }), + ty, + }; let sym = Symbol::Feature(state.ast.features.len()); state.ast.features.push(feature); diff --git a/uvls/src/core/config.rs b/uvls/src/core/config.rs index 5b0ebc32..1442651b 100644 --- a/uvls/src/core/config.rs +++ b/uvls/src/core/config.rs @@ -35,6 +35,8 @@ use ustr::Ustr; //JSON parsing is done with tree-sitter and not serde because there currently is no solid serde json //crate for span information and partial parsing so error reporting becomes impossible. +type Min = f64; +type Max = f64; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(untagged)] @@ -42,6 +44,7 @@ pub enum ConfigValue { Bool(bool), Number(f64), String(String), + Range(Min,Max,f64), } impl ConfigValue { pub fn ty(&self) -> Type { @@ -49,12 +52,15 @@ impl ConfigValue { Self::Bool(..) => Type::Bool, Self::Number(..) => Type::Real, Self::String(..) => Type::String, + Self::Range(..) => Type::Range, + } } pub fn default(ty: Type) -> ConfigValue { match ty { Type::Bool => ConfigValue::Bool(false), Type::Real => ConfigValue::Number(0.0), + Type::Range => ConfigValue::Range(0.0, 4.0,0.0), Type::String => ConfigValue::String("".into()), _ => unimplemented!(), } @@ -69,6 +75,7 @@ impl Display for ConfigValue { Self::Bool(x) => write!(f, "{x}"), Self::Number(x) => write!(f, "{x}"), Self::String(x) => write!(f, "{x}"), + Self::Range(_,_,x) => write!(f, "{x}"), } } } diff --git a/uvls/src/smt/smt_lib.rs b/uvls/src/smt/smt_lib.rs index 1062615b..916926e9 100644 --- a/uvls/src/smt/smt_lib.rs +++ b/uvls/src/smt/smt_lib.rs @@ -390,6 +390,7 @@ impl<'a> SMTBuilder<'a> { Type::String => { Expr::Not(Expr::Equal(vec![self.var(ms), Expr::String("".into())]).into()) } + Type::Range => Expr::Bool(true),//TODO _ => unimplemented!(), } } @@ -425,6 +426,7 @@ impl Into for ConfigValue { Self::Bool(b) => Expr::Bool(b), Self::Number(n) => Expr::Real(n), Self::String(s) => Expr::String(s), + Self::Range(_,_ ,n ) => if n <= 0.0 { Expr::Bool(false)} else {Expr::Bool(true)}, } } } diff --git a/uvls/src/webview.rs b/uvls/src/webview.rs index b1615042..a5559596 100644 --- a/uvls/src/webview.rs +++ b/uvls/src/webview.rs @@ -239,7 +239,10 @@ fn create_file_tree( Symbol::Feature(_) | Symbol::Attribute(_) => { let depth = depth + base_depth - 1; match file.type_of(sym).unwrap() { - Type::String | Type::Real | Type::Bool | Type::Attributes => {} + Type::Real => { + + } + Type::String | Type::Bool | Type::Attributes => {} _ => { return true; } diff --git a/uvls/src/webview/frontend.rs b/uvls/src/webview/frontend.rs index db0aa038..528e4369 100644 --- a/uvls/src/webview/frontend.rs +++ b/uvls/src/webview/frontend.rs @@ -137,7 +137,27 @@ fn RealInput(cx: Scope,init_val:f64,sym: ModuleSymbol,tag: u8)->Element{ }) } +#[inline_props] +fn RangeInput(cx: Scope,init_val:f64,sym: ModuleSymbol,tag: u8,min: f64,max:f64)->Element{ + let tx = use_coroutine_handle::(cx).unwrap(); + let val = use_state(cx,||init_val.to_string()); + cx.render(rsx! { + input{ + class:"input-value", + r#type:"number", + required:true, + value:"{val}", + min:"{min}", + max:"{max}", + oninput:move |e|{ + val.set(to_number(&e.value)); + tx.send(UIAction::Set(*sym,*tag,ConfigValue::Number(val.parse().unwrap_or(0.0)))); + + } + } + }) +} fn ConfigInput<'a>(cx: Scope<'a, ConfigInputProps<'a>>) -> Element { let ConfigInputProps { ty, @@ -195,6 +215,15 @@ fn ConfigInput<'a>(cx: Scope<'a, ConfigInputProps<'a>>) -> Element { } } }, + ConfigValue::Range(min,max, x) => rsx! { + RangeInput{ + sym:*sym, + init_val:*x, + tag:*tag, + min: *min, + max: *max, + } + } }; cx.render(rsx! { div{ From 54100a498b808d03092bf5435fffdc2bf1954927 Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 7 Jun 2023 15:08:39 +0200 Subject: [PATCH 02/17] Revert "update feature cardinality" This reverts commit 9ab283d20074e2666ce670328a4f93fd028f422b. --- uvls/src/core/ast.rs | 6 ------ uvls/src/core/ast/def.rs | 5 ----- uvls/src/core/ast/transform.rs | 7 ++----- uvls/src/core/config.rs | 7 ------- uvls/src/smt/smt_lib.rs | 2 -- uvls/src/webview.rs | 5 +---- uvls/src/webview/frontend.rs | 29 ----------------------------- 7 files changed, 3 insertions(+), 58 deletions(-) diff --git a/uvls/src/core/ast.rs b/uvls/src/core/ast.rs index 96b23757..eb797416 100644 --- a/uvls/src/core/ast.rs +++ b/uvls/src/core/ast.rs @@ -430,12 +430,6 @@ impl AstDocument { _ => None, } } - // pub fn get_cardinality(&self, sym: Symbol) -> Option { - // match sym { - // Symbol::Feature(i) => Some(self.ast.features[i].cardinality), - // _ => None, - // } - // } pub fn find(&self, offset: usize) -> Option { self.ast.find(offset) } diff --git a/uvls/src/core/ast/def.rs b/uvls/src/core/ast/def.rs index 9373bc87..d4e1197f 100644 --- a/uvls/src/core/ast/def.rs +++ b/uvls/src/core/ast/def.rs @@ -43,10 +43,6 @@ impl Path { } } - -type Min = f64; -type Max = f64; - //Type definitions for symbols #[bitflags] #[repr(u8)] @@ -59,7 +55,6 @@ pub enum Type { Bool, Void, Namespace, - Range } #[derive(Clone, Debug)] diff --git a/uvls/src/core/ast/transform.rs b/uvls/src/core/ast/transform.rs index 411ff085..07189a65 100644 --- a/uvls/src/core/ast/transform.rs +++ b/uvls/src/core/ast/transform.rs @@ -909,16 +909,16 @@ fn visit_attributes(state: &mut VisitorState, parent: Symbol) { } } -fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, mut ty: Type) { +fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, ty: Type) { match parent { Symbol::Feature(..) => { state.push_error(40, "features have to be separated by groups"); } _ => {} } - let feature = Feature { name, + ty, cardinality: state .node() .parent() @@ -926,11 +926,8 @@ fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, mut .child_by_field_name("cardinality") .and_then(|n| { check_langlvls(state, LanguageLevel::SMT(vec![LanguageLevelSMT::FeatureCardinality])); - ty = Type::Range; opt_cardinality(n, state) }), - ty, - }; let sym = Symbol::Feature(state.ast.features.len()); state.ast.features.push(feature); diff --git a/uvls/src/core/config.rs b/uvls/src/core/config.rs index 1442651b..5b0ebc32 100644 --- a/uvls/src/core/config.rs +++ b/uvls/src/core/config.rs @@ -35,8 +35,6 @@ use ustr::Ustr; //JSON parsing is done with tree-sitter and not serde because there currently is no solid serde json //crate for span information and partial parsing so error reporting becomes impossible. -type Min = f64; -type Max = f64; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(untagged)] @@ -44,7 +42,6 @@ pub enum ConfigValue { Bool(bool), Number(f64), String(String), - Range(Min,Max,f64), } impl ConfigValue { pub fn ty(&self) -> Type { @@ -52,15 +49,12 @@ impl ConfigValue { Self::Bool(..) => Type::Bool, Self::Number(..) => Type::Real, Self::String(..) => Type::String, - Self::Range(..) => Type::Range, - } } pub fn default(ty: Type) -> ConfigValue { match ty { Type::Bool => ConfigValue::Bool(false), Type::Real => ConfigValue::Number(0.0), - Type::Range => ConfigValue::Range(0.0, 4.0,0.0), Type::String => ConfigValue::String("".into()), _ => unimplemented!(), } @@ -75,7 +69,6 @@ impl Display for ConfigValue { Self::Bool(x) => write!(f, "{x}"), Self::Number(x) => write!(f, "{x}"), Self::String(x) => write!(f, "{x}"), - Self::Range(_,_,x) => write!(f, "{x}"), } } } diff --git a/uvls/src/smt/smt_lib.rs b/uvls/src/smt/smt_lib.rs index 916926e9..1062615b 100644 --- a/uvls/src/smt/smt_lib.rs +++ b/uvls/src/smt/smt_lib.rs @@ -390,7 +390,6 @@ impl<'a> SMTBuilder<'a> { Type::String => { Expr::Not(Expr::Equal(vec![self.var(ms), Expr::String("".into())]).into()) } - Type::Range => Expr::Bool(true),//TODO _ => unimplemented!(), } } @@ -426,7 +425,6 @@ impl Into for ConfigValue { Self::Bool(b) => Expr::Bool(b), Self::Number(n) => Expr::Real(n), Self::String(s) => Expr::String(s), - Self::Range(_,_ ,n ) => if n <= 0.0 { Expr::Bool(false)} else {Expr::Bool(true)}, } } } diff --git a/uvls/src/webview.rs b/uvls/src/webview.rs index a5559596..b1615042 100644 --- a/uvls/src/webview.rs +++ b/uvls/src/webview.rs @@ -239,10 +239,7 @@ fn create_file_tree( Symbol::Feature(_) | Symbol::Attribute(_) => { let depth = depth + base_depth - 1; match file.type_of(sym).unwrap() { - Type::Real => { - - } - Type::String | Type::Bool | Type::Attributes => {} + Type::String | Type::Real | Type::Bool | Type::Attributes => {} _ => { return true; } diff --git a/uvls/src/webview/frontend.rs b/uvls/src/webview/frontend.rs index 528e4369..db0aa038 100644 --- a/uvls/src/webview/frontend.rs +++ b/uvls/src/webview/frontend.rs @@ -137,27 +137,7 @@ fn RealInput(cx: Scope,init_val:f64,sym: ModuleSymbol,tag: u8)->Element{ }) } -#[inline_props] -fn RangeInput(cx: Scope,init_val:f64,sym: ModuleSymbol,tag: u8,min: f64,max:f64)->Element{ - let tx = use_coroutine_handle::(cx).unwrap(); - let val = use_state(cx,||init_val.to_string()); - cx.render(rsx! { - input{ - class:"input-value", - r#type:"number", - required:true, - value:"{val}", - min:"{min}", - max:"{max}", - oninput:move |e|{ - val.set(to_number(&e.value)); - tx.send(UIAction::Set(*sym,*tag,ConfigValue::Number(val.parse().unwrap_or(0.0)))); - - } - } - }) -} fn ConfigInput<'a>(cx: Scope<'a, ConfigInputProps<'a>>) -> Element { let ConfigInputProps { ty, @@ -215,15 +195,6 @@ fn ConfigInput<'a>(cx: Scope<'a, ConfigInputProps<'a>>) -> Element { } } }, - ConfigValue::Range(min,max, x) => rsx! { - RangeInput{ - sym:*sym, - init_val:*x, - tag:*tag, - min: *min, - max: *max, - } - } }; cx.render(rsx! { div{ From 597fd244e921379e2505444a371116a8f1009adf Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 7 Jun 2023 17:19:30 +0200 Subject: [PATCH 03/17] update feature cardinality --- uvls/src/core/ast/def.rs | 2 - uvls/src/core/ast/transform.rs | 85 +++++++++++++++++++++++++++------- uvls/src/smt.rs | 3 ++ uvls/src/smt/smt_lib.rs | 7 --- 4 files changed, 71 insertions(+), 26 deletions(-) diff --git a/uvls/src/core/ast/def.rs b/uvls/src/core/ast/def.rs index d4e1197f..cd30b532 100644 --- a/uvls/src/core/ast/def.rs +++ b/uvls/src/core/ast/def.rs @@ -67,9 +67,7 @@ pub enum GroupMode { } #[derive(Clone, Debug)] pub enum Cardinality { - From(usize), Range(usize, usize), - Max(usize), Any, } #[derive(Clone, Debug)] diff --git a/uvls/src/core/ast/transform.rs b/uvls/src/core/ast/transform.rs index 07189a65..bc82ec57 100644 --- a/uvls/src/core/ast/transform.rs +++ b/uvls/src/core/ast/transform.rs @@ -4,6 +4,7 @@ use ast::Ast; use check::ErrorInfo; use parse::*; use semantic::FileID; +use ustr::Ustr; use util::{node_range}; use log::info; use ropey::Rope; @@ -491,8 +492,7 @@ fn opt_cardinality(node: Node, state: &mut VisitorState) -> Option opt_int(begin, state)?, opt_int(end.unwrap(), state)?, )), - (Some(begin), Some("*")) => Some(Cardinality::From(opt_int(begin, state)?)), - (None, Some("int")) => Some(Cardinality::Max(opt_int(end.unwrap(), state)?)), + (None, Some("int")) => Some(Cardinality::Range(0, opt_int(end.unwrap(), state)?)), (_, _) => Some(Cardinality::Any), } } @@ -909,7 +909,45 @@ fn visit_attributes(state: &mut VisitorState, parent: Symbol) { } } +fn visit_cardinality(state: &mut VisitorState, parent: Symbol, ty: Type, feature: Feature){ + let cardinality = feature.cardinality.unwrap(); + match cardinality { + Cardinality::Any => info!("FUUUUUUUCK Cardinality Any detected!!!!!!!!!"), + Cardinality::Range(a, b) => { + info!(" cardinality"); + for i in 0 .. b { + let sym = Symbol::Feature(state.ast.features.len()); + let new_name = SymbolSpan { + name: Ustr::from(format!("{}[{}]", feature.name.name, i).as_str()), + span: feature.name.span.clone() + }; + let new_feature = Feature { + name: new_name, + ty: feature.ty.clone(), + cardinality: Some(Cardinality::Any), + }; + state.ast.features.push(new_feature); + state.push_child(parent, sym); + loop { + match state.kind() { + "attributes" => { + visit_children_arg(state, sym, visit_attributes); + } + "blk" => { + visit_children_arg(state, sym, visit_blk_decl); + } + _ => {} + } + if !state.goto_next_sibling() { + break; + } + } + } + } + } +} fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, ty: Type) { + info!("visit feature"); match parent { Symbol::Feature(..) => { state.push_error(40, "features have to be separated by groups"); @@ -929,23 +967,35 @@ fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, ty: opt_cardinality(n, state) }), }; - let sym = Symbol::Feature(state.ast.features.len()); - state.ast.features.push(feature); - state.push_child(parent, sym); - loop { - match state.kind() { - "attributes" => { - visit_children_arg(state, sym, visit_attributes); - } - "blk" => { - visit_children_arg(state, sym, visit_blk_decl); - } - _ => {} - } - if !state.goto_next_sibling() { - break; + + match feature.cardinality.clone() { + Some(cardinality) => { + visit_cardinality(state, parent, ty, feature); + + } + None =>{ + info!("no cardinality"); + let sym = Symbol::Feature(state.ast.features.len()); + state.ast.features.push(feature); + state.push_child(parent, sym); + loop { + match state.kind() { + "attributes" => { + visit_children_arg(state, sym, visit_attributes); + } + "blk" => { + visit_children_arg(state, sym, visit_blk_decl); + } + _ => {} + } + if !state.goto_next_sibling() { + break; + } + } } } + + } fn visit_ref(state: &mut VisitorState, parent: Symbol, path: Path) { @@ -1102,6 +1152,7 @@ fn visit_constraints(state: &mut VisitorState) { } fn visit_top_lvl(state: &mut VisitorState) { let mut top_level_order: Vec = Vec::new(); + info!("visit top level"); loop { if state.kind() == "blk" { let header = state.header().unwrap(); diff --git a/uvls/src/smt.rs b/uvls/src/smt.rs index d52e79f8..0ec3ce7d 100644 --- a/uvls/src/smt.rs +++ b/uvls/src/smt.rs @@ -347,6 +347,8 @@ async fn check_base_sat( async move { let smt_module = uvl2smt(&module, &HashMap::new()); let source = smt_module.to_source(&module); + info!("da"); + info!("{}",source); let model = create_model( &module, root.cancellation_token(), @@ -561,6 +563,7 @@ pub async fn check_handler( loop { info!("Check SMT"); let root = rx_root.borrow_and_update().clone(); + info!("test"); latest_versions = check_base_sat(&root, &tx_err, latest_versions).await; latest_versions_config = check_config(&root, &tx_err, &inlay_state, latest_versions_config).await; diff --git a/uvls/src/smt/smt_lib.rs b/uvls/src/smt/smt_lib.rs index 1062615b..65731f37 100644 --- a/uvls/src/smt/smt_lib.rs +++ b/uvls/src/smt/smt_lib.rs @@ -528,13 +528,6 @@ pub fn uvl2smt(module: &Module, config: &HashMap) -> } } GroupMode::Optional | GroupMode::Cardinality(Cardinality::Any) => {} - GroupMode::Cardinality(Cardinality::Max(max)) => { - builder.max_assert(max, &p_bind, m.sym(g)); - } - - GroupMode::Cardinality(Cardinality::From(min)) => { - builder.min_assert(min, &p_bind, m.sym(g)); - } GroupMode::Cardinality(Cardinality::Range(min, max)) => { builder.min_assert(min, &p_bind, m.sym(g)); builder.max_assert(max, &p_bind, m.sym(g)); From 4e66f6f007fbe96ef22adf71135a9133bdfec3ab Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Mon, 12 Jun 2023 17:15:27 +0200 Subject: [PATCH 04/17] update feature cardinality --- uvls/src/core/ast/def.rs | 3 +- uvls/src/core/ast/transform.rs | 350 ++++++++++++++++++++------------- uvls/src/core/ast/visitor.rs | 6 +- uvls/src/smt/smt_lib.rs | 4 +- 4 files changed, 226 insertions(+), 137 deletions(-) diff --git a/uvls/src/core/ast/def.rs b/uvls/src/core/ast/def.rs index cd30b532..93a107d0 100644 --- a/uvls/src/core/ast/def.rs +++ b/uvls/src/core/ast/def.rs @@ -68,7 +68,8 @@ pub enum GroupMode { #[derive(Clone, Debug)] pub enum Cardinality { Range(usize, usize), - Any, + Fixed, + } #[derive(Clone, Debug)] pub enum LanguageLevelMajor { diff --git a/uvls/src/core/ast/transform.rs b/uvls/src/core/ast/transform.rs index 493872ac..a1b4a2e6 100644 --- a/uvls/src/core/ast/transform.rs +++ b/uvls/src/core/ast/transform.rs @@ -1,18 +1,20 @@ use crate::core::*; +use ast::visitor::Visitor; use ast::visitor::*; use ast::Ast; use check::ErrorInfo; -use parse::*; -use semantic::FileID; -use ustr::Ustr; -use util::{node_range}; +use dioxus::html::b; +use futures_util::future::OrElse; use log::info; +use parse::*; use ropey::Rope; +use semantic::FileID; use std::borrow::{Borrow, Cow}; use tokio::time::Instant; use tower_lsp::lsp_types::{DiagnosticSeverity, Url}; use tree_sitter::{Node, Tree, TreeCursor}; -use ast::visitor::Visitor; +use ustr::Ustr; +use util::node_range; //Transform a tree-sitter tree into the Ast ECS via recursive decent //While parsing we keep a mutable state to store entities and errors #[derive(Clone)] @@ -260,7 +262,6 @@ fn check_simple_blk(state: &mut VisitorState, kind: &str) { } } - //report error if a node has cardinality or attributes fn check_no_extra_blk(state: &mut VisitorState, kind: &str) { match state.cursor.field_name() { @@ -306,7 +307,10 @@ fn opt_sat_minor(state: &mut VisitorState) -> Option { match state.kind() { "*" => Some(LanguageLevelSAT::Any), "group-cardinality" => Some(LanguageLevelSAT::GroupCardinality), - "feature-cardinality" | "aggregate-function" | "string-constraints" | "numeric-constraints" => { + "feature-cardinality" + | "aggregate-function" + | "string-constraints" + | "numeric-constraints" => { state.push_error(30, "not allowed under SAT"); None } @@ -362,14 +366,14 @@ fn opt_lang_lvl(state: &mut VisitorState) -> Option { } else { return None; } - }, + } LanguageLevel::SAT(v) => { if let Some(lvl) = visit_children(state, opt_sat_minor) { v.push(lvl); } else { return None; } - }, + } LanguageLevel::TYPE(v) => { if let Some(lvl) = visit_children(state, opt_type_minor) { v.push(lvl); @@ -379,7 +383,10 @@ fn opt_lang_lvl(state: &mut VisitorState) -> Option { } } } else { - state.push_error(30, "missing major level, please specify SMT, SAT or TYPE level"); + state.push_error( + 30, + "missing major level, please specify SMT, SAT or TYPE level", + ); return None; } } @@ -493,7 +500,7 @@ fn opt_cardinality(node: Node, state: &mut VisitorState) -> Option opt_int(end.unwrap(), state)?, )), (None, Some("int")) => Some(Cardinality::Range(0, opt_int(end.unwrap(), state)?)), - (_, _) => Some(Cardinality::Any), + (_, _) => Some(Cardinality::Range(0, 0)), } } @@ -557,43 +564,90 @@ fn opt_function_args(state: &mut VisitorState) -> Option> { } fn check_langlvls(state: &mut VisitorState, searched_lang_lvl: LanguageLevel) { - - if state.ast.includes.is_empty() { // no includes means, that implicitly everything is included + if state.ast.includes.is_empty() { + // no includes means, that implicitly everything is included return (); } - let includes: Vec = state.ast.includes.clone().into_iter().map(|x| x.lang_lvl).collect(); + let includes: Vec = state + .ast + .includes + .clone() + .into_iter() + .map(|x| x.lang_lvl) + .collect(); - fn check_sub_lang_lvls<'a, F, G, L: PartialEq>(mut m: F, mut get: G, sub_lang_lvls: Vec, includes: Vec, any: L) -> bool - where F: FnMut(&LanguageLevel) -> bool, G: FnMut(&LanguageLevel) -> Option>, { - sub_lang_lvls.is_empty() && includes.iter().any(|x| m(x)) || - sub_lang_lvls.iter().fold(false, |mut res, val: &L| -> bool { - for i in includes.iter(){ - let x = get(i).unwrap_or(vec![]); - if x.contains(&any) || x.contains(&val) { - res = true; - break; + fn check_sub_lang_lvls<'a, F, G, L: PartialEq>( + mut m: F, + mut get: G, + sub_lang_lvls: Vec, + includes: Vec, + any: L, + ) -> bool + where + F: FnMut(&LanguageLevel) -> bool, + G: FnMut(&LanguageLevel) -> Option>, + { + sub_lang_lvls.is_empty() && includes.iter().any(|x| m(x)) + || sub_lang_lvls + .iter() + .fold(false, |mut res, val: &L| -> bool { + for i in includes.iter() { + let x = get(i).unwrap_or(vec![]); + if x.contains(&any) || x.contains(&val) { + res = true; + break; + } } - } - res - }) + res + }) } if !match searched_lang_lvl.borrow() { LanguageLevel::SMT(s) => check_sub_lang_lvls( |x| matches!(x, LanguageLevel::SMT(_)), - |x| -> Option> {match x { LanguageLevel::SMT(l) => Some(l.to_vec()), _ => None}}, - s.clone(), includes, LanguageLevelSMT::Any), + |x| -> Option> { + match x { + LanguageLevel::SMT(l) => Some(l.to_vec()), + _ => None, + } + }, + s.clone(), + includes, + LanguageLevelSMT::Any, + ), LanguageLevel::SAT(s) => check_sub_lang_lvls( |x| matches!(x, LanguageLevel::SAT(_)), - |x| -> Option> {match x { LanguageLevel::SAT(l) => Some(l.to_vec()), _ => None}}, - s.clone(), includes, LanguageLevelSAT::Any), + |x| -> Option> { + match x { + LanguageLevel::SAT(l) => Some(l.to_vec()), + _ => None, + } + }, + s.clone(), + includes, + LanguageLevelSAT::Any, + ), LanguageLevel::TYPE(s) => check_sub_lang_lvls( |x| matches!(x, LanguageLevel::TYPE(_)), - |x| -> Option> {match x { LanguageLevel::TYPE(l) => Some(l.to_vec()), _ => None}}, - s.clone(), includes, LanguageLevelTYPE::Any) + |x| -> Option> { + match x { + LanguageLevel::TYPE(l) => Some(l.to_vec()), + _ => None, + } + }, + s.clone(), + includes, + LanguageLevelTYPE::Any, + ), } { - state.push_error(10, format!("Operation does not correspond includes. Please include {:?}", searched_lang_lvl)) + state.push_error( + 10, + format!( + "Operation does not correspond includes. Please include {:?}", + searched_lang_lvl + ), + ) } } @@ -632,7 +686,7 @@ fn opt_integer(state: &mut VisitorState) -> Option { visit_children(state, |state| { if state.goto_field("arg") { let n: Box = opt_numeric(state)?.into(); - let out = Some(Expr::Integer{op: op.clone(), n}); + let out = Some(Expr::Integer { op: op.clone(), n }); if state.goto_next_sibling() && state.goto_field("arg") { state.push_error(30, "expected exactly one argument"); } @@ -654,7 +708,8 @@ fn opt_numeric(state: &mut VisitorState) -> Option { "number" => Some(Expr::Number(opt_number(state)?)), "string" => Some(Expr::String(opt_string(state)?)), - "binary_expr" => { check_langlvls(state, LanguageLevel::SMT(vec![])); + "binary_expr" => { + check_langlvls(state, LanguageLevel::SMT(vec![])); let op = state.child_by_name("op").unwrap(); visit_children(state, |state| { if let Some(op) = opt_numeric_op(op) { @@ -678,13 +733,16 @@ fn opt_numeric(state: &mut VisitorState) -> Option { }) } "nested_expr" => visit_children(state, opt_numeric).map(|c| c.content), - "function" => {match state.slice(state.child_by_name("op")?).borrow() { + "function" => match state.slice(state.child_by_name("op")?).borrow() { "sum" | "avg" => { check_langlvls(state, LanguageLevel::SMT(vec![LanguageLevelSMT::Aggregate])); opt_aggregate(state) - }, + } "len" => { - check_langlvls(state, LanguageLevel::TYPE(vec![LanguageLevelTYPE::StringConstraints])); + check_langlvls( + state, + LanguageLevel::TYPE(vec![LanguageLevelTYPE::StringConstraints]), + ); if state.child_by_name("tail").is_some() { state.push_error(10, "tailing comma not allowed"); } @@ -702,16 +760,19 @@ fn opt_numeric(state: &mut VisitorState) -> Option { None } }) - }, + } "floor" | "ceil" => { - check_langlvls(state, LanguageLevel::TYPE(vec![LanguageLevelTYPE::NumericConstraints])); + check_langlvls( + state, + LanguageLevel::TYPE(vec![LanguageLevelTYPE::NumericConstraints]), + ); opt_integer(state) - }, + } _ => { state.push_error(30, "unknown function"); None } - }}, + }, _ => { state.push_error(40, "found a constraint, expected a expression"); None @@ -799,7 +860,7 @@ fn opt_constraint(state: &mut VisitorState) -> Option { } .map(|content| ConstraintDecl { span, content }) } -fn visit_constraint(state: &mut VisitorState, parent: Symbol) { +fn visit_constraint(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { if let Some(cons) = opt_constraint(state) { state.add_constraint(cons, parent); } @@ -852,7 +913,7 @@ fn opt_value(state: &mut VisitorState) -> Value { } } -fn visit_attribute_value(state: &mut VisitorState, parent: Symbol) { +fn visit_attribute_value(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { state.goto_field("name"); let name = opt_name(state).unwrap(); let sym = Symbol::Attribute(state.ast.attributes.len()); @@ -869,36 +930,36 @@ fn visit_attribute_value(state: &mut VisitorState, parent: Symbol) { depth: 0, }); if has_children { - visit_children_arg(state, sym, visit_attributes); + visit_children_arg(state, sym, cardinality, visit_attributes); } } -fn visit_constraint_list(state: &mut VisitorState, parent: Symbol) { +fn visit_constraint_list(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { loop { if state.kind() == "constraint" { - visit_children_arg(state, parent, visit_constraint); + visit_children_arg(state, parent, cardinality, visit_constraint); } if !state.goto_next_sibling() { break; } } } -fn visit_attributes(state: &mut VisitorState, parent: Symbol) { +fn visit_attributes(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { loop { match state.kind() { "attribute_constraints" => { if state.child_by_name("tail").is_some() { state.push_error(10, "tailing comma unsupported"); } - visit_children_arg(state, parent, visit_constraint_list); + visit_children_arg(state, parent, cardinality, visit_constraint_list); } "attribute_constraint" => { visit_children(state, |state| { debug_assert!(state.goto_kind("constraint")); - visit_children_arg(state, parent, visit_constraint); + visit_children_arg(state, parent, cardinality, visit_constraint); }); } "attribute_value" => { - visit_children_arg(state, parent, visit_attribute_value); + visit_children_arg(state, parent, cardinality, visit_attribute_value); } _ => {} } @@ -908,44 +969,50 @@ fn visit_attributes(state: &mut VisitorState, parent: Symbol) { } } -fn visit_cardinality(state: &mut VisitorState, parent: Symbol, ty: Type, feature: Feature){ - let cardinality = feature.cardinality.unwrap(); - match cardinality { - Cardinality::Any => info!("FUUUUUUUCK Cardinality Any detected!!!!!!!!!"), - Cardinality::Range(a, b) => { - info!(" cardinality"); - for i in 0 .. b { - let sym = Symbol::Feature(state.ast.features.len()); - let new_name = SymbolSpan { - name: Ustr::from(format!("{}[{}]", feature.name.name, i).as_str()), - span: feature.name.span.clone() - }; - let new_feature = Feature { - name: new_name, - ty: feature.ty.clone(), - cardinality: Some(Cardinality::Any), - }; - state.ast.features.push(new_feature); - state.push_child(parent, sym); - loop { - match state.kind() { - "attributes" => { - visit_children_arg(state, sym, visit_attributes); - } - "blk" => { - visit_children_arg(state, sym, visit_blk_decl); - } - _ => {} - } - if !state.goto_next_sibling() { - break; - } - } - } - } - } -} -fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, ty: Type) { +// fn visit_cardinality(state: &mut VisitorState, parent: Symbol, ty: Type, feature: Feature) { +// let cardinality = feature.cardinality.unwrap(); +// match cardinality { +// Cardinality::Fixed => info!("FUUUUUUUCK Cardinality Any detected!!!!!!!!!"), +// Cardinality::Range(a, b) => { +// info!(" cardinality"); +// for i in 0..b { +// let sym = Symbol::Feature(state.ast.features.len()); +// let new_name = SymbolSpan { +// name: Ustr::from(format!("{}[{}]", feature.name.name, i).as_str()), +// span: feature.name.span.clone(), +// }; +// let new_feature = Feature { +// name: new_name, +// ty: feature.ty.clone(), +// cardinality: Some(Cardinality::Fixed), +// }; +// state.ast.features.push(new_feature); +// state.push_child(parent, sym); +// loop { +// match state.kind() { +// "attributes" => { +// visit_children_arg(state, sym, visit_attributes); +// } +// "blk" => { +// visit_children_arg(state, sym, visit_blk_decl); +// } +// _ => {} +// } +// if !state.goto_next_sibling() { +// break; +// } +// } +// } +// } +// } +// } +fn visit_feature( + state: &mut VisitorState, + parent: Symbol, + name: SymbolSpan, + ty: Type, + cardinality: &Cardinality, +) { info!("visit feature"); match parent { Symbol::Feature(..) => { @@ -962,39 +1029,55 @@ fn visit_feature(state: &mut VisitorState, parent: Symbol, name: SymbolSpan, ty: .unwrap() .child_by_field_name("cardinality") .and_then(|n| { - check_langlvls(state, LanguageLevel::SMT(vec![LanguageLevelSMT::FeatureCardinality])); - opt_cardinality(n, state) - }), + check_langlvls( + state, + LanguageLevel::SMT(vec![LanguageLevelSMT::FeatureCardinality]), + ); + let feature_cardinality = opt_cardinality(n, state).unwrap(); + match cardinality { + Cardinality::Fixed => Some(feature_cardinality), + Cardinality::Range(min, max) => { + if let Cardinality::Range(new_min, new_max) = feature_cardinality { + Some(Cardinality::Range(new_min * min, new_max * max)) + }else{ + Some(cardinality.clone()) + } + } + } + }) + .or_else(|| Some(cardinality.clone())), }; - match feature.cardinality.clone() { - Some(cardinality) => { - visit_cardinality(state, parent, ty, feature); - - } - None =>{ - info!("no cardinality"); - let sym = Symbol::Feature(state.ast.features.len()); - state.ast.features.push(feature); + + let sym = Symbol::Feature(state.ast.features.len()); + match feature.clone().cardinality.unwrap() { + Cardinality::Fixed => { + state.ast.features.push(feature.clone()); state.push_child(parent, sym); - loop { - match state.kind() { - "attributes" => { - visit_children_arg(state, sym, visit_attributes); - } - "blk" => { - visit_children_arg(state, sym, visit_blk_decl); - } - _ => {} - } - if !state.goto_next_sibling() { - break; - } - } + } + Cardinality::Range(min, max) => { + for i in 0 .. max { + state.ast.features.push(feature.clone()); + state.push_child(parent, Symbol::Feature(state.ast.features.len() -1)); + // TODO parent remapping + } } } - + loop { + match state.kind() { + "attributes" => { + visit_children_arg(state, sym, &feature.clone().cardinality.clone().unwrap(), visit_attributes); + } + "blk" => { + visit_children_arg(state, sym,&feature.clone().cardinality.clone().unwrap(), visit_blk_decl); + } + _ => {} + } + if !state.goto_next_sibling() { + break; + } + } } fn visit_ref(state: &mut VisitorState, parent: Symbol, path: Path) { @@ -1012,7 +1095,7 @@ fn visit_ref(state: &mut VisitorState, parent: Symbol, path: Path) { } } } -fn visit_group(state: &mut VisitorState, parent: Symbol, mode: GroupMode) { +fn visit_group(state: &mut VisitorState, parent: Symbol, mode: GroupMode,cardinality: &Cardinality) { match parent { Symbol::Group(..) => { state.push_error(40, "groups have to be separated by features"); @@ -1031,19 +1114,19 @@ fn visit_group(state: &mut VisitorState, parent: Symbol, mode: GroupMode) { loop { check_no_extra_blk(state, "group"); if state.kind() == "blk" { - visit_children_arg(state, sym, visit_blk_decl); + visit_children_arg(state, sym, cardinality,visit_blk_decl); } if !state.goto_next_sibling() { break; } } } -fn visit_blk_decl(state: &mut VisitorState, parent: Symbol) { +fn visit_blk_decl(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { state.goto_field("header"); match state.kind() { "name" => { let name = opt_name(state).unwrap(); - visit_feature(state, parent, name, Type::Bool); + visit_feature(state, parent, name, Type::Bool, cardinality); } "typed_feature" => { check_langlvls(state, LanguageLevel::TYPE(vec![])); @@ -1062,7 +1145,7 @@ fn visit_blk_decl(state: &mut VisitorState, parent: Symbol) { Some((opt_name(state).unwrap(), ty)) }) .unwrap(); - visit_feature(state, parent, name, ty); + visit_feature(state, parent, name, ty, cardinality); } "ref" => { let path = visit_children(state, |state| { @@ -1084,12 +1167,15 @@ fn visit_blk_decl(state: &mut VisitorState, parent: Symbol) { "alternative" => GroupMode::Alternative, _ => GroupMode::Mandatory, }; - visit_group(state, parent, mode); + visit_group(state, parent, mode,cardinality); } "cardinality" => { - check_langlvls(state, LanguageLevel::SAT(vec![LanguageLevelSAT::GroupCardinality])); - let card = opt_cardinality(state.node(), state).unwrap_or(Cardinality::Any); - visit_group(state, parent, GroupMode::Cardinality(card)); + check_langlvls( + state, + LanguageLevel::SAT(vec![LanguageLevelSAT::GroupCardinality]), + ); + let card = opt_cardinality(state.node(), state).unwrap_or(Cardinality::Fixed); + visit_group(state, parent, GroupMode::Cardinality(card),cardinality); } _ => { state.push_error(40, "expected a feature or group declaration"); @@ -1097,15 +1183,15 @@ fn visit_blk_decl(state: &mut VisitorState, parent: Symbol) { } } fn visit_features(state: &mut VisitorState) { - let keyword = Keyword { - name: state.name(state.node()), - span: state.node().byte_range() - }; + let keyword = Keyword { + name: state.name(state.node()), + span: state.node().byte_range(), + }; state.ast.keywords.push(keyword); loop { check_no_extra_blk(state, "features"); if state.kind() == "blk" { - visit_children_arg(state, Symbol::Root, visit_blk_decl); + visit_children_arg(state, Symbol::Root, &Cardinality::Fixed,visit_blk_decl); } if !state.goto_next_sibling() { break; @@ -1116,8 +1202,8 @@ fn visit_constraint_decl(state: &mut VisitorState) { loop { check_simple_blk(state, "constraints"); match state.kind() { - "constraint" | "ref" => visit_children_arg(state, Symbol::Root, visit_constraint), - "name" => visit_constraint(state, Symbol::Root), + "constraint" | "ref" => visit_children_arg(state, Symbol::Root, &Cardinality::Fixed,visit_constraint), + "name" => visit_constraint(state, Symbol::Root,&Cardinality::Fixed), _ => {} } if state.kind() == "ref" { diff --git a/uvls/src/core/ast/visitor.rs b/uvls/src/core/ast/visitor.rs index 7e6675ed..739080ac 100644 --- a/uvls/src/core/ast/visitor.rs +++ b/uvls/src/core/ast/visitor.rs @@ -136,14 +136,14 @@ where } } -pub fn visit_children_arg<'a, A, F, T, V>(state: &mut V, arg: A, mut f: F) -> T +pub fn visit_children_arg<'a, A, F, T, V>(state: &mut V, arg: A, cardinality: & Cardinality, mut f: F) -> T where V: Visitor<'a>, - F: FnMut(&mut V, A) -> T, + F: FnMut(&mut V, A,&Cardinality) -> T, T: Default, { if state.goto_first_child() { - let out = stacker::maybe_grow(32 * 1024, 1024 * 1024, || f(state, arg)); + let out = stacker::maybe_grow(32 * 1024, 1024 * 1024, || f(state, arg, cardinality)); state.goto_parent(); out } else { diff --git a/uvls/src/smt/smt_lib.rs b/uvls/src/smt/smt_lib.rs index 65731f37..3498879f 100644 --- a/uvls/src/smt/smt_lib.rs +++ b/uvls/src/smt/smt_lib.rs @@ -429,6 +429,7 @@ impl Into for ConfigValue { } } +//TODO check cardinality pub fn uvl2smt(module: &Module, config: &HashMap) -> SMTModule { assert!(module.ok); let mut builder = SMTBuilder { @@ -436,6 +437,7 @@ pub fn uvl2smt(module: &Module, config: &HashMap) -> sym2var: IndexSet::new(), assert: Vec::new(), }; + let mut counter = 0; //encode features for (m, file) in module.instances() { for f in file.all_features() { @@ -527,7 +529,7 @@ pub fn uvl2smt(module: &Module, config: &HashMap) -> )) } } - GroupMode::Optional | GroupMode::Cardinality(Cardinality::Any) => {} + GroupMode::Optional | GroupMode::Cardinality(Cardinality::Fixed) => {} GroupMode::Cardinality(Cardinality::Range(min, max)) => { builder.min_assert(min, &p_bind, m.sym(g)); builder.max_assert(max, &p_bind, m.sym(g)); From 3c7b5f09089af28f212e48e4a206a33bd11368ef Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 14 Jun 2023 10:30:36 +0200 Subject: [PATCH 05/17] update feature cardinality in transform and z3 --- uvls/src/core/ast.rs | 9 ++ uvls/src/core/ast/def.rs | 2 + uvls/src/core/ast/transform.rs | 192 ++++++++++++++++++--------------- uvls/src/core/ast/visitor.rs | 6 +- uvls/src/smt/smt_lib.rs | 31 +++++- 5 files changed, 149 insertions(+), 91 deletions(-) diff --git a/uvls/src/core/ast.rs b/uvls/src/core/ast.rs index eb797416..c50d53fa 100644 --- a/uvls/src/core/ast.rs +++ b/uvls/src/core/ast.rs @@ -175,6 +175,12 @@ impl Ast { fn all_features(&self) -> impl Iterator { (0..self.features.len()).map(Symbol::Feature) } + fn get_feature(&self, index: usize) -> Option<&Feature>{ + self.features.get(index) + } + fn get_attribute(&self, index: usize) -> Option<&Attribute>{ + self.attributes.get(index) + } fn all_attributes(&self) -> impl Iterator { (0..self.attributes.len()).map(Symbol::Attribute) } @@ -241,6 +247,9 @@ impl AstDocument { pub fn all_features(&self) -> impl Iterator { self.ast.all_features() } + pub fn get_feature(&self,index: usize) -> Option<&Feature>{ + self.ast.get_feature(index) + } pub fn all_attributes(&self) -> impl Iterator { self.ast.all_attributes() } diff --git a/uvls/src/core/ast/def.rs b/uvls/src/core/ast/def.rs index 93a107d0..572e727f 100644 --- a/uvls/src/core/ast/def.rs +++ b/uvls/src/core/ast/def.rs @@ -111,6 +111,7 @@ pub struct Feature { pub name: SymbolSpan, pub cardinality: Option, pub ty: Type, + pub duplicate: bool, } #[derive(Clone, Debug)] pub struct Import { @@ -135,6 +136,7 @@ pub struct Attribute { pub name: SymbolSpan, pub value: ValueDecl, pub depth: u32, + pub duplicate: bool, } #[derive(Clone, Debug)] pub struct Keyword { diff --git a/uvls/src/core/ast/transform.rs b/uvls/src/core/ast/transform.rs index a1b4a2e6..e9ac41a4 100644 --- a/uvls/src/core/ast/transform.rs +++ b/uvls/src/core/ast/transform.rs @@ -3,8 +3,6 @@ use ast::visitor::Visitor; use ast::visitor::*; use ast::Ast; use check::ErrorInfo; -use dioxus::html::b; -use futures_util::future::OrElse; use log::info; use parse::*; use ropey::Rope; @@ -13,7 +11,6 @@ use std::borrow::{Borrow, Cow}; use tokio::time::Instant; use tower_lsp::lsp_types::{DiagnosticSeverity, Url}; use tree_sitter::{Node, Tree, TreeCursor}; -use ustr::Ustr; use util::node_range; //Transform a tree-sitter tree into the Ast ECS via recursive decent //While parsing we keep a mutable state to store entities and errors @@ -101,46 +98,50 @@ impl<'a> VisitorState<'a> { while let Some((node, scope, depth)) = stack.pop() { let new_scope = if let Some(name) = self.ast.name(node) { match node { - Symbol::Feature(..) => { - if let Some(old) = self - .ast - .index - .insert((Symbol::Root, name, SymbolKind::Feature), node) - { - self.errors.push(ErrorInfo { - location: self.ast.lsp_range(node, self.source).unwrap(), - severity: DiagnosticSeverity::ERROR, - weight: 20, - msg: "duplicate feature".to_string(), - }); - self.errors.push(ErrorInfo { - location: self.ast.lsp_range(old, self.source).unwrap(), - severity: DiagnosticSeverity::ERROR, - weight: 20, - msg: "duplicate feature".to_string(), - }) + Symbol::Feature(i) => { + if !self.ast.get_feature(i).unwrap().duplicate { + if let Some(old) = self + .ast + .index + .insert((Symbol::Root, name, SymbolKind::Feature), node) + { + self.errors.push(ErrorInfo { + location: self.ast.lsp_range(node, self.source).unwrap(), + severity: DiagnosticSeverity::ERROR, + weight: 20, + msg: "duplicate feature".to_string(), + }); + self.errors.push(ErrorInfo { + location: self.ast.lsp_range(old, self.source).unwrap(), + severity: DiagnosticSeverity::ERROR, + weight: 20, + msg: "duplicate feature".to_string(), + }) + } } node } Symbol::Attribute(i) => { - if let Some(old) = self - .ast - .index - .insert((scope, name, SymbolKind::Attribute), node) - { - self.errors.push(ErrorInfo { - location: self.ast.lsp_range(node, self.source).unwrap(), - severity: DiagnosticSeverity::ERROR, - weight: 20, - msg: "duplicate attribute".to_string(), - }); - self.errors.push(ErrorInfo { - location: self.ast.lsp_range(old, self.source).unwrap(), - severity: DiagnosticSeverity::ERROR, - weight: 20, - msg: "duplicate attribute".to_string(), - }); - }; + if !self.ast.get_attribute(i).unwrap().duplicate { + if let Some(old) = self + .ast + .index + .insert((scope, name, SymbolKind::Attribute), node) + { + self.errors.push(ErrorInfo { + location: self.ast.lsp_range(node, self.source).unwrap(), + severity: DiagnosticSeverity::ERROR, + weight: 20, + msg: "duplicate attribute".to_string(), + }); + self.errors.push(ErrorInfo { + location: self.ast.lsp_range(old, self.source).unwrap(), + severity: DiagnosticSeverity::ERROR, + weight: 20, + msg: "duplicate attribute".to_string(), + }); + }; + } self.ast.attributes[i].depth = depth; node } @@ -500,7 +501,7 @@ fn opt_cardinality(node: Node, state: &mut VisitorState) -> Option opt_int(end.unwrap(), state)?, )), (None, Some("int")) => Some(Cardinality::Range(0, opt_int(end.unwrap(), state)?)), - (_, _) => Some(Cardinality::Range(0, 0)), + (_, _) => Some(Cardinality::Range(0, 1)), } } @@ -860,7 +861,7 @@ fn opt_constraint(state: &mut VisitorState) -> Option { } .map(|content| ConstraintDecl { span, content }) } -fn visit_constraint(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { +fn visit_constraint(state: &mut VisitorState, parent: Symbol, _duplicate: &bool) { if let Some(cons) = opt_constraint(state) { state.add_constraint(cons, parent); } @@ -913,7 +914,7 @@ fn opt_value(state: &mut VisitorState) -> Value { } } -fn visit_attribute_value(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { +fn visit_attribute_value(state: &mut VisitorState, parent: Symbol, duplicate: &bool) { state.goto_field("name"); let name = opt_name(state).unwrap(); let sym = Symbol::Attribute(state.ast.attributes.len()); @@ -928,38 +929,39 @@ fn visit_attribute_value(state: &mut VisitorState, parent: Symbol, cardinality: span: state.node().byte_range(), }, depth: 0, + duplicate: duplicate.clone(), }); if has_children { - visit_children_arg(state, sym, cardinality, visit_attributes); + visit_children_arg(state, sym, &duplicate, visit_attributes); } } -fn visit_constraint_list(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { +fn visit_constraint_list(state: &mut VisitorState, parent: Symbol, duplicate: &bool) { loop { if state.kind() == "constraint" { - visit_children_arg(state, parent, cardinality, visit_constraint); + visit_children_arg(state, parent, duplicate, visit_constraint); } if !state.goto_next_sibling() { break; } } } -fn visit_attributes(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { +fn visit_attributes(state: &mut VisitorState, parent: Symbol, duplicate: &bool) { loop { match state.kind() { "attribute_constraints" => { if state.child_by_name("tail").is_some() { state.push_error(10, "tailing comma unsupported"); } - visit_children_arg(state, parent, cardinality, visit_constraint_list); + visit_children_arg(state, parent, duplicate, visit_constraint_list); } "attribute_constraint" => { visit_children(state, |state| { debug_assert!(state.goto_kind("constraint")); - visit_children_arg(state, parent, cardinality, visit_constraint); + visit_children_arg(state, parent, duplicate, visit_constraint); }); } "attribute_value" => { - visit_children_arg(state, parent, cardinality, visit_attribute_value); + visit_children_arg(state, parent, duplicate, visit_attribute_value); } _ => {} } @@ -1011,7 +1013,7 @@ fn visit_feature( parent: Symbol, name: SymbolSpan, ty: Type, - cardinality: &Cardinality, + duplicate: bool, ) { info!("visit feature"); match parent { @@ -1033,46 +1035,58 @@ fn visit_feature( state, LanguageLevel::SMT(vec![LanguageLevelSMT::FeatureCardinality]), ); - let feature_cardinality = opt_cardinality(n, state).unwrap(); - match cardinality { - Cardinality::Fixed => Some(feature_cardinality), - Cardinality::Range(min, max) => { - if let Cardinality::Range(new_min, new_max) = feature_cardinality { - Some(Cardinality::Range(new_min * min, new_max * max)) - }else{ - Some(cardinality.clone()) - } - } - } + opt_cardinality(n, state) }) - .or_else(|| Some(cardinality.clone())), + .or_else(|| Some(Cardinality::Fixed)), + duplicate: duplicate.clone(), }; - - let sym = Symbol::Feature(state.ast.features.len()); + let mut sym = vec![]; + match feature.clone().cardinality.unwrap() { Cardinality::Fixed => { + sym.push(Symbol::Feature(state.ast.features.len())); state.ast.features.push(feature.clone()); - state.push_child(parent, sym); - } - Cardinality::Range(min, max) => { - for i in 0 .. max { - state.ast.features.push(feature.clone()); - state.push_child(parent, Symbol::Feature(state.ast.features.len() -1)); + state.push_child(parent, sym.get(0).unwrap().clone()); + } + Cardinality::Range(_, max) => { + for i in 0..max { + let mut dup_feature = feature.clone(); + sym.push(Symbol::Feature(state.ast.features.len())); + if i != 0 { + dup_feature.duplicate = true; + } + state.ast.features.push(dup_feature); + state.push_child(parent, sym.get(i).unwrap().clone()); // TODO parent remapping } } } - loop { - match state.kind() { - "attributes" => { - visit_children_arg(state, sym, &feature.clone().cardinality.clone().unwrap(), visit_attributes); + for index in 0..sym.len() { + let mut duplicate_par = false; + if let Symbol::Feature(id) = sym.get(index).unwrap() { + duplicate_par = state.ast.get_feature(*id).unwrap().duplicate; } - "blk" => { - visit_children_arg(state, sym,&feature.clone().cardinality.clone().unwrap(), visit_blk_decl); + match state.kind() { + "attributes" => { + visit_children_arg( + state, + sym.get(index).unwrap().clone(), + &duplicate_par, + visit_attributes, + ); + } + "blk" => { + visit_children_arg( + state, + sym.get(index).unwrap().clone(), + &&duplicate_par, + visit_blk_decl, + ); + } + _ => {} } - _ => {} } if !state.goto_next_sibling() { break; @@ -1095,7 +1109,7 @@ fn visit_ref(state: &mut VisitorState, parent: Symbol, path: Path) { } } } -fn visit_group(state: &mut VisitorState, parent: Symbol, mode: GroupMode,cardinality: &Cardinality) { +fn visit_group(state: &mut VisitorState, parent: Symbol, mode: GroupMode, duplicate: &bool) { match parent { Symbol::Group(..) => { state.push_error(40, "groups have to be separated by features"); @@ -1114,19 +1128,19 @@ fn visit_group(state: &mut VisitorState, parent: Symbol, mode: GroupMode,cardina loop { check_no_extra_blk(state, "group"); if state.kind() == "blk" { - visit_children_arg(state, sym, cardinality,visit_blk_decl); + visit_children_arg(state, sym, duplicate, visit_blk_decl); } if !state.goto_next_sibling() { break; } } } -fn visit_blk_decl(state: &mut VisitorState, parent: Symbol, cardinality: &Cardinality) { +fn visit_blk_decl(state: &mut VisitorState, parent: Symbol, duplicate: &bool) { state.goto_field("header"); match state.kind() { "name" => { let name = opt_name(state).unwrap(); - visit_feature(state, parent, name, Type::Bool, cardinality); + visit_feature(state, parent, name, Type::Bool, *duplicate); } "typed_feature" => { check_langlvls(state, LanguageLevel::TYPE(vec![])); @@ -1145,7 +1159,7 @@ fn visit_blk_decl(state: &mut VisitorState, parent: Symbol, cardinality: &Cardin Some((opt_name(state).unwrap(), ty)) }) .unwrap(); - visit_feature(state, parent, name, ty, cardinality); + visit_feature(state, parent, name, ty, *duplicate); } "ref" => { let path = visit_children(state, |state| { @@ -1167,7 +1181,7 @@ fn visit_blk_decl(state: &mut VisitorState, parent: Symbol, cardinality: &Cardin "alternative" => GroupMode::Alternative, _ => GroupMode::Mandatory, }; - visit_group(state, parent, mode,cardinality); + visit_group(state, parent, mode, duplicate); } "cardinality" => { check_langlvls( @@ -1175,7 +1189,7 @@ fn visit_blk_decl(state: &mut VisitorState, parent: Symbol, cardinality: &Cardin LanguageLevel::SAT(vec![LanguageLevelSAT::GroupCardinality]), ); let card = opt_cardinality(state.node(), state).unwrap_or(Cardinality::Fixed); - visit_group(state, parent, GroupMode::Cardinality(card),cardinality); + visit_group(state, parent, GroupMode::Cardinality(card), duplicate); } _ => { state.push_error(40, "expected a feature or group declaration"); @@ -1191,7 +1205,7 @@ fn visit_features(state: &mut VisitorState) { loop { check_no_extra_blk(state, "features"); if state.kind() == "blk" { - visit_children_arg(state, Symbol::Root, &Cardinality::Fixed,visit_blk_decl); + visit_children_arg(state, Symbol::Root, &false, visit_blk_decl); } if !state.goto_next_sibling() { break; @@ -1202,8 +1216,10 @@ fn visit_constraint_decl(state: &mut VisitorState) { loop { check_simple_blk(state, "constraints"); match state.kind() { - "constraint" | "ref" => visit_children_arg(state, Symbol::Root, &Cardinality::Fixed,visit_constraint), - "name" => visit_constraint(state, Symbol::Root,&Cardinality::Fixed), + "constraint" | "ref" => { + visit_children_arg(state, Symbol::Root, &false, visit_constraint) + } + "name" => visit_constraint(state, Symbol::Root, &false), _ => {} } if state.kind() == "ref" { @@ -1308,6 +1324,8 @@ pub fn visit_root(source: Rope, tree: Tree, uri: Url, timestamp: Instant) -> Ast source: &source, }; visit_children(&mut state, visit_top_lvl); + info!("{:?}", state.ast.structure); + info!("{:?}", state.ast.features); state.connect(); (state.ast, state.errors) }; diff --git a/uvls/src/core/ast/visitor.rs b/uvls/src/core/ast/visitor.rs index 739080ac..19473f76 100644 --- a/uvls/src/core/ast/visitor.rs +++ b/uvls/src/core/ast/visitor.rs @@ -136,14 +136,14 @@ where } } -pub fn visit_children_arg<'a, A, F, T, V>(state: &mut V, arg: A, cardinality: & Cardinality, mut f: F) -> T +pub fn visit_children_arg<'a, A, F, T, V>(state: &mut V, arg: A,duplicate: &bool, mut f: F) -> T where V: Visitor<'a>, - F: FnMut(&mut V, A,&Cardinality) -> T, + F: FnMut(&mut V, A,&bool) -> T, T: Default, { if state.goto_first_child() { - let out = stacker::maybe_grow(32 * 1024, 1024 * 1024, || f(state, arg, cardinality)); + let out = stacker::maybe_grow(32 * 1024, 1024 * 1024, || f(state, arg,duplicate)); state.goto_parent(); out } else { diff --git a/uvls/src/smt/smt_lib.rs b/uvls/src/smt/smt_lib.rs index 3498879f..4e5f0bf4 100644 --- a/uvls/src/smt/smt_lib.rs +++ b/uvls/src/smt/smt_lib.rs @@ -437,12 +437,40 @@ pub fn uvl2smt(module: &Module, config: &HashMap) -> sym2var: IndexSet::new(), assert: Vec::new(), }; - let mut counter = 0; //encode features for (m, file) in module.instances() { for f in file.all_features() { builder.push_var(m.sym(f)); } + + for sym_feature in file.all_features() { + if let Symbol::Feature(id) = sym_feature { + let feature = file.get_feature(id).unwrap().clone(); + if let Cardinality::Range(min,_) = feature.cardinality.unwrap_or_else(|| Cardinality::Fixed) { + // Make AtLeast assertion for cardinality feature + let mut list = vec![]; + let parent = file.parent(sym_feature, false).unwrap(); + + for child in file.direct_children(parent){ + if let Symbol::Feature(sibling_id) = child { + + let sibling = file.get_feature(sibling_id); + if sibling.unwrap().name.name.as_str() == feature.name.name.as_str() { + list.push(builder.var(m.sym(Symbol::Feature(sibling_id)))); + } + } + } + + builder.assert.push( + Assert(Some(AssertInfo(m.sym(sym_feature), AssertName::GroupMin)), + Expr::AtLeast(min , list) + )); + + } + } + } + + } //set config features for (&ms, val) in config @@ -454,6 +482,7 @@ pub fn uvl2smt(module: &Module, config: &HashMap) -> Some(AssertInfo(ms, AssertName::Config)), Expr::Equal(vec![var, val.clone().into()]), )); + } //encode attributes for (m, file) in module.instances() { From ea19b548c44e7e7332f8b3d29dbd246775acc583 Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 14 Jun 2023 11:48:45 +0200 Subject: [PATCH 06/17] fix remove duplicate err --- uvls/src/core/ast/graph.rs | 37 ++++++++++++++++++------------------- uvls/src/core/check.rs | 8 +++++--- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/uvls/src/core/ast/graph.rs b/uvls/src/core/ast/graph.rs index ab249b97..3957bad2 100644 --- a/uvls/src/core/ast/graph.rs +++ b/uvls/src/core/ast/graph.rs @@ -297,9 +297,8 @@ fn opt_cardinality(node: Node, state: &mut VisitorGraph) -> Option opt_int(begin, state)?, opt_int(end.unwrap(), state)?, )), - (Some(begin), Some("*")) => Some(Cardinality::From(opt_int(begin, state)?)), - (None, Some("int")) => Some(Cardinality::Max(opt_int(end.unwrap(), state)?)), - (_, _) => Some(Cardinality::Any), + (None, Some("int")) => Some(Cardinality::Range(0, opt_int(end.unwrap(), state)?)), + (_, _) => Some(Cardinality::Range(0, 1)), } } @@ -451,7 +450,7 @@ fn opt_equation(node: Node) -> Option { _ => None, } } -fn visit_constraint(graph: &mut VisitorGraph, _: GraphNode) { +fn visit_constraint(graph: &mut VisitorGraph, _: GraphNode,_ :&bool) { graph.add_constraint(graph.node().byte_range()); } fn opt_bool(graph: &mut VisitorGraph) -> bool { @@ -500,34 +499,34 @@ fn opt_value(graph: &mut VisitorGraph) -> Value { } } -fn visit_attribute_value(graph: &mut VisitorGraph, _: GraphNode) { +fn visit_attribute_value(graph: &mut VisitorGraph, _: GraphNode, _:&bool) { graph.goto_field("name"); let _ = opt_name(graph).unwrap(); } -fn visit_constraint_list(graph: &mut VisitorGraph, parent: GraphNode) { +fn visit_constraint_list(graph: &mut VisitorGraph, parent: GraphNode, _:&bool) { loop { if graph.kind() == "constraint" { - visit_children_arg(graph, parent.clone(), visit_constraint); + visit_children_arg(graph, parent.clone(), &false,visit_constraint); } if !graph.goto_next_sibling() { break; } } } -fn visit_attributes(graph: &mut VisitorGraph, parent: &GraphNode) { +fn visit_attributes(graph: &mut VisitorGraph, parent: &GraphNode,_:&bool) { loop { match graph.kind() { "attribute_constraints" => { - visit_children_arg(graph, parent.clone(), visit_constraint_list); + visit_children_arg(graph, parent.clone(),&false, visit_constraint_list); } "attribute_constraint" => { visit_children(graph, |state| { debug_assert!(state.goto_kind("constraint")); - visit_children_arg(state, parent.clone(), visit_constraint); + visit_children_arg(state, parent.clone(), &false, visit_constraint); }); } "attribute_value" => { - visit_children_arg(graph, parent.clone(), visit_attribute_value); + visit_children_arg(graph, parent.clone(),&false, visit_attribute_value); } _ => {} } @@ -557,10 +556,10 @@ fn visit_feature(graph: &mut VisitorGraph, parent: &mut GraphNode, name: SymbolS loop { match graph.cursor().node().kind() { "attributes" => { - visit_children_arg(graph, &feature, visit_attributes); + visit_children_arg(graph, &feature, &false,visit_attributes); } "blk" => { - visit_children_arg(graph, &mut feature, visit_blk_decl); + visit_children_arg(graph, &mut feature, &false,visit_blk_decl); } _ => {} } @@ -586,14 +585,14 @@ fn visit_group(graph: &mut VisitorGraph, mut parent: &mut GraphNode, mode: Group parent.group_mode = Some(mode); loop { if graph.kind() == "blk" { - visit_children_arg(graph, &mut *parent, visit_blk_decl); + visit_children_arg(graph, &mut *parent, &false, visit_blk_decl); } if !graph.goto_next_sibling() { break; } } } -fn visit_blk_decl(graph: &mut VisitorGraph, parent: &mut GraphNode) { +fn visit_blk_decl(graph: &mut VisitorGraph, parent: &mut GraphNode,_:&bool) { graph.goto_field("header"); match graph.kind() { "name" => { @@ -633,7 +632,7 @@ fn visit_blk_decl(graph: &mut VisitorGraph, parent: &mut GraphNode) { visit_group(graph, parent, mode); } "cardinality" => { - let card = opt_cardinality(graph.node(), graph).unwrap_or(Cardinality::Any); + let card = opt_cardinality(graph.node(), graph).unwrap_or(Cardinality::Fixed); visit_group(graph, parent, GroupMode::Cardinality(card)); } _ => { } @@ -643,7 +642,7 @@ fn visit_features(graph: &mut VisitorGraph) { let mut root: GraphNode = GraphNode::root(graph.root_name.clone()); loop { if graph.kind() == "blk" { - visit_children_arg(graph, &mut root, visit_blk_decl); + visit_children_arg(graph, &mut root,&false, visit_blk_decl); } if !graph.goto_next_sibling() { break; @@ -653,8 +652,8 @@ fn visit_features(graph: &mut VisitorGraph) { fn visit_constraint_decl(graph: &mut VisitorGraph) { loop { match graph.kind() { - "constraint" | "ref" => visit_children_arg(graph, GraphNode::root(None), visit_constraint), - "name" => visit_constraint(graph, GraphNode::root(None)), + "constraint" | "ref" => visit_children_arg(graph, GraphNode::root(None), &false,visit_constraint), + "name" => visit_constraint(graph, GraphNode::root(None),&false), _ => {} } if !graph.goto_next_sibling() { diff --git a/uvls/src/core/check.rs b/uvls/src/core/check.rs index 0dfdf62d..bebf9311 100644 --- a/uvls/src/core/check.rs +++ b/uvls/src/core/check.rs @@ -10,7 +10,7 @@ use tower_lsp::Client; use tree_sitter::{Node, QueryCursor, Tree}; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct ErrorInfo { pub location: Range, pub severity: DiagnosticSeverity, @@ -35,11 +35,13 @@ impl ErrorInfo { } } pub async fn publish(client: &Client, uri: &Url, err: &[ErrorInfo]) { - if let Some(max) = err.iter().max_by_key(|e| e.weight) { + let mut reduced_err = vec![]; + err.iter().for_each(|ele| if !reduced_err.contains(ele) {reduced_err.push(ele.clone())}); + if let Some(max) = reduced_err.clone().into_iter().max_by_key(|e| e.weight) { client .publish_diagnostics( uri.clone(), - err.iter() + reduced_err[..].iter() .rev() .filter(|e| e.weight == max.weight) .map(|i| i.clone().diagnostic()) From 597dea0c7574eabab1927984dc1039063b4702f9 Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 14 Jun 2023 18:01:18 +0200 Subject: [PATCH 07/17] fix atLeast for cardinality --- uvls/src/core/ast/def.rs | 1 + uvls/src/core/ast/transform.rs | 4 ++- uvls/src/smt.rs | 1 - uvls/src/smt/smt_lib.rs | 52 ++++++++++++++++------------------ 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/uvls/src/core/ast/def.rs b/uvls/src/core/ast/def.rs index 572e727f..39e7d738 100644 --- a/uvls/src/core/ast/def.rs +++ b/uvls/src/core/ast/def.rs @@ -112,6 +112,7 @@ pub struct Feature { pub cardinality: Option, pub ty: Type, pub duplicate: bool, + pub first_cardinality_child: bool, } #[derive(Clone, Debug)] pub struct Import { diff --git a/uvls/src/core/ast/transform.rs b/uvls/src/core/ast/transform.rs index e9ac41a4..e1f1d309 100644 --- a/uvls/src/core/ast/transform.rs +++ b/uvls/src/core/ast/transform.rs @@ -500,7 +500,7 @@ fn opt_cardinality(node: Node, state: &mut VisitorState) -> Option opt_int(begin, state)?, opt_int(end.unwrap(), state)?, )), - (None, Some("int")) => Some(Cardinality::Range(0, opt_int(end.unwrap(), state)?)), + (None, Some("int")) => Some(Cardinality::Range(opt_int(end.unwrap(), state)?, opt_int(end.unwrap(), state)?)), (_, _) => Some(Cardinality::Range(0, 1)), } } @@ -1039,6 +1039,7 @@ fn visit_feature( }) .or_else(|| Some(Cardinality::Fixed)), duplicate: duplicate.clone(), + first_cardinality_child: true, }; let mut sym = vec![]; @@ -1055,6 +1056,7 @@ fn visit_feature( sym.push(Symbol::Feature(state.ast.features.len())); if i != 0 { dup_feature.duplicate = true; + dup_feature.first_cardinality_child = false; } state.ast.features.push(dup_feature); state.push_child(parent, sym.get(i).unwrap().clone()); diff --git a/uvls/src/smt.rs b/uvls/src/smt.rs index 0ec3ce7d..e9e0ddfc 100644 --- a/uvls/src/smt.rs +++ b/uvls/src/smt.rs @@ -347,7 +347,6 @@ async fn check_base_sat( async move { let smt_module = uvl2smt(&module, &HashMap::new()); let source = smt_module.to_source(&module); - info!("da"); info!("{}",source); let model = create_model( &module, diff --git a/uvls/src/smt/smt_lib.rs b/uvls/src/smt/smt_lib.rs index 4e5f0bf4..b83f2d34 100644 --- a/uvls/src/smt/smt_lib.rs +++ b/uvls/src/smt/smt_lib.rs @@ -448,29 +448,28 @@ pub fn uvl2smt(module: &Module, config: &HashMap) -> let feature = file.get_feature(id).unwrap().clone(); if let Cardinality::Range(min,_) = feature.cardinality.unwrap_or_else(|| Cardinality::Fixed) { // Make AtLeast assertion for cardinality feature - let mut list = vec![]; - let parent = file.parent(sym_feature, false).unwrap(); - - for child in file.direct_children(parent){ - if let Symbol::Feature(sibling_id) = child { - - let sibling = file.get_feature(sibling_id); - if sibling.unwrap().name.name.as_str() == feature.name.name.as_str() { - list.push(builder.var(m.sym(Symbol::Feature(sibling_id)))); + if feature.first_cardinality_child { + let mut list = vec![]; + let parent = file.parent(sym_feature, false).unwrap(); + + for child in file.direct_children(parent) { + if let Symbol::Feature(sibling_id) = child { + let sibling = file.get_feature(sibling_id); + if sibling.unwrap().name.name.as_str() == feature.name.name.as_str() + { + list.push(builder.var(m.sym(Symbol::Feature(sibling_id)))); + } } } + + builder.assert.push(Assert( + Some(AssertInfo(m.sym(sym_feature), AssertName::GroupMin)), + Expr::AtLeast(min, list), + )); } - - builder.assert.push( - Assert(Some(AssertInfo(m.sym(sym_feature), AssertName::GroupMin)), - Expr::AtLeast(min , list) - )); - } } } - - } //set config features for (&ms, val) in config @@ -482,7 +481,6 @@ pub fn uvl2smt(module: &Module, config: &HashMap) -> Some(AssertInfo(ms, AssertName::Config)), Expr::Equal(vec![var, val.clone().into()]), )); - } //encode attributes for (m, file) in module.instances() { @@ -745,14 +743,12 @@ fn translate_expr(decl: &ast::ExprDecl, m: InstanceID, builder: &mut SMTBuilder) ) } } - ast::Expr::Integer { op, n} => { - ( - match op { - ast::IntegerOP::Ceil => Expr::Ceil(translate_expr(n, m, builder).0.into()), - ast::IntegerOP::Floor => Expr::Floor(translate_expr(n, m, builder).0.into()) - }, - Type::Real, - ) - } + ast::Expr::Integer { op, n } => ( + match op { + ast::IntegerOP::Ceil => Expr::Ceil(translate_expr(n, m, builder).0.into()), + ast::IntegerOP::Floor => Expr::Floor(translate_expr(n, m, builder).0.into()), + }, + Type::Real, + ), } -} \ No newline at end of file +} From 60e3f4c83d856dc8226494935c81ce833025962d Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 21 Jun 2023 17:14:37 +0200 Subject: [PATCH 08/17] feat: feature Cardinality for config json --- uvls/src/core/ast/def.rs | 1 + uvls/src/core/config.rs | 18 +++++- uvls/src/core/module.rs | 121 ++++++++++++++++++++++++++++++----- uvls/src/smt/smt_lib.rs | 1 + uvls/src/webview/frontend.rs | 5 ++ 5 files changed, 130 insertions(+), 16 deletions(-) diff --git a/uvls/src/core/ast/def.rs b/uvls/src/core/ast/def.rs index 39e7d738..b328590f 100644 --- a/uvls/src/core/ast/def.rs +++ b/uvls/src/core/ast/def.rs @@ -55,6 +55,7 @@ pub enum Type { Bool, Void, Namespace, + Object, } #[derive(Clone, Debug)] diff --git a/uvls/src/core/config.rs b/uvls/src/core/config.rs index 5b0ebc32..559a7d6b 100644 --- a/uvls/src/core/config.rs +++ b/uvls/src/core/config.rs @@ -42,10 +42,13 @@ pub enum ConfigValue { Bool(bool), Number(f64), String(String), + Cardinality(Vec>) + } impl ConfigValue { pub fn ty(&self) -> Type { match self { + Self::Cardinality(..) => Type::Object, Self::Bool(..) => Type::Bool, Self::Number(..) => Type::Real, Self::String(..) => Type::String, @@ -69,6 +72,7 @@ impl Display for ConfigValue { Self::Bool(x) => write!(f, "{x}"), Self::Number(x) => write!(f, "{x}"), Self::String(x) => write!(f, "{x}"), + Self::Cardinality(x) => write!(f, "testWrite"), } } } @@ -88,7 +92,10 @@ impl Serialize for ConfigEntry { match self { - ConfigEntry::Value(..) => panic!(), + ConfigEntry::Value(p,k) => { + info!("Here I dould normally panic"); + serializer.serialize_bool(true) + } ConfigEntry::Import(_, v) => { let mut s = serializer.serialize_map(Some(v.len()))?; for i in v.iter() { @@ -107,6 +114,15 @@ impl Serialize for ConfigEntry { } } +impl<'de> Deserialize<'de> for ConfigEntry { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de> + { + Ok(ConfigEntry::Value(Path { names: vec![], spans: vec![] }, ConfigValue::Bool(true))) + } +} + impl ConfigEntry { pub fn is_empty(&self) -> bool { match self { diff --git a/uvls/src/core/module.rs b/uvls/src/core/module.rs index 2a80f844..20045287 100644 --- a/uvls/src/core/module.rs +++ b/uvls/src/core/module.rs @@ -270,21 +270,24 @@ impl ConfigModule { entries.push(entry); } } - file.visit_named_children(Symbol::Root, false, |sym, prefix| match sym { - Symbol::Feature(_) | Symbol::Attribute(_) => { - if let Some(config) = self.values.get(&i.sym(sym)) { - entries.push(ConfigEntry::Value( - Path { - names: prefix.to_vec(), - spans: Vec::new(), - }, - config.clone(), - )) - } - true - } - _ => false, - }); + + entries.append(&mut self.serialize_rec_file(Symbol::Root, file, i)); + // file.visit_named_children(Symbol::Root, false, |sym, prefix| match sym { + // Symbol::Feature(_) | Symbol::Attribute(_) => { + // if let Some(config) = self.values.get(&i.sym(sym)) { + // entries.push(ConfigEntry::Value( + // Path { + // names: prefix.to_vec(), + // spans: Vec::new(), + // }, + // config.clone(), + // )) + // } + // true + // } + // _ => false, + // }); + ConfigEntry::Import( Path { names: path.to_vec(), @@ -293,6 +296,94 @@ impl ConfigModule { entries, ) } + + fn serialize_rec_file(&self, sym: Symbol, file: &AstDocument,i: InstanceID) -> Vec{ + let mut entries: Vec = Vec::new(); + let mut child_map: HashMap>>= hashbrown::HashMap::new(); + + for child in file.direct_children(sym){ + info!("VISIT: {:?}", file.name(child).unwrap_or(Ustr::from("Error"))); + info!("CHILD: {:?}", child); + match child { + Symbol::Feature(id) => { + let feature = file.get_feature(id).unwrap(); + match feature.cardinality { + Some(Cardinality::Fixed) => { + if let Some(config) = self.values.get(&i.sym(child)) { + entries.push(ConfigEntry::Value( + Path { + names: vec![file.name(child).unwrap()], + spans: Vec::new(), + }, + config.clone(), + )) + } + entries.append(& mut self.serialize_rec_file(child, file,i)); + } + Some(Cardinality::Range(_, _)) =>{ + let mut child_entries:Vec = vec![]; + if let Some(config) = self.values.get(&i.sym(child)) { + child_entries.push(ConfigEntry::Value( + Path { + names: vec![file.name(child).unwrap()], + spans: Vec::new(), + }, + config.clone(), + )); + child_entries.append(&mut self.serialize_rec_file(child, file, i)); + } + child_map.get_mut(&file.name(child).unwrap()).and_then(|x| { + x.push(child_entries.clone()); + Some(()) + } + ).or_else(|| { + child_map.insert(file.name(child).unwrap(), vec![child_entries]); + Some(()) + }); + // entries.push(ConfigEntry::Value( + // Path { + // names: vec![file.name(child).unwrap()], + // spans: Vec::new(), + // }, + // ConfigValue::Cardinality(child_entries) + // )); + } + None => () + } + + } + Symbol::Attribute(_) =>{ + if let Some(config) = self.values.get(&i.sym(child)) { + entries.push(ConfigEntry::Value( + Path { + names: vec![file.name(child).unwrap()], + spans: Vec::new(), + }, + config.clone(), + )) + } + entries.append(& mut self.serialize_rec_file(child, file,i)); + + } + _ => { + entries.append(& mut self.serialize_rec_file(child, file, i)); + }, + } + + } + for (cardinality_name, cardinality_childs) in child_map.iter() { + entries.push(ConfigEntry::Value( + Path { + names: vec![cardinality_name.clone()], + spans: Vec::new(), + }, + ConfigValue::Cardinality(cardinality_childs.clone()) + )) + } + info!("entries: {:?}",entries); + return entries; + } + //Turns a the set of linear configuration values of this module into theire recusive from //used in json pub fn serialize(&self) -> Vec { diff --git a/uvls/src/smt/smt_lib.rs b/uvls/src/smt/smt_lib.rs index b83f2d34..f2c4e2ba 100644 --- a/uvls/src/smt/smt_lib.rs +++ b/uvls/src/smt/smt_lib.rs @@ -425,6 +425,7 @@ impl Into for ConfigValue { Self::Bool(b) => Expr::Bool(b), Self::Number(n) => Expr::Real(n), Self::String(s) => Expr::String(s), + _ => unimplemented!() } } } diff --git a/uvls/src/webview/frontend.rs b/uvls/src/webview/frontend.rs index db0aa038..04ff5481 100644 --- a/uvls/src/webview/frontend.rs +++ b/uvls/src/webview/frontend.rs @@ -195,6 +195,11 @@ fn ConfigInput<'a>(cx: Scope<'a, ConfigInputProps<'a>>) -> Element { } } }, + _ => rsx!{ div { + "something" + } + + }, }; cx.render(rsx! { div{ From 2dde1d26b13029f9cc99b1c364571971b37e4f5b Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Tue, 27 Jun 2023 09:31:24 +0200 Subject: [PATCH 09/17] update Seralization config to uvl.json --- uvls/src/core/config.rs | 45 ++++++++++++-- uvls/src/core/module.rs | 110 ++++++++++++++++++++++------------- uvls/src/webview/frontend.rs | 2 +- 3 files changed, 111 insertions(+), 46 deletions(-) diff --git a/uvls/src/core/config.rs b/uvls/src/core/config.rs index 559a7d6b..30cf5488 100644 --- a/uvls/src/core/config.rs +++ b/uvls/src/core/config.rs @@ -1,4 +1,4 @@ -use std::fmt::Display; +use std::{fmt::Display, path}; use crate::core::*; use ast::*; @@ -35,6 +35,11 @@ use ustr::Ustr; //JSON parsing is done with tree-sitter and not serde because there currently is no solid serde json //crate for span information and partial parsing so error reporting becomes impossible. +#[derive(Debug, Clone, PartialEq, Deserialize)] +pub enum CardinalityEntry { + CardinalityLvl(Vec>), + EntitiyLvl(Vec), +} #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(untagged)] @@ -42,9 +47,31 @@ pub enum ConfigValue { Bool(bool), Number(f64), String(String), - Cardinality(Vec>) + Cardinality(CardinalityEntry) +} + +impl Serialize for CardinalityEntry { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer { + use serde::ser::SerializeSeq; + match self { + CardinalityEntry::CardinalityLvl(childs) => { + let mut s = serializer.serialize_seq(Some(childs.len()))?; + for child in childs { + s.serialize_element(&CardinalityEntry::EntitiyLvl(child.to_owned())); + } + s.end() + + } + CardinalityEntry::EntitiyLvl(childs) => { + ConfigEntry::Import(Path { names: vec![], spans: vec![] }, childs.to_owned()).serialize(serializer) + } + } + } } + impl ConfigValue { pub fn ty(&self) -> Type { match self { @@ -88,7 +115,7 @@ impl Serialize for ConfigEntry { where S: serde::Serializer, { - use serde::ser::SerializeMap; + use serde::ser::{SerializeMap,SerializeSeq, SerializeStruct}; match self { @@ -221,8 +248,18 @@ fn opt_configs(state: &mut State) -> Vec { }); acc.push(ConfigEntry::Import(key, children)); } + "array" =>{ + let children = stacker::maybe_grow(32 * 1024, 1024 * 1024, || { + visit_children(state, |state| { + state.goto_field("value"); + visit_children(state, opt_configs) + }) + }); + info!("{:?}",children); + acc.push(ConfigEntry::Value(key, ConfigValue::Cardinality(CardinalityEntry::CardinalityLvl(vec![children])))) + } _ => { - state.push_error_node(val, 30, "expected a number or bool"); + state.push_error_node(val, 30, format!("Explect Number or Bool {:?}", val.kind())); } } } diff --git a/uvls/src/core/module.rs b/uvls/src/core/module.rs index 20045287..48352ffc 100644 --- a/uvls/src/core/module.rs +++ b/uvls/src/core/module.rs @@ -1,10 +1,10 @@ -use tokio::time::Instant; use crate::core::*; -use resolve; use config::*; use hashbrown::HashMap; use indexmap::IndexSet; use log::info; +use resolve; +use tokio::time::Instant; use ustr::Ustr; use std::sync::Arc; @@ -195,14 +195,32 @@ impl Module { out.insert(ModuleSymbol { instance, sym }, val.clone()); out_span.insert(ModuleSymbol { instance, sym }, path.range()); } else { - err( - path.range(), - format!( - "expected {} got {}", - file.type_of(sym).unwrap(), - val.ty() - ), - ); + if let Symbol::Feature(i) = sym { + let feature = file.get_feature(i).unwrap().clone(); + if let Cardinality::Range(_, _) = feature.cardinality.unwrap() { + out.insert(ModuleSymbol { instance, sym }, val.clone()); + out_span + .insert(ModuleSymbol { instance, sym }, path.range()); + } else { + err( + path.range(), + format!( + "expected {} got {}", + file.type_of(sym).unwrap(), + val.ty() + ), + ); + } + } else { + err( + path.range(), + format!( + "expected {} got {}", + file.type_of(sym).unwrap(), + val.ty() + ), + ); + } } } else { err(path.range(), format!("unresolved value",)); @@ -287,7 +305,7 @@ impl ConfigModule { // } // _ => false, // }); - + ConfigEntry::Import( Path { names: path.to_vec(), @@ -297,17 +315,25 @@ impl ConfigModule { ) } - fn serialize_rec_file(&self, sym: Symbol, file: &AstDocument,i: InstanceID) -> Vec{ + fn serialize_rec_file( + &self, + sym: Symbol, + file: &AstDocument, + i: InstanceID, + ) -> Vec { let mut entries: Vec = Vec::new(); - let mut child_map: HashMap>>= hashbrown::HashMap::new(); + let mut child_map: HashMap>> = hashbrown::HashMap::new(); - for child in file.direct_children(sym){ - info!("VISIT: {:?}", file.name(child).unwrap_or(Ustr::from("Error"))); + for child in file.direct_children(sym) { + info!( + "VISIT: {:?}", + file.name(child).unwrap_or(Ustr::from("Error")) + ); info!("CHILD: {:?}", child); match child { Symbol::Feature(id) => { let feature = file.get_feature(id).unwrap(); - match feature.cardinality { + match feature.cardinality { Some(Cardinality::Fixed) => { if let Some(config) = self.values.get(&i.sym(child)) { entries.push(ConfigEntry::Value( @@ -318,10 +344,10 @@ impl ConfigModule { config.clone(), )) } - entries.append(& mut self.serialize_rec_file(child, file,i)); + entries.append(&mut self.serialize_rec_file(child, file, i)); } - Some(Cardinality::Range(_, _)) =>{ - let mut child_entries:Vec = vec![]; + Some(Cardinality::Range(_, _)) => { + let mut child_entries: Vec = vec![]; if let Some(config) = self.values.get(&i.sym(child)) { child_entries.push(ConfigEntry::Value( Path { @@ -332,27 +358,29 @@ impl ConfigModule { )); child_entries.append(&mut self.serialize_rec_file(child, file, i)); } - child_map.get_mut(&file.name(child).unwrap()).and_then(|x| { - x.push(child_entries.clone()); - Some(()) - } - ).or_else(|| { - child_map.insert(file.name(child).unwrap(), vec![child_entries]); - Some(()) - }); - // entries.push(ConfigEntry::Value( + child_map + .get_mut(&file.name(child).unwrap()) + .and_then(|x| { + x.push(child_entries.clone()); + Some(()) + }) + .or_else(|| { + child_map + .insert(file.name(child).unwrap(), vec![child_entries]); + Some(()) + }); + // entries.push(ConfigEntry::Value( // Path { // names: vec![file.name(child).unwrap()], // spans: Vec::new(), - // }, + // }, // ConfigValue::Cardinality(child_entries) // )); } - None => () + None => (), } - } - Symbol::Attribute(_) =>{ + Symbol::Attribute(_) => { if let Some(config) = self.values.get(&i.sym(child)) { entries.push(ConfigEntry::Value( Path { @@ -362,25 +390,25 @@ impl ConfigModule { config.clone(), )) } - entries.append(& mut self.serialize_rec_file(child, file,i)); - + entries.append(&mut self.serialize_rec_file(child, file, i)); } _ => { - entries.append(& mut self.serialize_rec_file(child, file, i)); - }, + entries.append(&mut self.serialize_rec_file(child, file, i)); + } } - } for (cardinality_name, cardinality_childs) in child_map.iter() { - entries.push(ConfigEntry::Value( + entries.push(ConfigEntry::Value( Path { names: vec![cardinality_name.clone()], spans: Vec::new(), - }, - ConfigValue::Cardinality(cardinality_childs.clone()) + }, + ConfigValue::Cardinality(CardinalityEntry::CardinalityLvl( + cardinality_childs.clone(), + )), )) } - info!("entries: {:?}",entries); + info!("entries: {:?}", entries); return entries; } diff --git a/uvls/src/webview/frontend.rs b/uvls/src/webview/frontend.rs index 04ff5481..47faa943 100644 --- a/uvls/src/webview/frontend.rs +++ b/uvls/src/webview/frontend.rs @@ -196,7 +196,7 @@ fn ConfigInput<'a>(cx: Scope<'a, ConfigInputProps<'a>>) -> Element { } }, _ => rsx!{ div { - "something" + config.to_string() } }, From a9421bef1b58db22b57fe67fd232f0e8d2f5de20 Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 28 Jun 2023 17:32:03 +0200 Subject: [PATCH 10/17] update from uvl.json to config with cardinality --- uvls/src/core/ast.rs | 12 ++++++ uvls/src/core/ast/transform.rs | 39 ----------------- uvls/src/core/config.rs | 22 +++++++--- uvls/src/core/module.rs | 78 ++++++++++++++++++++++------------ uvls/src/core/parse.rs | 1 - uvls/src/core/semantic.rs | 2 - uvls/src/smt.rs | 7 +-- uvls/src/smt/smt_lib.rs | 2 +- uvls/src/webview.rs | 1 + 9 files changed, 81 insertions(+), 83 deletions(-) diff --git a/uvls/src/core/ast.rs b/uvls/src/core/ast.rs index 05086b80..b6f34ce2 100644 --- a/uvls/src/core/ast.rs +++ b/uvls/src/core/ast.rs @@ -4,6 +4,7 @@ use hashbrown::HashMap; use ropey::Rope; use semantic::FileID; use std::hash::Hash; +use std::ops::Index; use std::path::Component; use tokio::time::Instant; use tower_lsp::lsp_types::Url; @@ -73,6 +74,7 @@ struct Ast { structure: TreeMap, //The index is stored as a typed radix tree index: HashMap<(Symbol, Ustr, SymbolKind), Symbol>, + } impl Ast { pub fn import_prefix(&self, sym: Symbol) -> &[Ustr] { @@ -90,6 +92,7 @@ impl Ast { } //call f for each child under sym and prefix fn lookup(&self, sym: Symbol, prefix: Ustr, mut f: F) { + info!("AST index: {:?}", self.index); match sym { Symbol::Root => { if let Some(&dst) = self.index.get(&(sym, prefix, SymbolKind::Import)) { @@ -402,6 +405,15 @@ impl AstDocument { }) }) } + pub fn get_all_entities(&self,path: &[Ustr]) -> Vec{ + let res = vec![]; + for i in 0..self.ast.features.len() { + if path.last().unwrap_or(&Ustr::from("")) == self.get_feature(i).name.name{ + res.push(Symbol::Feature(i)); + } + } + res + } //prefix of sym from root pub fn prefix(&self, mut sym: Symbol) -> Vec { if matches!(sym, Symbol::Import(..)) { diff --git a/uvls/src/core/ast/transform.rs b/uvls/src/core/ast/transform.rs index e1f1d309..2f234fba 100644 --- a/uvls/src/core/ast/transform.rs +++ b/uvls/src/core/ast/transform.rs @@ -971,43 +971,6 @@ fn visit_attributes(state: &mut VisitorState, parent: Symbol, duplicate: &bool) } } -// fn visit_cardinality(state: &mut VisitorState, parent: Symbol, ty: Type, feature: Feature) { -// let cardinality = feature.cardinality.unwrap(); -// match cardinality { -// Cardinality::Fixed => info!("FUUUUUUUCK Cardinality Any detected!!!!!!!!!"), -// Cardinality::Range(a, b) => { -// info!(" cardinality"); -// for i in 0..b { -// let sym = Symbol::Feature(state.ast.features.len()); -// let new_name = SymbolSpan { -// name: Ustr::from(format!("{}[{}]", feature.name.name, i).as_str()), -// span: feature.name.span.clone(), -// }; -// let new_feature = Feature { -// name: new_name, -// ty: feature.ty.clone(), -// cardinality: Some(Cardinality::Fixed), -// }; -// state.ast.features.push(new_feature); -// state.push_child(parent, sym); -// loop { -// match state.kind() { -// "attributes" => { -// visit_children_arg(state, sym, visit_attributes); -// } -// "blk" => { -// visit_children_arg(state, sym, visit_blk_decl); -// } -// _ => {} -// } -// if !state.goto_next_sibling() { -// break; -// } -// } -// } -// } -// } -// } fn visit_feature( state: &mut VisitorState, parent: Symbol, @@ -1015,7 +978,6 @@ fn visit_feature( ty: Type, duplicate: bool, ) { - info!("visit feature"); match parent { Symbol::Feature(..) => { state.push_error(40, "features have to be separated by groups"); @@ -1255,7 +1217,6 @@ fn visit_constraints(state: &mut VisitorState) { } fn visit_top_lvl(state: &mut VisitorState) { let mut top_level_order: Vec = Vec::new(); - info!("visit top level"); loop { if state.kind() == "blk" { let header = state.header().unwrap(); diff --git a/uvls/src/core/config.rs b/uvls/src/core/config.rs index 30cf5488..66d3998b 100644 --- a/uvls/src/core/config.rs +++ b/uvls/src/core/config.rs @@ -1,8 +1,9 @@ -use std::{fmt::Display, path}; +use std::{fmt::Display, path, error::Error}; use crate::core::*; use ast::*; use check::ErrorInfo; +use serde_json::Deserializer; use crate::ide::completion::*; use parse::SymbolSlice; use semantic::{FileID, RootGraph}; @@ -60,7 +61,7 @@ impl Serialize for CardinalityEntry { CardinalityEntry::CardinalityLvl(childs) => { let mut s = serializer.serialize_seq(Some(childs.len()))?; for child in childs { - s.serialize_element(&CardinalityEntry::EntitiyLvl(child.to_owned())); + let _ = s.serialize_element(&CardinalityEntry::EntitiyLvl(child.to_owned())); } s.end() @@ -99,7 +100,7 @@ impl Display for ConfigValue { Self::Bool(x) => write!(f, "{x}"), Self::Number(x) => write!(f, "{x}"), Self::String(x) => write!(f, "{x}"), - Self::Cardinality(x) => write!(f, "testWrite"), + Self::Cardinality(_) => Ok(()), } } } @@ -146,7 +147,15 @@ impl<'de> Deserialize<'de> for ConfigEntry { where D: serde::Deserializer<'de> { - Ok(ConfigEntry::Value(Path { names: vec![], spans: vec![] }, ConfigValue::Bool(true))) + let s = Deserialize::deserialize(deserializer)?; + info!("deserialize {:?}", s); + + Ok(ConfigEntry::Value(Path { names: vec![Ustr::from("importZZZ")], spans: vec![] }, ConfigValue::Bool(true))) + + // match deserializer { + // ConfigEntry::Import(_, _ ) => Ok(ConfigEntry::Value(Path { names: vec![Ustr::from("importZZZ")], spans: vec![] }, ConfigValue::Bool(true))), + // ConfigEntry::Value(path, value) => Ok(ConfigEntry::Value(Path { names: vec![Ustr::from("valueZZZ")], spans: vec![] }, ConfigValue::Bool(true))) + // } } } @@ -256,10 +265,10 @@ fn opt_configs(state: &mut State) -> Vec { }) }); info!("{:?}",children); - acc.push(ConfigEntry::Value(key, ConfigValue::Cardinality(CardinalityEntry::CardinalityLvl(vec![children])))) + acc.push(ConfigEntry::Value(key, ConfigValue::Bool(true))); } _ => { - state.push_error_node(val, 30, format!("Explect Number or Bool {:?}", val.kind())); + state.push_error_node(val, 30, format!("Expect Number or Bool {:?}", val.kind())); } } } @@ -297,6 +306,7 @@ fn visit_file(state: &mut State) -> Option { state.goto_field("value"); if state.kind() == "object" { config = Some(visit_children(state, opt_configs)); + info!("config: {:?}", config); } else { state.push_error(30, "expected object"); } diff --git a/uvls/src/core/module.rs b/uvls/src/core/module.rs index 48352ffc..dcaafcc2 100644 --- a/uvls/src/core/module.rs +++ b/uvls/src/core/module.rs @@ -185,22 +185,51 @@ impl Module { for c in config.iter() { match c { ConfigEntry::Value(path, val) => { - if let Some(sym) = file - .lookup(Symbol::Root, &path.names, |sym| { - matches!(sym, Symbol::Feature(..) | Symbol::Attribute(..)) - }) - .next() - { - if file.type_of(sym).unwrap() == val.ty() { - out.insert(ModuleSymbol { instance, sym }, val.clone()); - out_span.insert(ModuleSymbol { instance, sym }, path.range()); - } else { - if let Symbol::Feature(i) = sym { - let feature = file.get_feature(i).unwrap().clone(); - if let Cardinality::Range(_, _) = feature.cardinality.unwrap() { - out.insert(ModuleSymbol { instance, sym }, val.clone()); - out_span - .insert(ModuleSymbol { instance, sym }, path.range()); + match val { + ConfigValue::Cardinality(entry) => { + match entry { + CardinalityEntry::CardinalityLvl(val_entry) => { + let entries = file.get_all_entities( &path.names); + for siebzig in val_entry { + for achtzig in siebzig{ + + } + } + + for e in entries { + info!("Symbol Iterator {:?}, {:?}", e, path); + } + }, + CardinalityEntry::EntitiyLvl(_) => panic!("Unexpected Cardinality Level"), + } + } + _ => { + if let Some(sym) = file + .lookup(Symbol::Root, &path.names, |sym| { + matches!(sym, Symbol::Feature(..) | Symbol::Attribute(..)) + }) + .next() + { + if file.type_of(sym).unwrap() == val.ty() { + out.insert(ModuleSymbol { instance, sym }, val.clone()); + out_span.insert(ModuleSymbol { instance, sym }, path.range()); + } else { + if let Symbol::Feature(i) = sym { + let feature = file.get_feature(i).unwrap().clone(); + if let Cardinality::Range(_, _) = feature.cardinality.unwrap() { + out.insert(ModuleSymbol { instance, sym }, val.clone()); + out_span + .insert(ModuleSymbol { instance, sym }, path.range()); + } else { + err( + path.range(), + format!( + "expected {} got {}", + file.type_of(sym).unwrap(), + val.ty() + ), + ); + } } else { err( path.range(), @@ -211,20 +240,13 @@ impl Module { ), ); } - } else { - err( - path.range(), - format!( - "expected {} got {}", - file.type_of(sym).unwrap(), - val.ty() - ), - ); } + } else { + err(path.range(), format!("unresolved value",)); } - } else { - err(path.range(), format!("unresolved value",)); - } + } + } + } ConfigEntry::Import(path, val) => { if let Some(sym) = file diff --git a/uvls/src/core/parse.rs b/uvls/src/core/parse.rs index 79638c6f..432105cb 100644 --- a/uvls/src/core/parse.rs +++ b/uvls/src/core/parse.rs @@ -143,7 +143,6 @@ pub fn parse_lang_lvl(node: Node, source: &S) -> Option(node: Node, source: &S) -> Option { - info!("{:?}", node); if let Some(name) = parse_lang_lvl(node, source) { Some(Path { names: vec![name.name], diff --git a/uvls/src/core/semantic.rs b/uvls/src/core/semantic.rs index 8fa61e09..0d51ed1d 100644 --- a/uvls/src/core/semantic.rs +++ b/uvls/src/core/semantic.rs @@ -193,7 +193,6 @@ impl RootGraph { let mut file_paths = HashSet::new(); for file in files.values() { if !file_paths.insert(file.path.as_slice()) { - //info!("{:?}", file.namespace()); if let Some(ns) = file.namespace() { if err.errors.contains_key(&file.id) { err.span(ns.range(), file.id, 100, "namespace already defined"); @@ -202,7 +201,6 @@ impl RootGraph { } } } - //info!("dirty {:?}",dirty); Self { cancel: CancellationToken::new(), cache: Cache::new(old, files, configs, &dirty, revision, err), diff --git a/uvls/src/smt.rs b/uvls/src/smt.rs index e9e0ddfc..2fd2a755 100644 --- a/uvls/src/smt.rs +++ b/uvls/src/smt.rs @@ -222,7 +222,6 @@ async fn find_fixed( } //let time = Instant::now(); if solve.check_sat().await? { - //info!("check sat {:?}", time.elapsed()); let unknown = state .iter() .filter(|(_, v)| !matches!(*v, SMTValueState::Any)) @@ -230,7 +229,6 @@ async fn find_fixed( format!("{acc} v{}", module.var(*k)) }); let values = solve.values(unknown).await?; - //info!("model {:?}", time.elapsed()); for (s, v) in module.parse_values(&values, base_module) { if let Some(old) = state.get(&s) { match (v, old) { @@ -347,7 +345,6 @@ async fn check_base_sat( async move { let smt_module = uvl2smt(&module, &HashMap::new()); let source = smt_module.to_source(&module); - info!("{}",source); let model = create_model( &module, root.cancellation_token(), @@ -562,7 +559,6 @@ pub async fn check_handler( loop { info!("Check SMT"); let root = rx_root.borrow_and_update().clone(); - info!("test"); latest_versions = check_base_sat(&root, &tx_err, latest_versions).await; latest_versions_config = check_config(&root, &tx_err, &inlay_state, latest_versions_config).await; @@ -598,13 +594,12 @@ pub async fn web_view_handler( }) }) .await; - //info!("model: {model:?}"); tx_ui .send(webview::UIAction::UpdateSMTModel(model, tag)) .await?; } Err(e) => { - //info!("err {e}"); + inlay_state.maybe_reset(inlay_source).await; tx_ui .send(webview::UIAction::UpdateSMTInvalid(format!("{e}"), tag)) diff --git a/uvls/src/smt/smt_lib.rs b/uvls/src/smt/smt_lib.rs index f2c4e2ba..2f81fcd7 100644 --- a/uvls/src/smt/smt_lib.rs +++ b/uvls/src/smt/smt_lib.rs @@ -425,12 +425,12 @@ impl Into for ConfigValue { Self::Bool(b) => Expr::Bool(b), Self::Number(n) => Expr::Real(n), Self::String(s) => Expr::String(s), + Self::Cardinality(_) => Expr::Bool(true), _ => unimplemented!() } } } -//TODO check cardinality pub fn uvl2smt(module: &Module, config: &HashMap) -> SMTModule { assert!(module.ok); let mut builder = SMTBuilder { diff --git a/uvls/src/webview.rs b/uvls/src/webview.rs index b1615042..942700f4 100644 --- a/uvls/src/webview.rs +++ b/uvls/src/webview.rs @@ -212,6 +212,7 @@ fn create_file_tree( config: &HashMap, entries: &mut IndexMap, ) { + info!("config_web{:?}", config); let mut last = Symbol::Root; let mut vdir = 0; file.visit_children_depth(Symbol::Root, true, |sym, depth| match sym { From 0f751233afc02b3ff674bc8dbf7e16e58c8965ce Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Mon, 3 Jul 2023 17:22:41 +0200 Subject: [PATCH 11/17] update uvl.json to config webview --- uvls/src/core/ast.rs | 4 +- uvls/src/core/config.rs | 14 +++++-- uvls/src/core/module.rs | 80 +++++++++++++++++++++++---------------- uvls/src/core/pipeline.rs | 1 + uvls/src/webview.rs | 5 ++- 5 files changed, 65 insertions(+), 39 deletions(-) diff --git a/uvls/src/core/ast.rs b/uvls/src/core/ast.rs index b6f34ce2..c3d683a2 100644 --- a/uvls/src/core/ast.rs +++ b/uvls/src/core/ast.rs @@ -406,9 +406,9 @@ impl AstDocument { }) } pub fn get_all_entities(&self,path: &[Ustr]) -> Vec{ - let res = vec![]; + let mut res = vec![]; for i in 0..self.ast.features.len() { - if path.last().unwrap_or(&Ustr::from("")) == self.get_feature(i).name.name{ + if path.last().unwrap_or(&Ustr::from("")).clone() == self.get_feature(i).unwrap().name.name{ res.push(Symbol::Feature(i)); } } diff --git a/uvls/src/core/config.rs b/uvls/src/core/config.rs index 66d3998b..dc7acfd4 100644 --- a/uvls/src/core/config.rs +++ b/uvls/src/core/config.rs @@ -260,11 +260,17 @@ fn opt_configs(state: &mut State) -> Vec { "array" =>{ let children = stacker::maybe_grow(32 * 1024, 1024 * 1024, || { visit_children(state, |state| { - state.goto_field("value"); - visit_children(state, opt_configs) + state.goto_field("array"); + opt_configs(state) + }) }); - info!("{:?}",children); + info!("JSON Children: {:?}",children); + info!("JSON Children len: {:?}",val.child_count()); + info!("JSON Children zero: {:?}",val.child(0)); + // for i in 0..val.child_count() { + // info!("Child {}: {:?}", i, opt_configs(val.child(i))) + // } acc.push(ConfigEntry::Value(key, ConfigValue::Bool(true))); } _ => { @@ -272,6 +278,8 @@ fn opt_configs(state: &mut State) -> Vec { } } } + }else{ + info!("state {}", state.kind()); } }); acc diff --git a/uvls/src/core/module.rs b/uvls/src/core/module.rs index dcaafcc2..dd6e8da6 100644 --- a/uvls/src/core/module.rs +++ b/uvls/src/core/module.rs @@ -179,47 +179,65 @@ impl Module { assert!(self.ok); let mut out = HashMap::new(); let mut out_span = HashMap::new(); - let mut stack = vec![(InstanceID(0), doc.as_slice())]; - while let Some((instance, config)) = stack.pop() { + let mut stack = vec![(InstanceID(0), doc.as_slice(), 0 as usize)]; + while let Some((instance, config, offset)) = stack.pop() { + info!("instance: {:?}, config:{:?}",instance, config); let file = self.file(instance); for c in config.iter() { match c { - ConfigEntry::Value(path, val) => { - match val { - ConfigValue::Cardinality(entry) => { - match entry { - CardinalityEntry::CardinalityLvl(val_entry) => { - let entries = file.get_all_entities( &path.names); - for siebzig in val_entry { - for achtzig in siebzig{ - + ConfigEntry::Value(path, val) => match val { + ConfigValue::Cardinality(entry) => match entry { + CardinalityEntry::CardinalityLvl(val_entry) => { + info!("resolve - Cardinality"); + let vec_entries = file.get_all_entities(&path.names.clone()); + let entries = vec_entries.iter().nth(offset); + info!("Cardinality entries: {:?}", entries); + match entries { + Some(Symbol::Feature(i)) => { + let feature = file.get_feature(i.clone()).unwrap(); + match feature.cardinality { + Some(Cardinality::Range(_, max)) => { + for j in 0..val_entry.len() { + info!("PUSH Stack: {:?}", val_entry.iter().nth(j).unwrap()); + stack.push(( + instance, + val_entry.iter().nth(j).unwrap(), + offset * max + j, + )); } } + _ => (), + } + } + _ => panic!("unexpected feature"), + } - for e in entries { - info!("Symbol Iterator {:?}, {:?}", e, path); - } - }, - CardinalityEntry::EntitiyLvl(_) => panic!("Unexpected Cardinality Level"), + for e in entries { + info!("Symbol Iterator {:?}, {:?}", e, path); } } - _ => { - if let Some(sym) = file - .lookup(Symbol::Root, &path.names, |sym| { - matches!(sym, Symbol::Feature(..) | Symbol::Attribute(..)) - }) - .next() - { + CardinalityEntry::EntitiyLvl(_) => { + panic!("Unexpected Cardinality Level") + } + }, + _ => { + info!("resolve - Value"); + if let Some(sym_ref) = file.get_all_entities(&path.names).iter().nth(offset) { + let sym = sym_ref.clone(); if file.type_of(sym).unwrap() == val.ty() { out.insert(ModuleSymbol { instance, sym }, val.clone()); out_span.insert(ModuleSymbol { instance, sym }, path.range()); } else { if let Symbol::Feature(i) = sym { let feature = file.get_feature(i).unwrap().clone(); - if let Cardinality::Range(_, _) = feature.cardinality.unwrap() { + if let Cardinality::Range(_, _) = + feature.cardinality.unwrap() + { out.insert(ModuleSymbol { instance, sym }, val.clone()); - out_span - .insert(ModuleSymbol { instance, sym }, path.range()); + out_span.insert( + ModuleSymbol { instance, sym }, + path.range(), + ); } else { err( path.range(), @@ -244,10 +262,8 @@ impl Module { } else { err(path.range(), format!("unresolved value",)); } - } - } - - } + } + }, ConfigEntry::Import(path, val) => { if let Some(sym) = file .lookup(Symbol::Root, &path.names, |sym| { @@ -255,7 +271,7 @@ impl Module { }) .find(|sym| matches!(sym, Symbol::Import(..))) { - stack.push((self.get_instance(instance, sym), &val)); + stack.push((self.get_instance(instance, sym), &val, offset)); } else { err(path.range(), format!("unresolved import",)); } @@ -263,6 +279,7 @@ impl Module { } } } + info!("resolve config {:?}", out); (out, out_span) } @@ -351,7 +368,6 @@ impl ConfigModule { "VISIT: {:?}", file.name(child).unwrap_or(Ustr::from("Error")) ); - info!("CHILD: {:?}", child); match child { Symbol::Feature(id) => { let feature = file.get_feature(id).unwrap(); diff --git a/uvls/src/core/pipeline.rs b/uvls/src/core/pipeline.rs index 57b3aa6d..2d12e3c9 100644 --- a/uvls/src/core/pipeline.rs +++ b/uvls/src/core/pipeline.rs @@ -91,6 +91,7 @@ async fn draft_handler( } }; info!("started draft handler {uri}"); + info!("draft: {:?}" , draft); spawn(make_red_tree(draft.clone(), uri.clone(), tx_link.clone())); while let Some(msg) = rx.recv().await { match msg { diff --git a/uvls/src/webview.rs b/uvls/src/webview.rs index 942700f4..f0030e3e 100644 --- a/uvls/src/webview.rs +++ b/uvls/src/webview.rs @@ -240,7 +240,7 @@ fn create_file_tree( Symbol::Feature(_) | Symbol::Attribute(_) => { let depth = depth + base_depth - 1; match file.type_of(sym).unwrap() { - Type::String | Type::Real | Type::Bool | Type::Attributes => {} + Type::String | Type::Real | Type::Bool | Type::Attributes| Type::Object => {} _ => { return true; } @@ -265,7 +265,7 @@ fn create_file_tree( let ms = instance.sym(sym); let config = config.get(&ms).cloned(); - + info!("Config Check. MS:{:?}, config: :{:?}", ms, config); entries.insert( ms, UIEntry { @@ -305,6 +305,7 @@ fn create_file_tree( }, }, ); + info!("entries: {:?}:", entries); last = sym; true } From 13057ae21732e47c2332d7a5912ab8357db304d1 Mon Sep 17 00:00:00 2001 From: Felix Date: Tue, 4 Jul 2023 15:21:40 +0200 Subject: [PATCH 12/17] feat: add json loading for configuration --- uvls/src/core/config.rs | 180 ++++++++++++++++++++++------------------ uvls/src/webview.rs | 8 +- 2 files changed, 103 insertions(+), 85 deletions(-) diff --git a/uvls/src/core/config.rs b/uvls/src/core/config.rs index dc7acfd4..b9b9edba 100644 --- a/uvls/src/core/config.rs +++ b/uvls/src/core/config.rs @@ -1,10 +1,9 @@ -use std::{fmt::Display, path, error::Error}; use crate::core::*; +use std::fmt::Display; +use crate::ide::completion::*; use ast::*; use check::ErrorInfo; -use serde_json::Deserializer; -use crate::ide::completion::*; use parse::SymbolSlice; use semantic::{FileID, RootGraph}; use util::*; @@ -32,7 +31,7 @@ use ustr::Ustr; // //} //This representation is very compact since it avoids rewriting long import prefixes but slightly -//more complex than just using the direct raw path to external symbols. +//more complex than just using the direct raw path to external symbols. //JSON parsing is done with tree-sitter and not serde because there currently is no solid serde json //crate for span information and partial parsing so error reporting becomes impossible. @@ -48,14 +47,14 @@ pub enum ConfigValue { Bool(bool), Number(f64), String(String), - Cardinality(CardinalityEntry) + Cardinality(CardinalityEntry), } impl Serialize for CardinalityEntry { fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer { - + where + S: serde::Serializer, + { use serde::ser::SerializeSeq; match self { CardinalityEntry::CardinalityLvl(childs) => { @@ -64,11 +63,15 @@ impl Serialize for CardinalityEntry { let _ = s.serialize_element(&CardinalityEntry::EntitiyLvl(child.to_owned())); } s.end() - - } - CardinalityEntry::EntitiyLvl(childs) => { - ConfigEntry::Import(Path { names: vec![], spans: vec![] }, childs.to_owned()).serialize(serializer) } + CardinalityEntry::EntitiyLvl(childs) => ConfigEntry::Import( + Path { + names: vec![], + spans: vec![], + }, + childs.to_owned(), + ) + .serialize(serializer), } } } @@ -116,13 +119,11 @@ impl Serialize for ConfigEntry { where S: serde::Serializer, { - use serde::ser::{SerializeMap,SerializeSeq, SerializeStruct}; - + use serde::ser::SerializeMap; match self { - ConfigEntry::Value(p,k) => { - info!("Here I dould normally panic"); - serializer.serialize_bool(true) + ConfigEntry::Value(_p, _k) => { + panic!("Unexpected Value"); } ConfigEntry::Import(_, v) => { let mut s = serializer.serialize_map(Some(v.len()))?; @@ -144,13 +145,19 @@ impl Serialize for ConfigEntry { impl<'de> Deserialize<'de> for ConfigEntry { fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de> + where + D: serde::Deserializer<'de>, { let s = Deserialize::deserialize(deserializer)?; info!("deserialize {:?}", s); - Ok(ConfigEntry::Value(Path { names: vec![Ustr::from("importZZZ")], spans: vec![] }, ConfigValue::Bool(true))) + Ok(ConfigEntry::Value( + Path { + names: vec![Ustr::from("importZZZ")], + spans: vec![], + }, + ConfigValue::Bool(true), + )) // match deserializer { // ConfigEntry::Import(_, _ ) => Ok(ConfigEntry::Value(Path { names: vec![Ustr::from("importZZZ")], spans: vec![] }, ConfigValue::Bool(true))), @@ -219,6 +226,7 @@ impl<'a> Visitor<'a> for State<'a> { fn opt_configs(state: &mut State) -> Vec { let mut acc = Vec::new(); visit_siblings(state, |state| { + info!("KIND: {:?}", state.kind()); if state.kind() == "pair" { if let Some(key) = state .child_by_name("key") @@ -257,29 +265,39 @@ fn opt_configs(state: &mut State) -> Vec { }); acc.push(ConfigEntry::Import(key, children)); } - "array" =>{ - let children = stacker::maybe_grow(32 * 1024, 1024 * 1024, || { - visit_children(state, |state| { - state.goto_field("array"); - opt_configs(state) - - }) + "array" => { + let mut children: Vec> = vec![]; + + state.goto_first_child(); + state.goto_field("value"); + state.goto_first_child(); + + visit_siblings(state, |state: &mut State<'_>| { + if state.kind() == "object" { + let children_object = + stacker::maybe_grow(32 * 1024, 1024 * 1024, || { + visit_children(state, |state| opt_configs(state)) + }); + children.push(children_object); + } }); - info!("JSON Children: {:?}",children); - info!("JSON Children len: {:?}",val.child_count()); - info!("JSON Children zero: {:?}",val.child(0)); - // for i in 0..val.child_count() { - // info!("Child {}: {:?}", i, opt_configs(val.child(i))) - // } - acc.push(ConfigEntry::Value(key, ConfigValue::Bool(true))); + state.goto_parent(); + state.goto_parent(); + + acc.push(ConfigEntry::Value( + key, + ConfigValue::Cardinality(CardinalityEntry::CardinalityLvl(children)), + )); } _ => { - state.push_error_node(val, 30, format!("Expect Number or Bool {:?}", val.kind())); + state.push_error_node( + val, + 30, + format!("Expect Number or Bool {:?}", val.kind()), + ); } } } - }else{ - info!("state {}", state.kind()); } }); acc @@ -398,7 +416,11 @@ fn json_path<'a>(mut node: Node, rope: &'a Rope) -> Vec { while let Some(p) = node.parent() { if node.kind() == "object" && p.kind() == "pair" { if let Some(key) = p.child_by_field_name("key").and_then(|k| k.named_child(0)) { - ctx.push(rope.slice(key.byte_range()).to_string().replace(r#"\"""#,"") ) + ctx.push( + rope.slice(key.byte_range()) + .to_string() + .replace(r#"\"""#, ""), + ) } } node = p; @@ -442,12 +464,9 @@ fn find_json_key<'a>(mut root: Node<'a>, source: &Rope, key: &[Ustr]) -> Option< if cursor.goto_first_child() { loop { if let Some(name) = cursor.node().child_by_field_name("key") { - - if source.slice_raw(name.named_child(0)?.byte_range()) == k.as_str() { root = cursor.node().child_by_field_name("value")?; - break; } } @@ -497,41 +516,36 @@ fn estimate_json_item(pos: &Position, source: &Rope) -> Option { let slice: std::borrow::Cow<'_, _> = source.line(line).into(); let start_byte = source.line_to_byte(line); let pos_byte = byte_offset(pos, source) - start_byte; - + RE.captures(&slice) .iter() - .find_map(|cap| { - - - match (cap.get(1), cap.get(2)) { - (Some(key), Some(val)) => { - if key.range().overlaps(pos_byte) { - Some(JSONItem::Key { - key: offset(key.range(), start_byte), - value: Some(offset(val.range(), start_byte)), - }) - } else if val.range().overlaps(pos_byte) { - Some(JSONItem::Value { - key: offset(key.range(), start_byte), - value: offset(val.range(), start_byte), - }) - } else { - None - } + .find_map(|cap| match (cap.get(1), cap.get(2)) { + (Some(key), Some(val)) => { + if key.range().overlaps(pos_byte) { + Some(JSONItem::Key { + key: offset(key.range(), start_byte), + value: Some(offset(val.range(), start_byte)), + }) + } else if val.range().overlaps(pos_byte) { + Some(JSONItem::Value { + key: offset(key.range(), start_byte), + value: offset(val.range(), start_byte), + }) + } else { + None } - (Some(key), None) if key.range().overlaps(pos_byte) => Some(JSONItem::Key { - key: offset(key.range(), start_byte), - value: None, - }), - _ => None, } + (Some(key), None) if key.range().overlaps(pos_byte) => Some(JSONItem::Key { + key: offset(key.range(), start_byte), + value: None, + }), + _ => None, }) .or_else(|| { lazy_static! { static ref RE: Regex = Regex::new(r#""((?:[^"\\]|\\.)*)""#).unwrap(); }; - RE.captures(&slice).iter().find_map(|cap| { info!("Cap: {:#?} ", cap); cap.get(1).and_then(|key| { @@ -551,7 +565,6 @@ fn estimate_json_item(pos: &Position, source: &Rope) -> Option { .chars() .all(|c| c.is_alphanumeric() || c.is_whitespace() || c == '.') { - let start = slice .char_indices() .take_while(|(_, c)| c.is_whitespace()) @@ -566,7 +579,6 @@ fn estimate_json_item(pos: &Position, source: &Rope) -> Option { .unwrap_or_default() .0 + start; - if (start..last + 1).contains(&pos_byte) { Some(JSONItem::FreeKey(offset(start..last + 1, start_byte))) @@ -641,7 +653,7 @@ pub fn completion_query(source: &Rope, tree: &Tree, src_pos: &Position) -> Optio .collect(); info!("path:{path:#?}"); info!("prefix:{prefix:#?}"); - info!("char:{}",source.char(char)); + info!("char:{}", source.char(char)); if source.char(char) == '.' { Some(CompletionQuery { offset: CompletionOffset::Dot, @@ -665,7 +677,7 @@ pub fn completion_query(source: &Rope, tree: &Tree, src_pos: &Position) -> Optio source, )?, }, - prefix:prefix[0..prefix.len().saturating_sub(1)].to_vec(), + prefix: prefix[0..prefix.len().saturating_sub(1)].to_vec(), postfix: path.names.last().map(|s| s.as_str()).unwrap_or("").into(), }) } @@ -689,12 +701,15 @@ pub fn completion_query(source: &Rope, tree: &Tree, src_pos: &Position) -> Optio start: src_pos.clone(), end: src_pos.clone(), }, - key_start:if path.len()>0{ - let start = lsp_position( path.spans[0].start,source).clone().unwrap(); - Some(Range{start:start.clone(),end:start}) - }else{ + key_start: if path.len() > 0 { + let start = lsp_position(path.spans[0].start, source).clone().unwrap(); + Some(Range { + start: start.clone(), + end: start, + }) + } else { None - } + }, }, prefix, postfix: CompactString::new_inline(""), @@ -708,14 +723,17 @@ pub fn completion_query(source: &Rope, tree: &Tree, src_pos: &Position) -> Optio path.spans.last().cloned().unwrap_or(key), source, )?, - key_start:if path.len()>1{ - let start = lsp_position( path.spans[0].start,source).clone().unwrap(); - Some(Range{start:start.clone(),end:start}) - }else{ + key_start: if path.len() > 1 { + let start = lsp_position(path.spans[0].start, source).clone().unwrap(); + Some(Range { + start: start.clone(), + end: start, + }) + } else { None - } + }, }, - prefix:prefix[0..prefix.len().saturating_sub(1)].to_vec(), + prefix: prefix[0..prefix.len().saturating_sub(1)].to_vec(), postfix: path.names.last().map(|s| s.as_str()).unwrap_or("").into(), }) } diff --git a/uvls/src/webview.rs b/uvls/src/webview.rs index f0030e3e..d7a3bb8f 100644 --- a/uvls/src/webview.rs +++ b/uvls/src/webview.rs @@ -240,7 +240,7 @@ fn create_file_tree( Symbol::Feature(_) | Symbol::Attribute(_) => { let depth = depth + base_depth - 1; match file.type_of(sym).unwrap() { - Type::String | Type::Real | Type::Bool | Type::Attributes| Type::Object => {} + Type::String | Type::Real | Type::Bool | Type::Attributes | Type::Object => {} _ => { return true; } @@ -265,7 +265,7 @@ fn create_file_tree( let ms = instance.sym(sym); let config = config.get(&ms).cloned(); - info!("Config Check. MS:{:?}, config: :{:?}", ms, config); + // info!("Config Check. MS:{:?}, config: :{:?}", ms, config); entries.insert( ms, UIEntry { @@ -305,7 +305,7 @@ fn create_file_tree( }, }, ); - info!("entries: {:?}:", entries); + // info!("entries: {:?}:", entries); last = sym; true } @@ -734,7 +734,7 @@ pub async fn ui_main( spawn(ui_sync(pipeline.clone(), tx_sync, root)); //Run the event loop ui_event_loop( - id, tx_config, ui_rx, rx_sync, &ui_config, &ui_state, &pipeline, tgt_path + id, tx_config, ui_rx, rx_sync, &ui_config, &ui_state, &pipeline, tgt_path, ) .await?; From 8e0301ac3e44dd80ce5946f8c7f5fa180705f1d8 Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 5 Jul 2023 14:28:28 +0200 Subject: [PATCH 13/17] fix: config with no set cardinality --- uvls/src/core/module.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/uvls/src/core/module.rs b/uvls/src/core/module.rs index dd6e8da6..21aacb73 100644 --- a/uvls/src/core/module.rs +++ b/uvls/src/core/module.rs @@ -364,10 +364,6 @@ impl ConfigModule { let mut child_map: HashMap>> = hashbrown::HashMap::new(); for child in file.direct_children(sym) { - info!( - "VISIT: {:?}", - file.name(child).unwrap_or(Ustr::from("Error")) - ); match child { Symbol::Feature(id) => { let feature = file.get_feature(id).unwrap(); @@ -395,6 +391,8 @@ impl ConfigModule { config.clone(), )); child_entries.append(&mut self.serialize_rec_file(child, file, i)); + }else{ + child_entries.append(&mut self.serialize_rec_file(child, file, i)); } child_map .get_mut(&file.name(child).unwrap()) From 64a07552cd9a70d4c9348d02965468436ac228f2 Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 5 Jul 2023 14:50:32 +0200 Subject: [PATCH 14/17] feat: clean config with cardinality --- uvls/src/core/module.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/uvls/src/core/module.rs b/uvls/src/core/module.rs index 21aacb73..413f33d4 100644 --- a/uvls/src/core/module.rs +++ b/uvls/src/core/module.rs @@ -390,21 +390,22 @@ impl ConfigModule { }, config.clone(), )); - child_entries.append(&mut self.serialize_rec_file(child, file, i)); - }else{ - child_entries.append(&mut self.serialize_rec_file(child, file, i)); } - child_map - .get_mut(&file.name(child).unwrap()) - .and_then(|x| { - x.push(child_entries.clone()); - Some(()) - }) - .or_else(|| { - child_map - .insert(file.name(child).unwrap(), vec![child_entries]); - Some(()) - }); + child_entries.append(&mut self.serialize_rec_file(child, file, i)); + if child_entries.len() > 0 { + child_map + .get_mut(&file.name(child).unwrap()) + .and_then(|x| { + x.push(child_entries.clone()); + Some(()) + }) + .or_else(|| { + child_map + .insert(file.name(child).unwrap(), vec![child_entries]); + Some(()) + }); + } + // entries.push(ConfigEntry::Value( // Path { // names: vec![file.name(child).unwrap()], From 46e9faaf6cf83437eaba3d038d74129ba1ed09d2 Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 5 Jul 2023 15:33:16 +0200 Subject: [PATCH 15/17] Cleanup --- uvls/src/core/ast.rs | 4 +- uvls/src/core/ast/def.rs | 3 +- uvls/src/core/ast/graph.rs | 1 + uvls/src/core/ast/transform.rs | 5 +-- uvls/src/core/check.rs | 1 + uvls/src/core/config.rs | 25 +++-------- uvls/src/core/module.rs | 78 +++++++++++----------------------- uvls/src/core/pipeline.rs | 1 - uvls/src/smt.rs | 3 +- uvls/src/smt/parse.rs | 2 +- uvls/src/smt/smt_lib.rs | 3 +- uvls/src/webview.rs | 4 +- uvls/src/webview/frontend.rs | 4 +- 13 files changed, 42 insertions(+), 92 deletions(-) diff --git a/uvls/src/core/ast.rs b/uvls/src/core/ast.rs index c3d683a2..6d6fc73f 100644 --- a/uvls/src/core/ast.rs +++ b/uvls/src/core/ast.rs @@ -4,7 +4,6 @@ use hashbrown::HashMap; use ropey::Rope; use semantic::FileID; use std::hash::Hash; -use std::ops::Index; use std::path::Component; use tokio::time::Instant; use tower_lsp::lsp_types::Url; @@ -74,7 +73,6 @@ struct Ast { structure: TreeMap, //The index is stored as a typed radix tree index: HashMap<(Symbol, Ustr, SymbolKind), Symbol>, - } impl Ast { pub fn import_prefix(&self, sym: Symbol) -> &[Ustr] { @@ -92,7 +90,6 @@ impl Ast { } //call f for each child under sym and prefix fn lookup(&self, sym: Symbol, prefix: Ustr, mut f: F) { - info!("AST index: {:?}", self.index); match sym { Symbol::Root => { if let Some(&dst) = self.index.get(&(sym, prefix, SymbolKind::Import)) { @@ -405,6 +402,7 @@ impl AstDocument { }) }) } + // returns all Symbols with same name, used for cardinality resolving pub fn get_all_entities(&self,path: &[Ustr]) -> Vec{ let mut res = vec![]; for i in 0..self.ast.features.len() { diff --git a/uvls/src/core/ast/def.rs b/uvls/src/core/ast/def.rs index b328590f..543f4950 100644 --- a/uvls/src/core/ast/def.rs +++ b/uvls/src/core/ast/def.rs @@ -70,7 +70,6 @@ pub enum GroupMode { pub enum Cardinality { Range(usize, usize), Fixed, - } #[derive(Clone, Debug)] pub enum LanguageLevelMajor { @@ -113,7 +112,7 @@ pub struct Feature { pub cardinality: Option, pub ty: Type, pub duplicate: bool, - pub first_cardinality_child: bool, + pub first_cardinality_child: bool, // used to fix same name problem } #[derive(Clone, Debug)] pub struct Import { diff --git a/uvls/src/core/ast/graph.rs b/uvls/src/core/ast/graph.rs index 3957bad2..d9817478 100644 --- a/uvls/src/core/ast/graph.rs +++ b/uvls/src/core/ast/graph.rs @@ -289,6 +289,7 @@ fn opt_int(node: Node, state: &mut VisitorGraph) -> Option { None } } +// returns cardinality for Node fn opt_cardinality(node: Node, state: &mut VisitorGraph) -> Option { let begin = node.child_by_field_name("begin"); let end = node.child_by_field_name("end"); diff --git a/uvls/src/core/ast/transform.rs b/uvls/src/core/ast/transform.rs index 2f234fba..9d194f4a 100644 --- a/uvls/src/core/ast/transform.rs +++ b/uvls/src/core/ast/transform.rs @@ -99,6 +99,7 @@ impl<'a> VisitorState<'a> { let new_scope = if let Some(name) = self.ast.name(node) { match node { Symbol::Feature(i) => { + // removes duplicate feature error for cardinality if !self.ast.get_feature(i).unwrap().duplicate { if let Some(old) = self .ast @@ -1004,6 +1005,7 @@ fn visit_feature( first_cardinality_child: true, }; + // remaps feature to different entities of the cardinality let mut sym = vec![]; match feature.clone().cardinality.unwrap() { @@ -1022,7 +1024,6 @@ fn visit_feature( } state.ast.features.push(dup_feature); state.push_child(parent, sym.get(i).unwrap().clone()); - // TODO parent remapping } } } @@ -1287,8 +1288,6 @@ pub fn visit_root(source: Rope, tree: Tree, uri: Url, timestamp: Instant) -> Ast source: &source, }; visit_children(&mut state, visit_top_lvl); - info!("{:?}", state.ast.structure); - info!("{:?}", state.ast.features); state.connect(); (state.ast, state.errors) }; diff --git a/uvls/src/core/check.rs b/uvls/src/core/check.rs index bebf9311..8c0792dc 100644 --- a/uvls/src/core/check.rs +++ b/uvls/src/core/check.rs @@ -35,6 +35,7 @@ impl ErrorInfo { } } pub async fn publish(client: &Client, uri: &Url, err: &[ErrorInfo]) { + // reduces cardinality error to one error let mut reduced_err = vec![]; err.iter().for_each(|ele| if !reduced_err.contains(ele) {reduced_err.push(ele.clone())}); if let Some(max) = reduced_err.clone().into_iter().max_by_key(|e| e.weight) { diff --git a/uvls/src/core/config.rs b/uvls/src/core/config.rs index b9b9edba..5d48cc18 100644 --- a/uvls/src/core/config.rs +++ b/uvls/src/core/config.rs @@ -1,13 +1,11 @@ use crate::core::*; use std::fmt::Display; - use crate::ide::completion::*; use ast::*; use check::ErrorInfo; use parse::SymbolSlice; use semantic::{FileID, RootGraph}; use util::*; - use itertools::Itertools; use log::info; use ropey::Rope; @@ -35,6 +33,9 @@ use ustr::Ustr; //JSON parsing is done with tree-sitter and not serde because there currently is no solid serde json //crate for span information and partial parsing so error reporting becomes impossible. + +// This enum is used for storing a cardinality inside of ConfigEntry +// EntitiyLvl is only used to serialize cardinality. #[derive(Debug, Clone, PartialEq, Deserialize)] pub enum CardinalityEntry { CardinalityLvl(Vec>), @@ -75,7 +76,6 @@ impl Serialize for CardinalityEntry { } } } - impl ConfigValue { pub fn ty(&self) -> Type { match self { @@ -122,9 +122,7 @@ impl Serialize for ConfigEntry { use serde::ser::SerializeMap; match self { - ConfigEntry::Value(_p, _k) => { - panic!("Unexpected Value"); - } + ConfigEntry::Value(..) => panic!(), ConfigEntry::Import(_, v) => { let mut s = serializer.serialize_map(Some(v.len()))?; for i in v.iter() { @@ -143,26 +141,19 @@ impl Serialize for ConfigEntry { } } +// This is necesarry for rust compiler impl<'de> Deserialize<'de> for ConfigEntry { - fn deserialize(deserializer: D) -> std::result::Result + fn deserialize(_deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { - let s = Deserialize::deserialize(deserializer)?; - info!("deserialize {:?}", s); - Ok(ConfigEntry::Value( Path { - names: vec![Ustr::from("importZZZ")], + names: vec![], spans: vec![], }, ConfigValue::Bool(true), )) - - // match deserializer { - // ConfigEntry::Import(_, _ ) => Ok(ConfigEntry::Value(Path { names: vec![Ustr::from("importZZZ")], spans: vec![] }, ConfigValue::Bool(true))), - // ConfigEntry::Value(path, value) => Ok(ConfigEntry::Value(Path { names: vec![Ustr::from("valueZZZ")], spans: vec![] }, ConfigValue::Bool(true))) - // } } } @@ -226,7 +217,6 @@ impl<'a> Visitor<'a> for State<'a> { fn opt_configs(state: &mut State) -> Vec { let mut acc = Vec::new(); visit_siblings(state, |state| { - info!("KIND: {:?}", state.kind()); if state.kind() == "pair" { if let Some(key) = state .child_by_name("key") @@ -332,7 +322,6 @@ fn visit_file(state: &mut State) -> Option { state.goto_field("value"); if state.kind() == "object" { config = Some(visit_children(state, opt_configs)); - info!("config: {:?}", config); } else { state.push_error(30, "expected object"); } diff --git a/uvls/src/core/module.rs b/uvls/src/core/module.rs index 413f33d4..d73c978e 100644 --- a/uvls/src/core/module.rs +++ b/uvls/src/core/module.rs @@ -1,10 +1,10 @@ +use tokio::time::Instant; use crate::core::*; +use resolve; use config::*; use hashbrown::HashMap; use indexmap::IndexSet; use log::info; -use resolve; -use tokio::time::Instant; use ustr::Ustr; use std::sync::Arc; @@ -167,7 +167,8 @@ impl Module { _ => panic!("{src_sym:?} not a value"), } } - //Bind a recursive configuration doc to a linear set of symbols + // Bind a recursive configuration doc to a linear set of symbols + // Add layer for cardinality pub fn resolve_config( &self, doc: &Vec, @@ -179,30 +180,27 @@ impl Module { assert!(self.ok); let mut out = HashMap::new(); let mut out_span = HashMap::new(); + // offset is used for mapping to different entities of a cardinality and its children let mut stack = vec![(InstanceID(0), doc.as_slice(), 0 as usize)]; while let Some((instance, config, offset)) = stack.pop() { - info!("instance: {:?}, config:{:?}",instance, config); let file = self.file(instance); for c in config.iter() { match c { ConfigEntry::Value(path, val) => match val { - ConfigValue::Cardinality(entry) => match entry { - CardinalityEntry::CardinalityLvl(val_entry) => { - info!("resolve - Cardinality"); - let vec_entries = file.get_all_entities(&path.names.clone()); - let entries = vec_entries.iter().nth(offset); - info!("Cardinality entries: {:?}", entries); + ConfigValue::Cardinality(cardinality) => match cardinality { + CardinalityEntry::CardinalityLvl(cardinality_lvl) => { + let entries = file.get_all_entities(&path.names.clone()); + let entries = entries.iter().nth(offset); match entries { - Some(Symbol::Feature(i)) => { - let feature = file.get_feature(i.clone()).unwrap(); + Some(Symbol::Feature(id)) => { + let feature = file.get_feature(id.clone()).unwrap(); match feature.cardinality { Some(Cardinality::Range(_, max)) => { - for j in 0..val_entry.len() { - info!("PUSH Stack: {:?}", val_entry.iter().nth(j).unwrap()); + for i in 0..cardinality_lvl.len() { stack.push(( instance, - val_entry.iter().nth(j).unwrap(), - offset * max + j, + cardinality_lvl.iter().nth(i).unwrap(), + offset * max + i, )); } } @@ -211,17 +209,12 @@ impl Module { } _ => panic!("unexpected feature"), } - - for e in entries { - info!("Symbol Iterator {:?}, {:?}", e, path); - } } CardinalityEntry::EntitiyLvl(_) => { - panic!("Unexpected Cardinality Level") + panic!("unexpected cardinality level") } }, _ => { - info!("resolve - Value"); if let Some(sym_ref) = file.get_all_entities(&path.names).iter().nth(offset) { let sym = sym_ref.clone(); if file.type_of(sym).unwrap() == val.ty() { @@ -279,7 +272,6 @@ impl Module { } } } - info!("resolve config {:?}", out); (out, out_span) } @@ -329,22 +321,6 @@ impl ConfigModule { } entries.append(&mut self.serialize_rec_file(Symbol::Root, file, i)); - // file.visit_named_children(Symbol::Root, false, |sym, prefix| match sym { - // Symbol::Feature(_) | Symbol::Attribute(_) => { - // if let Some(config) = self.values.get(&i.sym(sym)) { - // entries.push(ConfigEntry::Value( - // Path { - // names: prefix.to_vec(), - // spans: Vec::new(), - // }, - // config.clone(), - // )) - // } - // true - // } - // _ => false, - // }); - ConfigEntry::Import( Path { names: path.to_vec(), @@ -354,6 +330,7 @@ impl ConfigModule { ) } + // serialize file recursive while accommodate for cardinality fn serialize_rec_file( &self, sym: Symbol, @@ -361,6 +338,7 @@ impl ConfigModule { i: InstanceID, ) -> Vec { let mut entries: Vec = Vec::new(); + // used for different entities of cardinality let mut child_map: HashMap>> = hashbrown::HashMap::new(); for child in file.direct_children(sym) { @@ -381,9 +359,10 @@ impl ConfigModule { entries.append(&mut self.serialize_rec_file(child, file, i)); } Some(Cardinality::Range(_, _)) => { - let mut child_entries: Vec = vec![]; + let mut cardinal_entry: Vec = vec![]; + // add self to cardinality definition if let Some(config) = self.values.get(&i.sym(child)) { - child_entries.push(ConfigEntry::Value( + cardinal_entry.push(ConfigEntry::Value( Path { names: vec![file.name(child).unwrap()], spans: Vec::new(), @@ -391,28 +370,20 @@ impl ConfigModule { config.clone(), )); } - child_entries.append(&mut self.serialize_rec_file(child, file, i)); - if child_entries.len() > 0 { + cardinal_entry.append(&mut self.serialize_rec_file(child, file, i)); + if cardinal_entry.len() > 0 { child_map .get_mut(&file.name(child).unwrap()) .and_then(|x| { - x.push(child_entries.clone()); + x.push(cardinal_entry.clone()); Some(()) }) .or_else(|| { child_map - .insert(file.name(child).unwrap(), vec![child_entries]); + .insert(file.name(child).unwrap(), vec![cardinal_entry]); Some(()) }); } - - // entries.push(ConfigEntry::Value( - // Path { - // names: vec![file.name(child).unwrap()], - // spans: Vec::new(), - // }, - // ConfigValue::Cardinality(child_entries) - // )); } None => (), } @@ -445,7 +416,6 @@ impl ConfigModule { )), )) } - info!("entries: {:?}", entries); return entries; } diff --git a/uvls/src/core/pipeline.rs b/uvls/src/core/pipeline.rs index 2d12e3c9..57b3aa6d 100644 --- a/uvls/src/core/pipeline.rs +++ b/uvls/src/core/pipeline.rs @@ -91,7 +91,6 @@ async fn draft_handler( } }; info!("started draft handler {uri}"); - info!("draft: {:?}" , draft); spawn(make_red_tree(draft.clone(), uri.clone(), tx_link.clone())); while let Some(msg) = rx.recv().await { match msg { diff --git a/uvls/src/smt.rs b/uvls/src/smt.rs index 2fd2a755..b5be00f8 100644 --- a/uvls/src/smt.rs +++ b/uvls/src/smt.rs @@ -598,8 +598,7 @@ pub async fn web_view_handler( .send(webview::UIAction::UpdateSMTModel(model, tag)) .await?; } - Err(e) => { - + Err(e) => { inlay_state.maybe_reset(inlay_source).await; tx_ui .send(webview::UIAction::UpdateSMTInvalid(format!("{e}"), tag)) diff --git a/uvls/src/smt/parse.rs b/uvls/src/smt/parse.rs index 52e8856a..ade59e4f 100644 --- a/uvls/src/smt/parse.rs +++ b/uvls/src/smt/parse.rs @@ -190,7 +190,7 @@ mod tests { assert_eq!(n, "test"); let (i,(_,ConfigValue::Bool(n))) = parser.parse(i).unwrap() else {panic!()}; assert_eq!(n, true); - let (i,(_,ConfigValue::Number(n))) = parser.parse(i).unwrap() else {panic!()}; + let (_i,(_,ConfigValue::Number(n))) = parser.parse(i).unwrap() else {panic!()}; assert_approx_eq!(n,1.0); } } diff --git a/uvls/src/smt/smt_lib.rs b/uvls/src/smt/smt_lib.rs index 2f81fcd7..c1f16dbc 100644 --- a/uvls/src/smt/smt_lib.rs +++ b/uvls/src/smt/smt_lib.rs @@ -426,7 +426,6 @@ impl Into for ConfigValue { Self::Number(n) => Expr::Real(n), Self::String(s) => Expr::String(s), Self::Cardinality(_) => Expr::Bool(true), - _ => unimplemented!() } } } @@ -752,4 +751,4 @@ fn translate_expr(decl: &ast::ExprDecl, m: InstanceID, builder: &mut SMTBuilder) Type::Real, ), } -} +} \ No newline at end of file diff --git a/uvls/src/webview.rs b/uvls/src/webview.rs index d7a3bb8f..d465662b 100644 --- a/uvls/src/webview.rs +++ b/uvls/src/webview.rs @@ -212,7 +212,6 @@ fn create_file_tree( config: &HashMap, entries: &mut IndexMap, ) { - info!("config_web{:?}", config); let mut last = Symbol::Root; let mut vdir = 0; file.visit_children_depth(Symbol::Root, true, |sym, depth| match sym { @@ -265,7 +264,7 @@ fn create_file_tree( let ms = instance.sym(sym); let config = config.get(&ms).cloned(); - // info!("Config Check. MS:{:?}, config: :{:?}", ms, config); + entries.insert( ms, UIEntry { @@ -305,7 +304,6 @@ fn create_file_tree( }, }, ); - // info!("entries: {:?}:", entries); last = sym; true } diff --git a/uvls/src/webview/frontend.rs b/uvls/src/webview/frontend.rs index 47faa943..fe05e9b0 100644 --- a/uvls/src/webview/frontend.rs +++ b/uvls/src/webview/frontend.rs @@ -197,9 +197,7 @@ fn ConfigInput<'a>(cx: Scope<'a, ConfigInputProps<'a>>) -> Element { }, _ => rsx!{ div { config.to_string() - } - - }, + }}, }; cx.render(rsx! { div{ From ab1b483fef5428da09c58fcb2ae06497490e0679 Mon Sep 17 00:00:00 2001 From: pascalfoerster Date: Wed, 5 Jul 2023 17:21:57 +0200 Subject: [PATCH 16/17] fix attributes --- uvls/src/core/ast.rs | 26 +++++++++++++---- uvls/src/core/ast/transform.rs | 19 ++++++------ uvls/src/core/module.rs | 53 ++++++++++++++++++++-------------- 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/uvls/src/core/ast.rs b/uvls/src/core/ast.rs index 6d6fc73f..59f1e905 100644 --- a/uvls/src/core/ast.rs +++ b/uvls/src/core/ast.rs @@ -1,6 +1,7 @@ use crate::core::*; use check::ErrorInfo; use hashbrown::HashMap; +use itertools::Itertools; use ropey::Rope; use semantic::FileID; use std::hash::Hash; @@ -11,9 +12,9 @@ use tree_sitter::Tree; use ustr::Ustr; use util::lsp_range; mod def; +pub mod graph; mod transform; mod visitor; -pub mod graph; pub use def::*; pub use visitor::*; //Easy to work with AST parsing and util. @@ -176,10 +177,10 @@ impl Ast { fn all_features(&self) -> impl Iterator { (0..self.features.len()).map(Symbol::Feature) } - fn get_feature(&self, index: usize) -> Option<&Feature>{ + fn get_feature(&self, index: usize) -> Option<&Feature> { self.features.get(index) } - fn get_attribute(&self, index: usize) -> Option<&Attribute>{ + fn get_attribute(&self, index: usize) -> Option<&Attribute> { self.attributes.get(index) } fn all_attributes(&self) -> impl Iterator { @@ -248,9 +249,12 @@ impl AstDocument { pub fn all_features(&self) -> impl Iterator { self.ast.all_features() } - pub fn get_feature(&self,index: usize) -> Option<&Feature>{ + pub fn get_feature(&self, index: usize) -> Option<&Feature> { self.ast.get_feature(index) } + pub fn get_attribute(&self, index: usize) -> Option<&Attribute> { + self.ast.get_attribute(index) + } pub fn all_attributes(&self) -> impl Iterator { self.ast.all_attributes() } @@ -403,13 +407,23 @@ impl AstDocument { }) } // returns all Symbols with same name, used for cardinality resolving - pub fn get_all_entities(&self,path: &[Ustr]) -> Vec{ + pub fn get_all_entities(&self, path: &[Ustr]) -> Vec { + let ustr_path = Ustr::from(path.iter().map(|s| s.to_string()).join(".").as_str()); let mut res = vec![]; for i in 0..self.ast.features.len() { - if path.last().unwrap_or(&Ustr::from("")).clone() == self.get_feature(i).unwrap().name.name{ + if ustr_path == self.get_feature(i).unwrap().name.name { res.push(Symbol::Feature(i)); } } + let mut path: Vec = path.iter().cloned().collect(); + if let Some(name) = path.pop() { + let features = self.get_all_entities(&path); + for i in features { + if let Some(sym) = self.ast.index.get(&(i, name, SymbolKind::Attribute)) { + res.push(*sym); + } + } + } res } //prefix of sym from root diff --git a/uvls/src/core/ast/transform.rs b/uvls/src/core/ast/transform.rs index 10f94543..cc41c3c1 100644 --- a/uvls/src/core/ast/transform.rs +++ b/uvls/src/core/ast/transform.rs @@ -102,9 +102,9 @@ impl<'a> VisitorState<'a> { // removes duplicate feature error for cardinality if !self.ast.get_feature(i).unwrap().duplicate { if let Some(old) = self - .ast - .index - .insert((Symbol::Root, name, SymbolKind::Feature), node) + .ast + .index + .insert((Symbol::Root, name, SymbolKind::Feature), node) { self.errors.push(ErrorInfo { location: self.ast.lsp_range(node, self.source).unwrap(), @@ -123,12 +123,11 @@ impl<'a> VisitorState<'a> { node } Symbol::Attribute(i) => { - if !self.ast.get_attribute(i).unwrap().duplicate { - if let Some(old) = self - .ast - .index - .insert((scope, name, SymbolKind::Attribute), node) - { + if let Some(old) = self + .ast + .index + .insert((scope, name, SymbolKind::Attribute), node) + { self.errors.push(ErrorInfo { location: self.ast.lsp_range(node, self.source).unwrap(), severity: DiagnosticSeverity::ERROR, @@ -141,7 +140,7 @@ impl<'a> VisitorState<'a> { weight: 20, msg: "duplicate attribute".to_string(), }); - }; + } self.ast.attributes[i].depth = depth; node diff --git a/uvls/src/core/module.rs b/uvls/src/core/module.rs index d73c978e..fbfc29d8 100644 --- a/uvls/src/core/module.rs +++ b/uvls/src/core/module.rs @@ -221,17 +221,36 @@ impl Module { out.insert(ModuleSymbol { instance, sym }, val.clone()); out_span.insert(ModuleSymbol { instance, sym }, path.range()); } else { - if let Symbol::Feature(i) = sym { - let feature = file.get_feature(i).unwrap().clone(); - if let Cardinality::Range(_, _) = - feature.cardinality.unwrap() - { + match sym { + Symbol::Feature(i) => { + let feature = file.get_feature(i).unwrap().clone(); + if let Cardinality::Range(_, _) = + feature.cardinality.unwrap() + { + out.insert(ModuleSymbol { instance, sym }, val.clone()); + out_span.insert( + ModuleSymbol { instance, sym }, + path.range(), + ); + } else { + err( + path.range(), + format!( + "expected {} got {}", + file.type_of(sym).unwrap(), + val.ty() + ), + ); + } + } + Symbol::Attribute(i) => { out.insert(ModuleSymbol { instance, sym }, val.clone()); - out_span.insert( - ModuleSymbol { instance, sym }, - path.range(), - ); - } else { + out_span.insert( + ModuleSymbol { instance, sym }, + path.range(), + ); + } + _ => { err( path.range(), format!( @@ -241,16 +260,8 @@ impl Module { ), ); } - } else { - err( - path.range(), - format!( - "expected {} got {}", - file.type_of(sym).unwrap(), - val.ty() - ), - ); - } + } + } } else { err(path.range(), format!("unresolved value",)); @@ -392,7 +403,7 @@ impl ConfigModule { if let Some(config) = self.values.get(&i.sym(child)) { entries.push(ConfigEntry::Value( Path { - names: vec![file.name(child).unwrap()], + names: vec![file.name(sym).unwrap(),file.name(child).unwrap()], spans: Vec::new(), }, config.clone(), From 5fb7bcb52ae49357e24597fc32e8686adeb864bb Mon Sep 17 00:00:00 2001 From: Felix Date: Tue, 11 Jul 2023 12:40:56 +0200 Subject: [PATCH 17/17] fix: remove Warning --- uvls/src/core/module.rs | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/uvls/src/core/module.rs b/uvls/src/core/module.rs index fbfc29d8..c66d3b43 100644 --- a/uvls/src/core/module.rs +++ b/uvls/src/core/module.rs @@ -1,10 +1,10 @@ -use tokio::time::Instant; use crate::core::*; -use resolve; use config::*; use hashbrown::HashMap; use indexmap::IndexSet; use log::info; +use resolve; +use tokio::time::Instant; use ustr::Ustr; use std::sync::Arc; @@ -189,7 +189,7 @@ impl Module { ConfigEntry::Value(path, val) => match val { ConfigValue::Cardinality(cardinality) => match cardinality { CardinalityEntry::CardinalityLvl(cardinality_lvl) => { - let entries = file.get_all_entities(&path.names.clone()); + let entries = file.get_all_entities(&path.names.clone()); let entries = entries.iter().nth(offset); match entries { Some(Symbol::Feature(id)) => { @@ -215,7 +215,9 @@ impl Module { } }, _ => { - if let Some(sym_ref) = file.get_all_entities(&path.names).iter().nth(offset) { + if let Some(sym_ref) = + file.get_all_entities(&path.names).iter().nth(offset) + { let sym = sym_ref.clone(); if file.type_of(sym).unwrap() == val.ty() { out.insert(ModuleSymbol { instance, sym }, val.clone()); @@ -227,7 +229,10 @@ impl Module { if let Cardinality::Range(_, _) = feature.cardinality.unwrap() { - out.insert(ModuleSymbol { instance, sym }, val.clone()); + out.insert( + ModuleSymbol { instance, sym }, + val.clone(), + ); out_span.insert( ModuleSymbol { instance, sym }, path.range(), @@ -242,13 +247,13 @@ impl Module { ), ); } - } - Symbol::Attribute(i) => { + } + Symbol::Attribute(_) => { out.insert(ModuleSymbol { instance, sym }, val.clone()); - out_span.insert( - ModuleSymbol { instance, sym }, - path.range(), - ); + out_span.insert( + ModuleSymbol { instance, sym }, + path.range(), + ); } _ => { err( @@ -260,8 +265,7 @@ impl Module { ), ); } - } - + } } } else { err(path.range(), format!("unresolved value",)); @@ -390,8 +394,10 @@ impl ConfigModule { Some(()) }) .or_else(|| { - child_map - .insert(file.name(child).unwrap(), vec![cardinal_entry]); + child_map.insert( + file.name(child).unwrap(), + vec![cardinal_entry], + ); Some(()) }); } @@ -403,7 +409,7 @@ impl ConfigModule { if let Some(config) = self.values.get(&i.sym(child)) { entries.push(ConfigEntry::Value( Path { - names: vec![file.name(sym).unwrap(),file.name(child).unwrap()], + names: vec![file.name(sym).unwrap(), file.name(child).unwrap()], spans: Vec::new(), }, config.clone(),