internal.interpreter
Implements a small interpreter.
Syntax:
This interpreter interprets a subset of the Python programming language, with an extension to the behavior of default arguments in lambdas. Since it uses the Python parser, it obeys Python’s operator precedence. If it encounters a name in the expression, it looks it up in the supplied environment.
Here are the supported operations:
Strings (with support for the .format method)
Integers and floats.
True,False, andNone.Lists and list comprehensions
Dictionaries and dict comprehensions
Indexing for lists and dictionaries.
Unary
not, negation.Binary multiplication, division, exponentiation, addition, subtraction.
Boolean
andandor.Comparison with
<,>,<=,>=,==, and!=.Chained comparison, like
0.2 < x < 0.5.Builtin functions:
exp,log,sqrt,abs,any,all,min,max,sum,len,range.Builtin constants:
e,pi,true,false, andnull. Thetrue,false, andnullconstants are for compatibility with JSON. The Python literalsTrue,False, andNoneare also supported.User-defined functions with
lambdasyntax. By abusing default parameters, you can even create recursive functions!
The extension to the lambda default parameters lets you use letrec-style recursive functions without needing to use the Z combinator to implement recursion. For example, this is valid in my interpreter but not valid Python:
(lambda x=5, y=(lambda q: x + q): y(7))()
In effect, you can think of this being translated to:
(letrec ((x 5) (y (lambda (q) (+ x q)))) (y 7))
Note that if you use a lambda as a default parameter to a lambda, you cannot override any default arguments when you call it. So this:
(lambda x=5, y=(lambda q: x + q): y(7))(3)
is an error because the call to the outer lambda attempted to specify x.
<expression> ::= (<expression>) | "<list-of-character>" | [<list-of-expression>] | {<list-of-dict-elems>} | [<expression> <comprehension-suite>] | {<dict-elem> <comprehension-suite>} | <expression>[<expression>] | <expression>.format(<list-of-expression>) | <unary-op-expr> | <bin-op-expr> | <expression> <compare-suite> | <bool-op-expr> | <number> | <python-literal> | lambda <formals>: <expression> | <expression>(<list-of-expression>) | <list-of-character>
<comprehension-suite> ::= for <list-of-character> in <expression> « if <expression>» | <comprehension-suite> <comprehension-suite>
<list-of-dict-elems> ::= <empty> | <dict-elem>«, <list-of-dict-elems>»
<dict-elem> ::= <expression>: <expression>
<formals> ::= <empty> | <list-of-character>«, <formals>» | <formals-with-defaults>
<formals-with-defaults> ::= <empty> | <list-of-character>=<expression>«, <formals-with-defaults>»
<list-of-expression> ::= <empty> | <expression>«, <list-of-expression>»
<bool-op-expr> ::= <expression> and <expression> | <expression> or <expression>
<bin-op-expr> ::= <expression> ** <expression> <expression> * <expression> <expression> / <expression> <expression> + <expression> <expression> - <expression>
<unary-op-expr> ::= - <expression> | not <expression>
<compare-suite> ::= <compare-op> <expression> «<compare-suite>»
<compare-op> ::= < | > | < | >= | == | != | in | not in
<python-literal> ::= (Anything that is a literal in Python)
- class bpreveal.internal.interpreter.Closure(env, args, body)
Represents a function and its environment.
You do not need to use this, it’s only necessary to set up letrec-style default parameters for lambdas.
- Parameters:
env (dict[str, int | float | bool | str | Callable | Closure | dict | list | Collection | None])
args (arguments)
body (expr)
- bpreveal.internal.interpreter.evalAstRaw(t, env)
Evaluates the (ast.parse()d) filter string t using variables in the environment env.
- Parameters:
t (AST) – The parsed AST that should be evaluated
env (dict[str, Any]) – The environment containing the variables used in the expression.
- Returns:
The value of the expression.
- Return type:
int | float | bool | str | Callable | Closure | dict | list | Collection | None
You should probably call
evalAst()instead of this, since that function will add helpful builtins to your environment.
- bpreveal.internal.interpreter.evalAst(t, env=None, addFunctions=True)
Evaluates the (ast.parse()d) filter string t using variables in the environment env.
- Parameters:
t (AST) – The parsed AST that should be evaluated
env (dict[str, int | float | bool | str | Callable | Closure | dict | list | Collection | None] | None) – The environment containing the variables used in the expression.
addFunctions (bool) – If True (the default), then the functions
exp,log,sqrt,abs, andlen, along with the constantspiandewill be added to the environment (but they will be shadowed by existing declarations if they have already been defined.)
- Returns:
The value of the expression.
- Return type:
int | float | bool | str | Callable | Closure | dict | list | Collection | None
- bpreveal.internal.interpreter.evalString(expr, env=None, addFunctions=True)
Parses the given string and then runs evalAst on it.
- bpreveal.internal.interpreter.evalFile(fname, env=None, addFunctions=True)
Read in the named file and evaluate it.