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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/rust.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Build
run: cargo build --verbose --workspace
run: cargo build --verbose --workspace --locked
- name: Run tests
run: cargo test --verbose --workspace
run: cargo test --verbose --workspace --locked

- name: generate bindings and ensure clean
run: cargo run --package buildtools --bin generate --all-features
Expand All @@ -25,7 +25,7 @@ jobs:
with:
node-version: "22"

- run: yarn install && cargo install wasm-pack
- run: yarn install && cargo install --locked wasm-pack
- run: yarn workspace logisheets-web build
- run: yarn run run-scripts && yarn run wasm
- run: yarn build
Expand Down
12 changes: 11 additions & 1 deletion crates/controller/base/src/traits/block_ref.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{BlockCellId, SheetId};
use crate::{BlockCellId, BlockId, SheetId};

pub trait BlockRefTrait {
fn get_all_keys(&self, ref_name: &str) -> Vec<(String, SheetId, BlockCellId)>;
Expand All @@ -9,4 +9,14 @@ pub trait BlockRefTrait {
key: &String,
field: &String,
) -> Option<(SheetId, BlockCellId)>;

fn get_all_keys_by_block(&self, sheet_id: SheetId, block_id: BlockId) -> Vec<(String, SheetId, BlockCellId)>;
fn get_all_fields_by_block(&self, sheet_id: SheetId, block_id: BlockId) -> Vec<String>;
fn resolve_by_block(
&self,
sheet_id: SheetId,
block_id: BlockId,
key: &String,
field: &String,
) -> Option<(SheetId, BlockCellId)>;
}
20 changes: 14 additions & 6 deletions crates/controller/src/block_manager/schema_manager/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,34 @@ impl BlockSchemaExecutor {
.enumerate()
{
let idx = i + p.field_from;
// RowSchema (p.row=true) stores ColId per field — fields
// run along columns, records along rows. ColSchema flips
// both. We fetch from the *records* dimension at index 0
// and take the *fields* dimension's id at idx, so the
// bind only needs the block to extend `idx` cells along
// the fields axis. Existing buggy behavior swapped these
// and accidentally worked for square blocks because
// RowId and ColId share the u32 representation.
let id = if p.row {
ctx.fetch_block_cell_id(&sheet_id, &block_id, idx, 0)?.row
} else {
ctx.fetch_block_cell_id(&sheet_id, &block_id, 0, idx)?.col
} else {
ctx.fetch_block_cell_id(&sheet_id, &block_id, idx, 0)?.row
};
fields.push((field, (id, render_id)));
}
let schema = if p.row {
let key = ctx
.fetch_block_cell_id(&sheet_id, &block_id, p.key_idx, 0)?
.row;
.fetch_block_cell_id(&sheet_id, &block_id, 0, p.key_idx)?
.col;
Schema::RowSchema(RowSchema {
fields,
key,
name: p.ref_name.clone(),
})
} else {
let key = ctx
.fetch_block_cell_id(&sheet_id, &block_id, 0, p.key_idx)?
.col;
.fetch_block_cell_id(&sheet_id, &block_id, p.key_idx, 0)?
.row;
Schema::ColSchema(ColSchema {
fields,
key,
Expand Down
28 changes: 27 additions & 1 deletion crates/controller/src/block_manager/schema_manager/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,36 @@ impl SchemaManager {
#[inline]
pub fn get_all_fields(&self, ref_name: &str) -> Option<Vec<Field>> {
let (sheet_id, block_id) = self.refs.get(ref_name)?;
let schema = self.schemas.get(&(*sheet_id, *block_id))?;
self.get_all_fields_by_block(*sheet_id, *block_id)
}

#[inline]
pub fn get_all_fields_by_block(&self, sheet_id: SheetId, block_id: BlockId) -> Option<Vec<Field>> {
let schema = self.schemas.get(&(sheet_id, block_id))?;
Some(schema.get_all_fields())
}

pub fn get_all_key_cell_ids_by_block<'a>(
&'a self,
sheet_id: SheetId,
block_id: BlockId,
bp: &'a BlockPlace,
) -> Option<Vec<BlockCellId>> {
let schema = self.schemas.get(&(sheet_id, block_id))?;
Some(schema.get_all_key_cell_ids(block_id, bp))
}

pub fn partially_resolve_by_block(
&self,
sheet_id: SheetId,
block_id: BlockId,
key: BlockCellId,
field: &String,
) -> Option<BlockCellId> {
let schema = self.schemas.get(&(sheet_id, block_id))?;
schema.partially_resolve(key, field)
}

#[inline]
pub fn get_render_id(&self, sheet_id: &SheetId, cell_id: &BlockCellId) -> Option<RenderId> {
let schema = self.schemas.get(&(*sheet_id, cell_id.block_id))?;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use logisheets_base::{BlockId, SheetId};
use logisheets_parser::ast;

use crate::calc_engine::{
Expand All @@ -17,7 +18,30 @@ where
assert_text_from_calc_value!(key, key);
let field = fetcher.get_calc_value(args_iter.next().unwrap());
assert_text_from_calc_value!(field, field);
let result = fetcher.resolve(&ref_name, &key, &field);
calc_by_ref_name(fetcher, &ref_name, key, field)
}

pub(crate) fn calc_by_ref_name<C>(fetcher: &mut C, ref_name: &str, key: String, field: String) -> CalcVertex
where
C: Connector,
{
let result = fetcher.resolve(ref_name, &key, &field);
if result.is_none() {
return CalcVertex::from_error(ast::Error::Value);
}
let (sheet_id, cell_id) = result.unwrap();
let value = fetcher.get_block_cell_value(sheet_id, cell_id);
match value {
Some(value) => CalcVertex::Value(value),
None => CalcVertex::from_error(ast::Error::Value),
}
}

pub(crate) fn calc_by_block<C>(fetcher: &mut C, sheet_id: SheetId, block_id: BlockId, key: String, field: String) -> CalcVertex
where
C: Connector,
{
let result = fetcher.resolve_by_block(sheet_id, block_id, &key, &field);
if result.is_none() {
return CalcVertex::from_error(ast::Error::Value);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use logisheets_parser::ast;

use crate::calc_engine::{
calculator::calc_vertex::{CalcVertex, CalcValue, Value},
connector::Connector,
};

use super::blockref::calc_by_block;

pub fn calc<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
where
C: Connector,
{
assert_or_return!(args.len() == 4, ast::Error::Unspecified);
let mut args_iter = args.into_iter();
let sheet_id = fetcher.get_calc_value(args_iter.next().unwrap());
assert_f64_from_calc_value!(sheet_id, sheet_id);
let block_id = fetcher.get_calc_value(args_iter.next().unwrap());
assert_f64_from_calc_value!(block_id, block_id);
let key = fetcher.get_calc_value(args_iter.next().unwrap());
assert_text_from_calc_value!(key, key);
let field = fetcher.get_calc_value(args_iter.next().unwrap());
assert_text_from_calc_value!(field, field);
let sheet_id = sheet_id as u16;
let block_id = block_id as usize;
calc_by_block(fetcher, sheet_id, block_id, key, field)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,45 +20,69 @@ where

let key_condition = fetcher.get_calc_value(args_iter.next().unwrap());
assert_text_from_calc_value!(key_condition, key_condition);
let key_condigtion =
parse_condition(&key_condition).ok_or(CalcVertex::from_error(ast::Error::Unspecified));
if let Err(e) = key_condigtion {
return e;
}
let key_condigtion = key_condigtion.unwrap();
let field_condition = fetcher.get_calc_value(args_iter.next().unwrap());
assert_text_from_calc_value!(field_condition, field_condition);

let keys = fetcher
.get_all_keys(&ref_name)
.into_iter()
.map(|(t, _, _)| Value::Text(t));
let fields = fetcher.get_all_fields(&ref_name).into_iter();

calc_matrix(
fetcher,
keys,
fields,
key_condition,
field_condition,
|fetcher, key, field| fetcher.resolve(&ref_name, key, field),
)
}

pub(crate) fn calc_matrix<C, IKeys, IFields, F>(
fetcher: &mut C,
keys: IKeys,
fields: IFields,
key_condition_str: String,
field_condition_str: String,
resolve: F,
) -> CalcVertex
where
C: Connector,
IKeys: Iterator<Item = Value>,
IFields: Iterator<Item = String>,
F: Fn(
&mut C,
&String,
&String,
) -> Option<(logisheets_base::SheetId, logisheets_base::BlockCellId)>,
{
let key_condition =
parse_condition(&key_condition_str).ok_or(CalcVertex::from_error(ast::Error::Unspecified));
if let Err(e) = key_condition {
return e;
}
let key_condition = key_condition.unwrap();
let key_values = keys
.into_iter()
.filter(|key| match_condition(&key_condigtion, key))
.filter(|key| match_condition(&key_condition, key))
.collect::<Vec<_>>();

let field_condition = fetcher.get_calc_value(args_iter.next().unwrap());
assert_text_from_calc_value!(field_condition, field_condition);
let field_condigtion =
parse_condition(&field_condition).ok_or(CalcVertex::from_error(ast::Error::Unspecified));
if let Err(e) = field_condigtion {
let field_condition = parse_condition(&field_condition_str)
.ok_or(CalcVertex::from_error(ast::Error::Unspecified));
if let Err(e) = field_condition {
return e;
}
let field_condigtion = field_condigtion.unwrap();
let fields = fetcher
.get_all_fields(&ref_name)
.into_iter()
.map(|t| Value::Text(t));
let field_condition = field_condition.unwrap();
let field_values = fields
.into_iter()
.filter(|field| match_condition(&field_condigtion, field))
.filter(|field| match_condition(&field_condition, &Value::Text(field.clone())))
.collect::<Vec<_>>();

let mut result = vec![];
for k in key_values.into_iter() {
let key = k.assert_text();
let mut values = vec![];
for f in field_values.iter() {
let field = f.assert_text_ptr();
let v = fetcher.resolve(&ref_name, &key, field);
let v = resolve(fetcher, &key, f);
if let Some((sheet_id, cell_id)) = v {
let value = fetcher.get_block_cell_value(sheet_id, cell_id);
if let Some(value) = value {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use logisheets_parser::ast;

use crate::calc_engine::{
calculator::calc_vertex::{CalcVertex, CalcValue, Value},
connector::Connector,
};

use super::blockrefs::calc_matrix;

pub fn calc<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
where
C: Connector,
{
assert_or_return!(args.len() == 4, ast::Error::Unspecified);
let mut args_iter = args.into_iter();
let sheet_id = fetcher.get_calc_value(args_iter.next().unwrap());
assert_f64_from_calc_value!(sheet_id, sheet_id);
let block_id = fetcher.get_calc_value(args_iter.next().unwrap());
assert_f64_from_calc_value!(block_id, block_id);
let key_condition = fetcher.get_calc_value(args_iter.next().unwrap());
assert_text_from_calc_value!(key_condition, key_condition);
let field_condition = fetcher.get_calc_value(args_iter.next().unwrap());
assert_text_from_calc_value!(field_condition, field_condition);

let sheet_id = sheet_id as u16;
let block_id = block_id as usize;

let keys = fetcher
.get_all_keys_by_block(sheet_id, block_id)
.into_iter()
.map(|(t, _, _)| Value::Text(t));
let fields = fetcher
.get_all_fields_by_block(sheet_id, block_id)
.into_iter()
.map(|t| t);

calc_matrix(
fetcher,
keys,
fields,
key_condition,
field_condition,
|fetcher, key, field| fetcher.resolve_by_block(sheet_id, block_id, key, field),
)
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod blockref;
pub mod blockrefb;
pub mod blockrefs;
pub mod blockrefsb;
2 changes: 2 additions & 0 deletions crates/controller/src/calc_engine/calculator/funcs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ where
"BITRSHIFT" => bits::bit::calc_bitrshift(args, fetcher),
"BITXOR" => bits::bit::calc_bitxor(args, fetcher),
"BLOCKREF" => blocks::blockref::calc(args, fetcher),
"BLOCKREFB" => blocks::blockrefb::calc(args, fetcher),
"BLOCKREFS" => blocks::blockrefs::calc(args, fetcher),
"BLOCKREFSB" => blocks::blockrefsb::calc(args, fetcher),
"CHISQ.DIST" => distribution::chisqdist::calc_chisqdist(args, fetcher),
"CHISQ.DIST.RT" => distribution::chisqdist::calc_chisqdist_rt(args, fetcher),
"CHOOSE" => choose::calc(args, fetcher),
Expand Down
18 changes: 18 additions & 0 deletions crates/controller/src/calc_engine/calculator/funcs/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,24 @@ pub mod tests_utils {
) -> Option<(SheetId, logisheets_base::BlockCellId)> {
unreachable!()
}

fn get_all_keys_by_block(&self, _sheet_id: SheetId, _block_id: logisheets_base::BlockId) -> Vec<(String, SheetId, BlockCellId)> {
unreachable!()
}

fn get_all_fields_by_block(&self, _sheet_id: SheetId, _block_id: logisheets_base::BlockId) -> Vec<String> {
unreachable!()
}

fn resolve_by_block(
&self,
_sheet_id: SheetId,
_block_id: logisheets_base::BlockId,
_key: &String,
_field: &String,
) -> Option<(SheetId, logisheets_base::BlockCellId)> {
unreachable!()
}
}

impl Connector for TestFetcher {
Expand Down
Loading
Loading