Skip to content
This repository has been archived by the owner on Dec 28, 2021. It is now read-only.

Argument Names in the Span Tree #781

Merged
merged 38 commits into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1a98504
[wip] A new kind of an empty node placeholder that represents known f…
mwu-tow Aug 27, 2020
1303f7e
This looks like trouble.
mwu-tow Aug 27, 2020
c0f51ec
mostly just moving stuff around
mwu-tow Aug 28, 2020
d68fef8
propagating the context, not adding append placeholders for prefix in…
mwu-tow Aug 28, 2020
96a12c1
[wip]
mwu-tow Sep 1, 2020
eadd317
[wip]
mwu-tow Sep 1, 2020
6524415
[wip]
mwu-tow Sep 2, 2020
102e816
tests, fixes, some cleanups
mwu-tow Sep 4, 2020
ee84e6d
cleanups, refactorings, setting up more test
mwu-tow Sep 4, 2020
c1f089d
more tests and fixes
mwu-tow Sep 4, 2020
dd65848
bump size, mark tests as wasm
mwu-tow Sep 4, 2020
787d6ba
cleanups & fixes
mwu-tow Sep 5, 2020
359c1ce
restored missing method
mwu-tow Sep 6, 2020
376a97f
bad ideas
mwu-tow Sep 7, 2020
9f3a04d
now hidden
mwu-tow Sep 7, 2020
c92fa61
[wip]
mwu-tow Sep 7, 2020
cd7ca76
support for method notation and other fixes / improvements
mwu-tow Sep 9, 2020
9e7bc72
this and that
mwu-tow Sep 9, 2020
6bbd07c
cr feedback
mwu-tow Sep 9, 2020
bcded97
notifications
mwu-tow Sep 9, 2020
9ea9fc6
Merge remote-tracking branch 'remotes/origin/main' into wip/mwu/arg-n…
mwu-tow Sep 10, 2020
a001211
wasm
mwu-tow Sep 10, 2020
ecd670b
cleanups
mwu-tow Sep 10, 2020
18f3676
minor
mwu-tow Sep 10, 2020
47b3204
fix / cleanups
mwu-tow Sep 10, 2020
365690e
follow up fix
mwu-tow Sep 10, 2020
9a8e5be
Update src/rust/ide/src/controller/module.rs
mwu-tow Sep 10, 2020
9c49635
Update src/rust/ide/src/model/project.rs
mwu-tow Sep 10, 2020
f12d861
Update src/rust/ide/src/controller/module.rs
mwu-tow Sep 10, 2020
b9d2a03
cr feedback
mwu-tow Sep 10, 2020
1ab6d33
fixed tests
mwu-tow Sep 10, 2020
6916484
Merge branch 'wip/mwu/arg-names' of https://github.com/luna/basegl in…
mwu-tow Sep 10, 2020
c3208b3
note, wasm test
mwu-tow Sep 10, 2020
8f8e251
Update span trees even if expression wasn't changed.
mwu-tow Sep 11, 2020
d5b3d44
Merge branch 'main' into wip/mwu/arg-names
mwu-tow Sep 11, 2020
bfee177
fixing the shaky test
mwu-tow Sep 11, 2020
5d42397
clippy
mwu-tow Sep 11, 2020
b912a2f
Merge branch 'main' into wip/mwu/arg-names
mwu-tow Sep 11, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/rust/ide/lib/ast/impl/src/opr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,16 +343,16 @@ impl Chain {
(infix.name() == operator).as_some_from(|| infix.flatten())
}

/// Iterates over &Located<Ast>, beginning with target (this argument) and then subsequent
/// Iterates over operands beginning with target (this argument) and then subsequent
/// arguments.
pub fn enumerate_operands<'a>
(&'a self) -> impl Iterator<Item=Located<&'a ArgWithOffset<Ast>>> + 'a {
(&'a self) -> impl Iterator<Item=Option<Located<&'a ArgWithOffset<Ast>>>> + 'a {
let rev_args = self.args.iter().rev();
let target_crumbs = rev_args.map(ChainElement::crumb_to_previous).collect_vec();
let target = self.target.as_ref();
let loc_target = target.map(|opr| Located::new(target_crumbs,opr)).into_iter();
let loc_target = std::iter::once(target.map(|opr| Located::new(target_crumbs,opr)));
let args = self.args.iter().enumerate();
let loc_args = args.filter_map(move |(i,elem)| {
let loc_args = args.map(move |(i,elem)| {
elem.operand.as_ref().map(|operand| {
let latter_args = self.args.iter().skip(i+1);
let to_infix = latter_args.rev().map(ChainElement::crumb_to_previous);
Expand All @@ -364,6 +364,14 @@ impl Chain {
loc_target.chain(loc_args)
}


/// Iterates over non-empty operands beginning with target (this argument) and then subsequent
/// arguments.
pub fn enumerate_non_empty_operands<'a>
(&'a self) -> impl Iterator<Item=Located<&'a ArgWithOffset<Ast>>> + 'a {
self.enumerate_operands().flatten()
}

/// Iterates over all operator's AST in this chain, starting from target side.
pub fn enumerate_operators<'a>(&'a self) -> impl Iterator<Item=Located<&'a known::Opr>> + 'a {
self.args.iter().enumerate().map(move |(i,elem)| {
Expand Down Expand Up @@ -522,8 +530,8 @@ mod tests {
}

fn test_enumerating(chain:&Chain, root_ast:&Ast, expected_asts:&[&Ast]) {
assert_eq!(chain.enumerate_operands().count(), expected_asts.len());
for (elem,expected) in chain.enumerate_operands().zip(expected_asts) {
assert_eq!(chain.enumerate_non_empty_operands().count(), expected_asts.len());
for (elem,expected) in chain.enumerate_non_empty_operands().zip(expected_asts) {
assert_eq!(elem.item.arg,**expected);
let ast = root_ast.get_traversing(&elem.crumbs).unwrap();
assert_eq!(ast,*expected);
Expand Down
69 changes: 69 additions & 0 deletions src/rust/ide/lib/ast/impl/src/prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,22 @@ pub struct Argument {
pub prefix_id : Option<Id>,
}

impl Argument {
/// Make an argument consisting of a single blank placeholder: `_`.
pub fn new_blank(offset:usize, prefix_id:Option<Id>) -> Self {
let sast = Shifted::new(offset,Ast::blank());
Self {sast,prefix_id}
}
}

impl HasTokens for Argument {
fn feed_to(&self, consumer: &mut impl TokenConsumer) {
self.sast.feed_to(consumer)
}
}



// ====================
// === Prefix Chain ===
// ====================
Expand Down Expand Up @@ -156,6 +166,27 @@ impl Chain {
}
self.func
}

/// Get the ID of the Ast represented by this chain.
pub fn id(&self) -> Option<Id> {
match self.args.last() {
Some(last_arg) => last_arg.prefix_id,
None => self.func.id,
}
}

/// Insert argument at given position in the prefix chain. If index is out of bounds,
/// additional blank `_` arguments will be placed.
pub fn insert_arg(&mut self, index:usize, argument:Argument) {
if let Some(blanks_to_add) = index.checked_sub(self.args.len()) {
let make_blank = || {
let prefix_id = argument.prefix_id.map(|_| Id::new_v4());
Argument::new_blank(argument.sast.off,prefix_id)
};
self.args.extend(std::iter::repeat_with(make_blank).take(blanks_to_add));
}
self.args.insert(index,argument);
}
}

impl HasTokens for Chain {
Expand Down Expand Up @@ -209,5 +240,43 @@ mod tests {
assert_eq!(chain.into_ast().repr(), "a b c");
}

#[test]
fn inserting_arg() {
let a = Ast::var("a");
let b = Ast::var("b");
let c = Ast::var("c");
let chain = Chain::new(a,vec![b,c]);
assert_eq!(chain.repr(), "a b c");

let arg = |text:&str| Argument {
prefix_id : None,
sast : Shifted::new(1,Ast::var(text)),
};

{
let mut chain = chain.clone();
chain.insert_arg(0, arg("arg"));
assert_eq!(chain.repr(), "a arg b c");
}

{
let mut chain = chain.clone();
chain.insert_arg(2, arg("arg"));
assert_eq!(chain.repr(), "a b c arg");
}

{
let mut chain = chain.clone();
chain.insert_arg(3, arg("arg"));
assert_eq!(chain.repr(), "a b c _ arg");
}

{
let mut chain = chain.clone();
chain.insert_arg(4, arg("arg"));
assert_eq!(chain.repr(), "a b c _ _ arg");
}
}

// TODO[ao] add tests for modifying chain.
}
10 changes: 10 additions & 0 deletions src/rust/ide/lib/enso-protocol/src/language_server/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,4 +656,14 @@ pub mod test {
method_pointer : None,
}
}

/// Generate `ExpressionValueUpdate` with update for a single expression bringing only the
/// method pointer.
pub fn value_update_with_method_ptr(id:ExpressionId, method_pointer:SuggestionId) -> ExpressionValueUpdate {
ExpressionValueUpdate {
expression_id : id,
typename : None,
method_pointer : Some(method_pointer),
}
}
}
21 changes: 21 additions & 0 deletions src/rust/ide/lib/parser/tests/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ fn assert_opr<StringLike:Into<String>>(ast:&Ast, name:StringLike) {
assert_eq!(*actual,expected);
}

fn roundtrip_program(program:&str) {
let parser = parser::Parser::new_or_panic();
let ast = parser.parse(program.to_string(), Default::default()).unwrap();
assert_eq!(ast.repr(), program, "{:#?}", ast);
}



// ===============
Expand Down Expand Up @@ -436,3 +442,18 @@ impl Fixture {
fn parser_tests() {
Fixture::new().run()
}

/// Test case for https://github.com/enso-org/ide/issues/296
#[wasm_bindgen_test]
fn block_roundtrip() {
let programs = vec![
"main = 10 + 10",
"main =\n a = 10\n b = 20\n a * b",
"main =\n foo a =\n a * 10\n foo 10\n print \"hello\"",
"main =\n foo\n \n bar",
"main =\n \n foo\n \n bar"
];
for program in programs {
roundtrip_program(program);
}
}
50 changes: 43 additions & 7 deletions src/rust/ide/lib/span-tree/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use ast::crumbs::*;
use ast::opr::ArgWithOffset;



/// ==============
/// === Errors ===
/// ==============
Expand Down Expand Up @@ -126,6 +127,8 @@ impl<'a> Implementation for node::Ref<'a> {
BeforeTarget | AfterTarget => infix.target = Some(item),
Append if has_arg => infix.push_operand(item),
Append => *last_arg = Some(item),
// TODO? below should never happen, as operator arity is always fixed to 2?
ExpectedArgument(i) => infix.insert_operand(*i, item),
};
infix.into_ast()
} else {
Expand All @@ -135,9 +138,10 @@ impl<'a> Implementation for node::Ref<'a> {
prefix_id : None,
};
match ins_type {
BeforeTarget => prefix.args.insert(0,item),
AfterTarget => prefix.args.insert(1,item),
Append => prefix.args.push(item),
BeforeTarget => prefix.insert_arg(0,item),
AfterTarget => prefix.insert_arg(1,item),
Append => prefix.args.push(item),
ExpectedArgument(i) => prefix.insert_arg(*i, item),
}
prefix.into_ast()
};
Expand Down Expand Up @@ -197,12 +201,18 @@ mod test {

use Action::*;

use wasm_bindgen_test::wasm_bindgen_test;
use parser::Parser;
use crate::builder::TreeBuilder;
use crate::generate::context;
use crate::node::Kind::Operation;
use crate::node::Kind::Target;
use crate::node::InsertType::ExpectedArgument;

use ast::HasRepr;
use data::text::Index;
use data::text::Span;
use std::ops::Range;
use parser::Parser;
use wasm_bindgen_test::wasm_bindgen_test;

#[wasm_bindgen_test]
fn actions_in_span_tree() {
Expand All @@ -217,7 +227,7 @@ mod test {
impl Case {
fn run(&self, parser:&Parser) {
let ast = parser.parse_line(self.expr).unwrap();
let tree = ast.generate_tree().unwrap();
let tree = ast.generate_tree(&context::Empty).unwrap();
let span_begin = Index::new(self.span.start);
let span_end = Index::new(self.span.end);
let span = Span::from_indices(span_begin,span_end);
Expand Down Expand Up @@ -299,7 +309,7 @@ mod test {
impl Case {
fn run(&self, parser:&Parser) {
let ast = parser.parse_line(self.expr).unwrap();
let tree = ast.generate_tree().unwrap();
let tree = ast.generate_tree(&context::Empty).unwrap();
let span_begin = Index::new(self.span.start);
let span_end = Index::new(self.span.end);
let span = Span::from_indices(span_begin,span_end);
Expand Down Expand Up @@ -345,4 +355,30 @@ mod test {
let parser = Parser::new_or_panic();
for case in cases { case.run(&parser); }
}

#[test]
fn setting_positional_arguments() {
// Consider Span Tree for `foo bar` where `foo` is a method known to take 3 parameters.
// We can try setting each of 3 arguments to `baz`.
let is_removable = false;
let tree = TreeBuilder::new(7)
.add_leaf(0,3,Operation ,PrefixCrumb::Func)
.add_leaf(4,7,Target{is_removable},PrefixCrumb::Arg)
.add_empty_child(7, ExpectedArgument(1))
.add_empty_child(7, ExpectedArgument(2))
.build();

let ast = Ast::prefix(Ast::var("foo"), Ast::var("bar"));
assert_eq!(ast.repr(),"foo bar");
let baz = Ast::var("baz");

let after = tree.root_ref().child(1).unwrap().set(&ast,baz.clone_ref()).unwrap();
assert_eq!(after.repr(),"foo baz");

let after = tree.root_ref().child(2).unwrap().set(&ast,baz.clone_ref()).unwrap();
assert_eq!(after.repr(),"foo bar baz");

let after = tree.root_ref().child(3).unwrap().set(&ast,baz.clone_ref()).unwrap();
assert_eq!(after.repr(),"foo bar _ baz");
}
}
2 changes: 2 additions & 0 deletions src/rust/ide/lib/span-tree/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub trait Builder : Sized {
size : Size::new(len),
children : vec![],
expression_id : None,
parameter_info: None,
};
let child = node::Child { node,
offset : Size::new(offset),
Expand Down Expand Up @@ -82,6 +83,7 @@ impl TreeBuilder {
size : Size::new(len),
children : vec![],
expression_id : None,
parameter_info: None,
}
}
}
Expand Down
Loading