Skip to content

Commit

Permalink
Merge pull request #715 from schungx/master
Browse files Browse the repository at this point in the history
Fix bugs.
  • Loading branch information
schungx committed Apr 27, 2023
2 parents 160f72b + 76e6c1b commit aa47dd2
Show file tree
Hide file tree
Showing 23 changed files with 630 additions and 305 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@ Version 1.14.0

The code hacks that attempt to optimize branch prediction performance are removed because benchmarks do not show any material speed improvements.

Buf fixes
Bug fixes
----------

* `is_shared` is a reserved keyword and is now handled properly (e.g. it cannot be the target of a function pointer).
* Re-optimizing an AST via `optimize_ast` with constants now works correctly for closures. Previously the hidden `Share` nodes are not removed and causes variable-not-found errors during runtime if the constants are not available in the scope.
* Expressions such as `(v[0].func()).prop` now parse correctly.
* Shadowed variable exports are now handled correctly.
* Shadowed constant definitions are now optimized correctly when propagated (e.g. `const X = 1; const X = 1 + 1 + 1; X` now evaluates to 3 instead of 0).
* Identifiers and comma's in the middle of custom syntax now register correctly.
* Exporting an object map from a module with closures defined on properties now works correctly when those properties are called to mimic method calls in OOP-style.

New features
------------

* It is now possible to require a specific _type_ to the `this` pointer for a particular script-defined function so that it is called only when the `this` pointer contains the specified type.
* `is_def_fn` is extended to support checking for typed methods, with syntax `is_def_fn(this_type, fn_name, arity)`
* `Dynamic::take` is added as a short-cut for `std::mem::take(&mut value)`.

Enhancements
------------
Expand Down
16 changes: 7 additions & 9 deletions src/api/custom_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,9 @@ impl Engine {
}

let token = Token::lookup_symbol_from_syntax(s).or_else(|| {
if is_reserved_keyword_or_symbol(s).0 {
Some(Token::Reserved(Box::new(s.into())))
} else {
None
}
is_reserved_keyword_or_symbol(s)
.0
.then(|| Token::Reserved(Box::new(s.into())))
});

let seg = match s {
Expand All @@ -256,6 +254,9 @@ impl Engine {
#[cfg(not(feature = "no_float"))]
CUSTOM_SYNTAX_MARKER_FLOAT if !segments.is_empty() => s.into(),

// Identifier not in first position
_ if !segments.is_empty() && is_valid_identifier(s) => s.into(),

// Keyword/symbol not in first position
_ if !segments.is_empty() && token.is_some() => {
// Make it a custom keyword/symbol if it is disabled or reserved
Expand All @@ -277,10 +278,7 @@ impl Engine {
{
return Err(LexError::ImproperSymbol(
s.to_string(),
format!(
"Improper symbol for custom syntax at position #{}: '{s}'",
segments.len() + 1,
),
format!("Improper symbol for custom syntax at position #0: '{s}'"),
)
.into_err(Position::NONE));
}
Expand Down
2 changes: 1 addition & 1 deletion src/api/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl Engine {
///
/// To access a primary argument value (i.e. cloning is cheap), use: `args[n].as_xxx().unwrap()`
///
/// To access an argument value and avoid cloning, use `std::mem::take(args[n]).cast::<T>()`.
/// To access an argument value and avoid cloning, use `args[n].take().cast::<T>()`.
/// Notice that this will _consume_ the argument, replacing it with `()`.
///
/// To access the first mutable parameter, use `args.get_mut(0).unwrap()`
Expand Down
6 changes: 6 additions & 0 deletions src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::{
fmt::Write,
hash::Hash,
iter::once,
mem,
num::{NonZeroU8, NonZeroUsize},
};

Expand Down Expand Up @@ -833,6 +834,11 @@ impl Expr {
Self::Property(..) => matches!(token, Token::LeftParen),
}
}
/// Return this [`Expr`], replacing it with [`Expr::Unit`].
#[inline(always)]
pub fn take(&mut self) -> Self {
mem::take(self)
}
/// Recursively walk this expression.
/// Return `false` from the callback to terminate the walk.
pub fn walk<'a>(
Expand Down
5 changes: 5 additions & 0 deletions src/ast/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,11 @@ impl Stmt {
pub const fn is_control_flow_break(&self) -> bool {
matches!(self, Self::Return(..) | Self::BreakLoop(..))
}
/// Return this [`Stmt`], replacing it with [`Stmt::Noop`].
#[inline(always)]
pub fn take(&mut self) -> Self {
mem::take(self)
}
/// Recursively walk this statement.
/// Return `false` from the callback to terminate the walk.
pub fn walk<'a>(
Expand Down
2 changes: 1 addition & 1 deletion src/eval/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,7 @@ impl Engine {

if !val.is_shared() {
// Replace the variable with a shared value.
*val = std::mem::take(val).into_shared();
*val = val.take().into_shared();
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/func/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
return match op {
PlusAssign => Some((
|_ctx, args| {
let x = std::mem::take(args[1]).into_array().unwrap();
let x = args[1].take().into_array().unwrap();

if x.is_empty() {
return Ok(Dynamic::UNIT);
Expand Down Expand Up @@ -783,7 +783,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
return match op {
PlusAssign => Some((
|_ctx, args| {
let blob2 = std::mem::take(args[1]).into_blob().unwrap();
let blob2 = args[1].take().into_blob().unwrap();
let blob1 = &mut *args[0].write_lock::<Blob>().unwrap();

#[cfg(not(feature = "unchecked"))]
Expand Down Expand Up @@ -931,7 +931,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
PlusAssign => Some((
|_ctx, args| {
{
let x = std::mem::take(args[1]);
let x = args[1].take();
let array = &mut *args[0].write_lock::<Array>().unwrap();
push(array, x);
}
Expand Down

0 comments on commit aa47dd2

Please sign in to comment.