Skip to content

Commit

Permalink
Merge branch 'trueagi-io:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
luketpeterson authored May 6, 2024
2 parents 26d1780 + 67d9c78 commit 7037d60
Show file tree
Hide file tree
Showing 16 changed files with 315 additions and 317 deletions.
69 changes: 69 additions & 0 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,72 @@ export CIBW_BUILD=cp37-manylinux_x86_64
After exporting the variables above one can start release by executing
`cibuildwheel` from the `./python` directory of the repo. See [cibuildwheel
documentation](https://cibuildwheel.pypa.io/en/stable/) for details.

## How to update the version

Usually it is needed after releasing the artifacts or before making a test
release.

There are three locations to update:
- [/Cargo.toml](/Cargo.toml) file:
- `workspace.package.version` property
- `workspace.dependencies.hyperon.version` property
- [/python/VERSION](/python/VERSION) file

All three locations should contain the same version.

## How to release binaries

Use [Create a new release
link](https://github.com/trueagi-io/hyperon-experimental/releases/new) on the
main page of the GitHub repo. Press `Choose a tag` control and type new tag
which should be in form of `v<next-version>` (for example if next version is
`0.1.7` then tag is `v0.1.7`). Next version should be identical to versions
which are written in locations mentioned in [How to update the
version](#how-to-update-the-version) instruction. After typing the tag press
`Create new tag on publish`. Now press `Generate release notes` button. It will
automatically fill the `Release title` and `Release description` fields. Tick
`Set as a pre-release` checkbox if needed and press `Publish release` button.
Now you have published new GitHub release and triggered a job to build release
artifacts.

After release job is finished one need to approve publishing artifacts to the
PyPi repository. Before approving one can download and test Python wheels
built. To check the job status go the `Actions/release-pyhon` page, and select
last workflow run. Links to the archives with the artifacts are located at the
bottom of the page.

If distribution wheels are good then one can approve the publishing process. At
the top of the workflow run page there are two blocks `Publish to Test PyPi`
and `Publish to PyPi`. First press `Publish to Test PyPi` block approve it and
wait for publishing. It is critical to start from Test PyPi because release
cannot be removed from the PyPi after publishing.

After release is published check it can be installed executing:
```
python3 -m pip install --index-url https://test.pypi.org/simple/ hyperon
```
Check that the latest published version was downloaded and installed. If you
are making a test release then you should not publish it to the PyPi. If it is
a production release then proceed with `Publish to PyPi` block.

## How to check release job in fork

First you need to select the test release version. It should contain an
additional version digit after the latest officially released version. Let's
say the latest released version is `0.1.7`. Then the test release version
should be `0.1.7.x` for instance `0.1.7.1`. Start from 1 and increment it after
each release you published successfully.

Make a separate branch to release the code. It is not necessary but it is
highly recommended to not pollute the main branch of the fork. In order to be
able releasing from the branch one need to temporary make it default branch. It
is done by using GitHub repo `Settings/General/Default branch` control.

[Update the version](#how-to-update-the-version) in the branch to the test
release version you constructed. Commit and push this change in your test
branch. Now you are ready to make a test release. See [release
binaries instruction](#how-to-release-binaries).

After testing the release procedure remove the commit with version update from
your branch. And set default branch setting to the previous value.
26 changes: 19 additions & 7 deletions lib/src/atom/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,32 +1116,44 @@ pub fn match_result_product(prev: MatchResultIter, next: MatchResultIter) -> Mat
Box::new(prev.merge(&next).into_iter())
}

/// Applies bindings to atom and return it (see [apply_bindings_to_atom_mut]).
#[inline]
pub fn apply_bindings_to_atom_move(mut atom: Atom, bindings: &Bindings) -> Atom {
apply_bindings_to_atom_mut(&mut atom, bindings);
atom
}

/// Applies bindings to atom. Function replaces all variables in atom by
/// corresponding bindings.
///
/// # Examples
///
/// ```
/// use hyperon::*;
/// use hyperon::atom::matcher::apply_bindings_to_atom;
/// use hyperon::atom::matcher::apply_bindings_to_atom_mut;
///
/// let binds = bind!{ y: expr!("Y") };
/// let atom = apply_bindings_to_atom(&expr!("+" "X" y), &binds);
/// let mut atom = expr!("+" "X" y);
/// apply_bindings_to_atom_mut(&mut atom, &binds);
///
/// assert_eq!(atom, expr!("+" "X" "Y"));
/// ```
pub fn apply_bindings_to_atom(atom: &Atom, bindings: &Bindings) -> Atom {
let mut result = atom.clone();
pub fn apply_bindings_to_atom_mut(atom: &mut Atom, bindings: &Bindings) {
let trace_atom = match log::log_enabled!(log::Level::Trace) {
true => Some(atom.clone()),
false => None,
};
if !bindings.is_empty() {
result.iter_mut().for_each(|atom| match atom {
atom.iter_mut().for_each(|atom| match atom {
Atom::Variable(var) => {
bindings.resolve(var).map(|value| *atom = value);
},
_ => {},
});
}
log::trace!("apply_bindings_to_atom: {} | {} -> {}", atom, bindings, result);
result
if let Some(atom_copy) = trace_atom {
log::trace!("apply_bindings_to_atom: {} | {} -> {}", atom_copy, bindings, atom);
}
}

/// Applies bindings `from` to the each value from bindings `to`.
Expand Down
12 changes: 6 additions & 6 deletions lib/src/metta/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ impl InterpreterCache {
fn insert(&mut self, key: Atom, mut value: Results) {
value.iter_mut().for_each(|res| {
let vars: HashSet<&VariableAtom> = key.iter().filter_type::<&VariableAtom>().collect();
res.0 = apply_bindings_to_atom(&res.0, &res.1);
apply_bindings_to_atom_mut(&mut res.0, &res.1);
res.1.retain(|v| vars.contains(v));
});
self.0.insert(key, value)
Expand Down Expand Up @@ -362,7 +362,7 @@ fn interpret_as_type_plan<'a, T: SpaceRef<'a>>(context: InterpreterContextRef<'a
fn cast_atom_to_type_plan<'a, T: SpaceRef<'a>>(context: InterpreterContextRef<'a, T>,
input: InterpretedAtom, typ: Atom) -> StepResult<'a, Results, InterpreterError> {
// TODO: implement this via interpreting of the (:cast atom typ) expression
let typ = apply_bindings_to_atom(&typ, input.bindings());
let typ = apply_bindings_to_atom_move(typ, input.bindings());
let mut results = get_type_bindings(&context.space, input.atom(), &typ);
log::debug!("cast_atom_to_type_plan: type check results: {:?}", results);
if !results.is_empty() {
Expand All @@ -373,7 +373,7 @@ fn cast_atom_to_type_plan<'a, T: SpaceRef<'a>>(context: InterpreterContextRef<'a
// should we apply bindings to bindings?
let bindings = Bindings::merge(&bindings, &typ_bindings);
if let Some(bindings) = bindings {
let atom = apply_bindings_to_atom(&atom, &bindings);
let atom = apply_bindings_to_atom_move(atom, &bindings);
Some(InterpretedAtom(atom, bindings))
} else {
None
Expand Down Expand Up @@ -446,7 +446,7 @@ fn interpret_expression_as_type_op<'a, T: SpaceRef<'a>>(context: InterpreterCont
plan,
OperatorPlan::new(move |results: Results| {
make_alternives_plan(arg.clone(), results, move |result| -> NoInputPlan {
let arg_typ = apply_bindings_to_atom(&arg_typ, result.bindings());
let arg_typ = apply_bindings_to_atom_move(arg_typ.clone(), result.bindings());
Box::new(SequencePlan::new(
interpret_as_type_plan(context.clone(),
InterpretedAtom(arg.clone(), result.bindings().clone()),
Expand Down Expand Up @@ -500,7 +500,7 @@ fn insert_reducted_arg_op<'a>(expr: InterpretedAtom, atom_idx: usize, mut arg_va
let InterpretedAtom(arg, bindings) = arg;
let mut expr_with_arg = expr.atom().clone();
get_expr_mut(&mut expr_with_arg).children_mut()[atom_idx] = arg;
InterpretedAtom(apply_bindings_to_atom(&expr_with_arg, &bindings), bindings)
InterpretedAtom(apply_bindings_to_atom_move(expr_with_arg, &bindings), bindings)
}).collect();
log::debug!("insert_reducted_arg_op: result: {:?}", result);
StepResult::ret(result)
Expand Down Expand Up @@ -626,7 +626,7 @@ fn match_op<'a, T: SpaceRef<'a>>(context: InterpreterContextRef<'a, T>, input: I
let results: Vec<InterpretedAtom> = query_bindings
.drain(0..)
.map(|query_binding| {
let result = apply_bindings_to_atom(&Atom::Variable(var_x.clone()), &query_binding);
let result = apply_bindings_to_atom_move(Atom::Variable(var_x.clone()), &query_binding);
// TODO: sometimes we apply bindings twice: first time here,
// second time when inserting matched argument into nesting
// expression. It should be enough doing it only once.
Expand Down
Loading

0 comments on commit 7037d60

Please sign in to comment.