Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature request] allow pointer accessor outside predicate for parsing #733

Open
lublak opened this issue Nov 26, 2024 · 4 comments
Open

Comments

@lublak
Copy link

lublak commented Nov 26, 2024

Currently i can even parse it. It would be usefull to implement your own "scope" via "patching".
I would like to use a patcher to patchh somethin like this:

.Test

and patch it to (if not used in a "build in function"!)

CurrentScope.Test

https://expr-lang.org/docs/patch

but i get directly an error cannot use pointer accessor outside closure or cannot use pointer accessor outside predicate without even a chance to access the ast tree.

@antonmedv
Copy link
Member

So what would we the case for this?

Pointer accessor (#.Test or .Test) is reserved for builtins like all and map. To access your current env you can simply use Test (do leading dot).

@lublak
Copy link
Author

lublak commented Nov 27, 2024

@antonmedv
Basically simple to say: To build such closure functions myself.
For example, I have functions that describe an element.
element(“information”, closure)
The first time the expr is executed, only the information is drawn. The closure is not executed. With a certain interaction, the expr is executed again, but this time with closure and the context of the element.
If patching were possible here, I would try to give myself a small way to define callbacks that allow a “tree” as a parameter. Which I can then execute in the callback (callback is then closure).

@antonmedv
Copy link
Member

I see. Predicates/closures dependent on corresponding compiler code. What would be results of your patching?

@lublak
Copy link
Author

lublak commented Nov 27, 2024

@antonmedv
In general, the patcher receives information on the functions via reflection.
For my project, I would set a fixed default for how the callback should look. If this function then contains a callback, the function is wrapped.
First of all, let's get to the patcher. This first goes through all CallNodes. If the function exists in my map with callbacks, the PredicateNodes or ClosureNodes are patched. The basic idea here would be to convert these to a value and then execute the function with an “ast tree”.
Example:

type patcher struct {
	fn map[string]reflect.Value
}
func (p *patcher) Visit(node *ast.Node) {
  switch n := (*node).(type) {
    case *ast.CallNode:
      // if fn map contains callee, patch it if it arguments contains a callback (tree argument) and CallNode arguments contains a PredicateNode, ClosureNode
  }
}
testfn("customePredicateFunction", .Test == "bla")
becomes:
testfn("customePredicateFunction", { /* ... ast (tree) as a map/object */})
or 
// int is just a counter and the map gets filled from the patcher with the .Test == "bla" tree/node
testfn("customePredicateFunction", reference_to_a_dynamic_map[int])
// also exists in the expr.Env(env),
func testfn(argument1 string, tree *parser.Tree) {
  // now i can do everything i want with the Tree / or ast.Node
  // compiler.Compile(tree, conf.CreateNew())
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants