scheme-from-python is an experimental scheme interpreter in Python.
demo.mov
- Scheme core
- define
- if
- lambda (with closures)
- macro (without capturing context)
- Builtin functions
- Boolean operators
- Arithmetic operators (integer, float, complex)
- Comparing operators
- Input / Output functions
- Interoperation
- Auto signature inferring from Python to Scheme
- Lazy or non-lazy functions
- Capturing the evaluation context (symbol table)
- Call pure Python functions
- Interpreter
- File / command-line expression
- Auto-indented multi-line
- Auto fixing missing right parentheses
For sequence expression, the final value is the value of the last sub-expression, e.g.,
1 2 3
=3
.
Most static Python functions can be accessed in sfpy, by the qualified name :builtinAttribute
, module:
, module:attribue
or module:class.attribue
, e.g., :dir
, os:getcwd
, os.path:split
.
sfpy tries to wrap the Python function to adapt to the scheme environment. Have fun to try this experimental feature!
> sys:version
3.10.4 | packaged by conda-forge | (main, Mar 30 2022, 08:38:02) [MSC v.1916 64 bit (AMD64)]
> os:getcwd
(lambda () (...))
> (os:getcwd)
D:\scheme-from-python\src
> (:dir math:)
Object(['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'lcm', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc', 'ulp'])
- Boolean:
#t
true,#f
false - Integer:
0
,-1
,2
, ... - Float:
0.1
,1.5
, ... - Complex:
1+2j
,3+4j
, ... - Symbol:
a
,b
,c
,+
,-
, ... - String:
a
,b
,c
,+
,-
, ... - Function:
(lambda (x) (+ x 1))
, ... - Empty:
<empty>
only as return value
(define symbol_name value_expression)
Define a symbol with exact value, and return the value, def
for a short alternative.
(if predicate_expression true_expression false_expresion)
Branch expression, if predicate_expression
is not #f
, then evaluate and return the value of true_expression
, otherwise evaluate and return the value of false_expression
.
(lambda (p1 p2 ... pn) body_expression
Lambda expresion, define an anonymous function (closure) with the parameters named p1
, p2
, ..., pn
(can be empty, i.e., ()
), and the function body, lam
for a short alternative.
The lambda function creates a sub-symbol-table, so define
in a lambda function can only write current symbols, and cannot write upstream symbols (can hidden them by define symbols in the same name). Here is an example code snippet.
>>> ((lambda () (define x 1)))
x
>>> x
Undefined symbol: x
(macro (p1 p2 ... pn) body_expression)
Macro expression, define a macro, for text replacement with the parameters named p1
, p2
, ..., pn
(can be empty, i.e., ()
), and the macro body, mac
for a short alternative, no capturing context.
(not b)
(and b1 b2 ... bn)
without short circuit
(or b1 b2 ... bn)
without short circuit
The operands must be integers.
(+ v1 v2 ... vn)
(- v1 v2)
(* v1 v2 ... vn)
(// v1 v2)
(/ v1 v2)
(% v1 v2)
(^ v1 v2)
(max v1 v2 ... vn)
(min v1 v2 ... vn)
(< v1 v2)
(<= v1 v2)
(> v1 v2)
(>= v1 v2)
(= v1 v2)
(!= v1 v2)
(print v)
Print the value and return empty.
(from filePath)
Interprete a source file and return the evaluated value.
(symbols)
Return all symbols in the current context, syms
for a short alternative.
conda create -n sfpy python=3.10
conda activate sfpy
cd src
pip install -r requirements.txt
sfpy supports interactor (for user input) and interpreter (for file input) mode.
python -m sfpy
- Use
_
to access last value.
python -m sfpy -f your_scheme_file
python -m sfpy -e "your scheme expression"
python -m sfpy -f ./demo/arithmetic.scm
python -m sfpy -f ./demo/lambda.scm
python -m sfpy -f ./demo/factorial.scm