feat: crates restructure (#22)

This commit is contained in:
Ivan Miletic
2023-04-24 20:28:27 +02:00
committed by GitHub
parent 307ba977dd
commit 062ee5df90
41 changed files with 85 additions and 192 deletions
+2 -5
View File
@@ -120,11 +120,8 @@ jobs:
- name: Login to Crates.IO
run: cargo login ${{ secrets.CRATES_TOKEN }}
- name: Publish Parser
run: cd core/parser && cargo publish
- name: Publish VM
run: cd core/vm && cargo publish
- name: Publish Expression
run: cd core/expression && cargo publish
- name: Publish Engine
run: cd core/engine && cargo publish
+4 -8
View File
@@ -11268,14 +11268,12 @@ var semver = __nccwpck_require__(1383);
var toml = __nccwpck_require__(4920);
;// CONCATENATED MODULE: ./src/cargo.ts
const versionRegex = /version = "[0-9]+\.[0-9]+\.[0-9]+"$/mi;
const vmDep = /zen-vm =.*$/mi;
const parserDep = /zen-parser =.*$/mi;
const versionRegex = /version = "[0-9]+\.[0-9]+\.[0-9]+"$/im;
const expressionDep = /zen-expression =.*$/im;
const updateCargoContents = (contents, { version }) => {
return contents
.replace(versionRegex, `version = "${version}"`)
.replace(parserDep, `zen-parser = { path = "../parser", version = "${version}" }`)
.replace(vmDep, `zen-vm = { path = "../vm", version = "${version}" }`);
.replace(expressionDep, `zen-expression = { path = "../expression", version = "${version}" }`);
};
const getCargoVersion = (contents) => {
var _a;
@@ -11310,9 +11308,7 @@ function run() {
const project = 'engine';
const projectsFolder = 'core';
const directory = yield promises_namespaceObject.readdir(external_path_.join(...[workspace, projectsFolder]), { withFileTypes: true });
const folders = directory
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name);
const folders = directory.filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
const cargoFilePath = external_path_.join(...[workspace, projectsFolder, project, 'Cargo.toml']);
const cargoFile = yield promises_namespaceObject.readFile(cargoFilePath, 'utf-8');
const currentVersion = getCargoVersion(cargoFile);
+8 -10
View File
@@ -1,21 +1,19 @@
import * as toml from "toml";
import * as toml from 'toml';
type UpdateCargoOptions = {
version: string;
}
};
const versionRegex = /version = "[0-9]+\.[0-9]+\.[0-9]+"$/mi;
const vmDep = /zen-vm =.*$/mi;
const parserDep = /zen-parser =.*$/mi;
const versionRegex = /version = "[0-9]+\.[0-9]+\.[0-9]+"$/im;
const expressionDep = /zen-expression =.*$/im;
export const updateCargoContents = (contents: string, {version}: UpdateCargoOptions): string => {
export const updateCargoContents = (contents: string, { version }: UpdateCargoOptions): string => {
return contents
.replace(versionRegex, `version = "${version}"`)
.replace(parserDep, `zen-parser = { path = "../parser", version = "${version}" }`)
.replace(vmDep, `zen-vm = { path = "../vm", version = "${version}" }`);
}
.replace(expressionDep, `zen-expression = { path = "../expression", version = "${version}" }`);
};
export const getCargoVersion = (contents: string): string => {
const t = toml.parse(contents);
return t?.package?.version;
}
};
+22 -23
View File
@@ -1,12 +1,12 @@
import {describe} from "node:test";
import {expect, test} from "@jest/globals";
import {getCargoVersion, updateCargoContents} from "./cargo";
import {inc, ReleaseType} from "semver";
import * as fs from "fs/promises";
import * as path from "path";
import { describe } from 'node:test';
import { expect, test } from '@jest/globals';
import { getCargoVersion, updateCargoContents } from './cargo';
import { inc, ReleaseType } from 'semver';
import * as fs from 'fs/promises';
import * as path from 'path';
// language=Toml
const makeToml = ({version}): string => `
const makeToml = ({ version }): string => `
[package]
authors = ["GoRules Team <bot@gorules.io>"]
description = "Business rules engine"
@@ -28,37 +28,36 @@ serde_v8 = { version = "0.88.0" }
once_cell = { version = "1.17.1" }
futures = "0.3.27"
v8 = { version = "0.66.0" }
zen-parser = { path = "../parser", version = "${version}" }
zen-vm = { path = "../vm", version = "${version}" }
`
zen-expression = { path = "../expression", version = "${version}" }
`;
describe("GitHub Action", () => {
test("Bumps package", () => {
const version = "0.2.0";
const initialToml = makeToml({version});
describe('GitHub Action', () => {
test('Bumps package', () => {
const version = '0.2.0';
const initialToml = makeToml({ version });
const releases: ReleaseType[] = ["major", "minor", "patch"];
const releases: ReleaseType[] = ['major', 'minor', 'patch'];
for (const release of releases) {
const newVersion = inc(version, release);
const expectedToml = makeToml({version: newVersion});
const expectedToml = makeToml({ version: newVersion });
expect(updateCargoContents(initialToml, {version: newVersion})).toEqual(expectedToml);
expect(updateCargoContents(initialToml, { version: newVersion })).toEqual(expectedToml);
}
});
test("Extracts package version", () => {
const versions = ["0.1.0", "0.2.0", "0.3.0"];
test('Extracts package version', () => {
const versions = ['0.1.0', '0.2.0', '0.3.0'];
for (const version of versions) {
const versionedToml = makeToml({ version });
expect(getCargoVersion(versionedToml)).toEqual(version);
}
})
});
test("Points to right directory", async () => {
test('Points to right directory', async () => {
const escapeDir = (count: number) => '../'.repeat(count);
const coreDirectory = path.join(__dirname, escapeDir(3), 'core');
const folders = await fs.readdir(coreDirectory);
expect(folders).toEqual(expect.arrayContaining(["engine", "parser", "vm"]))
expect(folders).toEqual(expect.arrayContaining(['engine', 'expression']));
});
});
});
+5 -7
View File
@@ -3,8 +3,8 @@ import * as exec from '@actions/exec';
import * as fs from 'fs/promises';
import * as path from 'path';
import {inc, ReleaseType} from 'semver';
import {getCargoVersion, updateCargoContents} from "./cargo";
import { inc, ReleaseType } from 'semver';
import { getCargoVersion, updateCargoContents } from './cargo';
async function run() {
try {
@@ -16,10 +16,8 @@ async function run() {
const project = 'engine';
const projectsFolder = 'core';
const directory = await fs.readdir(path.join(...[workspace, projectsFolder]), {withFileTypes: true});
const folders = directory
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name);
const directory = await fs.readdir(path.join(...[workspace, projectsFolder]), { withFileTypes: true });
const folders = directory.filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
const cargoFilePath = path.join(...[workspace, projectsFolder, project, 'Cargo.toml']);
const cargoFile = await fs.readFile(cargoFilePath, 'utf-8');
@@ -33,7 +31,7 @@ async function run() {
folders.map(async (folder) => {
const cargoFilePath = path.join(...[workspace, projectsFolder, folder, 'Cargo.toml']);
const cargoFile = await fs.readFile(cargoFilePath, 'utf-8');
const updatedCargoFile = updateCargoContents(cargoFile, {version});
const updatedCargoFile = updateCargoContents(cargoFile, { version });
console.log(`Writing new version to: ${cargoFilePath}`);
await fs.writeFile(cargoFilePath, updatedCargoFile);
+1 -1
View File
@@ -22,7 +22,7 @@ serde_v8 = { version = "0.88.0" }
once_cell = { version = "1.17.1" }
futures = "0.3.27"
v8 = { version = "0.66.0" }
zen-vm = { path = "../vm", version = "0.2.1" }
zen-expression = { path = "../expression", version = "0.2.1" }
[dev-dependencies]
tokio-test = "0.4.2"
+1 -1
View File
@@ -7,7 +7,7 @@ use serde_json::Value;
use crate::handler::node::{NodeRequest, NodeResponse, NodeResult};
use crate::handler::table::{RowOutput, RowOutputKind};
use crate::model::{DecisionNodeKind, DecisionTableContent, DecisionTableHitPolicy};
use zen_vm::isolate::Isolate;
use zen_expression::isolate::Isolate;
#[derive(Debug, Serialize)]
struct RowResult {
@@ -1,7 +1,7 @@
[package]
authors = ["GoRules Team <bot@gorules.io>"]
description = "Zen expression language virtual machine"
name = "zen-vm"
description = "Zen Expression Language"
name = "zen-expression"
license = "MIT"
version = "0.2.1"
edition = "2021"
@@ -16,15 +16,27 @@ hashbrown = { workspace = true, features = ["bumpalo"] }
humantime = { workspace = true }
fastrand = { workspace = true }
once_cell = { workspace = true }
phf = { workspace = true, features = ["macros"] }
serde_json = { workspace = true, features = ["arbitrary_precision"] }
thiserror = { workspace = true }
rust_decimal = { workspace = true, features = ["maths-nopanic"] }
rust_decimal_macros = { workspace = true }
zen-parser = { path = "../parser", version = "0.2.1" }
[dev-dependencies]
criterion = { workspace = true }
[[bench]]
harness = false
name = "unary"
[[bench]]
harness = false
name = "standard"
[[bench]]
harness = false
name = "lexer"
[[bench]]
harness = false
name = "isolate"
@@ -1,7 +1,7 @@
# ZEN VM
# ZEN Expression
Parser for business-first expression language used in
Zen business rules engine by GoRules. The language is designed
Zen Expression is business-first expression language used in
Zen Business rules engine by GoRules. The language is designed
to follow these principles:
- Side-effect free
@@ -1,7 +1,7 @@
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use serde_json::Value;
use zen_vm::isolate::Isolate;
use zen_expression::isolate::Isolate;
fn bench_source(b: &mut Bencher, source: &'static str) {
let s: Value = serde_json::from_str(r#"{ "$": "ru" }"#).unwrap();
@@ -1,6 +1,6 @@
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use zen_parser::lexer::Lexer;
use zen_expression::lexer::Lexer;
fn bench_source(b: &mut Bencher, source: &'static str) {
let lexer = Lexer::new();
@@ -1,8 +1,8 @@
use bumpalo::Bump;
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use zen_parser::lexer::Lexer;
use zen_parser::parser::StandardParser;
use zen_expression::lexer::Lexer;
use zen_expression::parser::StandardParser;
fn bench_source(b: &mut Bencher, src: &'static str) {
let lexer = Lexer::new();
@@ -1,8 +1,8 @@
use bumpalo::Bump;
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use zen_parser::lexer::Lexer;
use zen_parser::parser::UnaryParser;
use zen_expression::lexer::Lexer;
use zen_expression::parser::UnaryParser;
fn bench_source(b: &mut Bencher, src: &'static str) {
let lexer = Lexer::new();
@@ -4,7 +4,7 @@ use std::rc::Rc;
use bumpalo::Bump;
use thiserror::Error;
use zen_parser::ast::Node;
use crate::ast::Node;
use crate::compiler::CompilerError::{
ArgumentNotFound, UnknownBinaryOperator, UnknownBuiltIn, UnknownUnaryOperator,
@@ -10,10 +10,10 @@ use bumpalo::Bump;
use serde_json::Value;
use thiserror::Error;
use zen_parser::lexer::error::LexerError;
use zen_parser::lexer::Lexer;
use zen_parser::parser::error::ParserError;
use zen_parser::parser::{StandardParser, UnaryParser};
use crate::lexer::error::LexerError;
use crate::lexer::Lexer;
use crate::parser::error::ParserError;
use crate::parser::{StandardParser, UnaryParser};
use crate::compiler::{Compiler, CompilerError};
use crate::opcodes::{ExecResult, Opcode, Variable};
@@ -5,7 +5,10 @@ extern crate core;
mod helpers;
pub mod ast;
pub mod compiler;
pub mod isolate;
pub mod lexer;
pub mod opcodes;
pub mod parser;
pub mod vm;
@@ -2,8 +2,8 @@ use bumpalo::Bump;
use rust_decimal_macros::dec;
use serde_json::{json, Value};
use zen_vm::isolate::Isolate;
use zen_vm::opcodes::{ExecResult, Variable};
use zen_expression::isolate::Isolate;
use zen_expression::opcodes::{ExecResult, Variable};
struct TestEnv {
env: Value,
@@ -1,5 +1,5 @@
use zen_parser::lexer::token::{Token, TokenKind};
use zen_parser::lexer::Lexer;
use zen_expression::lexer::token::{Token, TokenKind};
use zen_expression::lexer::Lexer;
struct LexerTest {
test: &'static str,
@@ -3,9 +3,9 @@ use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use zen_parser::ast::Node;
use zen_parser::lexer::Lexer;
use zen_parser::parser::StandardParser;
use zen_expression::ast::Node;
use zen_expression::lexer::Lexer;
use zen_expression::parser::StandardParser;
struct StandardTest {
src: &'static str,
@@ -2,9 +2,9 @@ use bumpalo::Bump;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use zen_parser::ast::Node;
use zen_parser::lexer::Lexer;
use zen_parser::parser::UnaryParser;
use zen_expression::ast::Node;
use zen_expression::lexer::Lexer;
use zen_expression::parser::UnaryParser;
struct UnaryTest {
src: &'static str,
-32
View File
@@ -1,32 +0,0 @@
[package]
authors = ["GoRules Team <bot@gorules.io>"]
description = "Zen expression language parser"
name = "zen-parser"
license = "MIT"
version = "0.2.1"
edition = "2021"
repository = "https://github.com/gorules/zen.git"
[dependencies]
ahash = { workspace = true }
bumpalo = { workspace = true }
once_cell = { workspace = true }
phf = { workspace = true, features = ["macros"] }
thiserror = { workspace = true }
rust_decimal = { workspace = true }
rust_decimal_macros = { workspace = true }
[dev-dependencies]
criterion = { workspace = true }
[[bench]]
harness = false
name = "unary"
[[bench]]
harness = false
name = "standard"
[[bench]]
harness = false
name = "lexer"
-71
View File
@@ -1,71 +0,0 @@
# ZEN Parser
Virtual machine for business-first expression language used in
Zen business rules engine by GoRules. The language is designed
to follow these principles:
- Side-effect free
- Dynamic types
- Simple syntax for broad audiences
It's primary objective is to bridge the gap between business analysts and engineers,
while providing outstanding performance and readability.
## Resources
[Documentation](https://gorules.io/docs/)
[Zen Language Playground](https://gorules.io/docs/rules-engine/expression-language#playground)
[Online Rules Editor](https://editor.gorules.io/)
## Unary tests
Unary test is a comma-separated list of simple expressions which
evaluate to a boolean value. Each comma separation is treated as
or operator. Inside unary expressions, a special symbol is available
$ which refers to a current column.
Some examples:
```js
// Given: $ = 1
1, 2, 3 // true
1 // true
>= 1 // true
< 1 // false
[0..10] // true, (internally this is $ >= 0 and $ <= 10)
> 0 and < 10 // true
// Given: $ = 'USD'
'GBP', 'USD' // true
'EUR' // false
startsWith($, "US") // true - defaults to expression mode, comma is unavailable
endsWith($, "US") // false - defaults to expression mode
lower($) == "usd" // true - defaults to expression mode
```
## Standard tests
Expressions feature full capability syntax of ZEN language.
They give you access to all functions, and are most useful when
defining columns or outputs. Full syntax is also available in unary
expressions when $ is used (as it forces the expression mode).
```js
100 + 100 // 200
10 * 5 // 50
10 ^ 2 // 100
1 in [1, 2, 3] // true
5 in (5..10] // false
sum([1, 2, 3]) // 6
max([1, 2, 3]) // 3
"hello" + " " + "world" // "hello world"
len("world") // 5
weekdayString(date("2022-11-08")) // "Tue"
contains("hello world", "hello") // true
upper('john') // "JOHN"
some(['admin', 'user'], # == "admin") // true
not all([100, 200, 400, 800], # in (100..800)) // false
filter([100, 200, 400, 800], # >= 200) // [200, 400, 800]
```
-7
View File
@@ -1,7 +0,0 @@
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![allow(clippy::module_inception)]
pub mod ast;
pub mod lexer;
pub mod parser;