scm.py: support eval. Improve eval in home page

master
Nicolò Balzarotti 2023-02-22 03:58:53 +01:00
parent 13e1ed9f34
commit 40c9655424
5 changed files with 31 additions and 20 deletions

3
app.py
View File

@ -90,8 +90,7 @@ def handle_new_client():
@socketio.on('eval scheme')
def eval_scheme(code):
output = phasectrl.safe_eval(code, statemachine.env)
phasectrl.safe_eval(f'(notify "{output}")', statemachine.env)
output = phasectrl.safe_eval(code, statemachine.env, notify=False)
socketio.emit('eval output', output)
@socketio.on('get sensors history')

View File

@ -14,13 +14,15 @@ MY_GLOBAL_ENV = (
_('format-time', 1, lambda x: stohms(x.car),
GLOBAL_ENV)))
def safe_eval(data, env):
def safe_eval(data, env, notify=True):
try:
return eval(data, env)
except Exception as e:
err = ' '.join(('evaluating:', data, ':', str(e)))
chat.send_sync(err)
return True
if notify:
chat.send_sync(err)
return True
return err
def load_phase(json):
def fallback(v):
@ -244,7 +246,7 @@ class State():
actuators[actuator].enable()
else:
actuators[actuator].disable()
print('setting actuator ', actuator, 'to value', value,
print('setting actuator', actuator, 'to value', value,
', remember to change it manually if stopping?')
def get_total_consumption(self):

22
scm.py
View File

@ -82,6 +82,9 @@ class SchemeString:
def __repr__(self):
return '"' + self.string + '"'
def __eq__(self, other):
return self.string == other.string
class Environment (object):
"Linked list of bindings mapping symbols to values"
@ -206,11 +209,13 @@ GLOBAL_ENV = (
# My custom helpers
from datetime import datetime
GLOBAL_ENV = (
_('now', 0, lambda x: datetime.now(),
_('concat', -1, lambda x: ''.join((stringify(x, False) for x in x)),
_('exit', 0, lambda x: exit(),
GLOBAL_ENV))))
_('eval', 1, lambda x: evaluate(x.car),
GLOBAL_ENV)))))
# records = {}
# def make_record_type(name, params):
@ -249,11 +254,12 @@ GLOBAL_ENV = Environment(
_('cdr', 1, lambda x: x.car.cdr,
_('cons', 2, lambda x: Cell(x.car, x.cdr.car),
_('eq?', 2, lambda x: x.car is x.cdr.car,
_('pair?', 1, lambda x: isinstance(x.car, Cell),
_('null?', 1, lambda x: x.car is NIL,
_('not', 1, lambda x: x.car is False,
_('list', -1, lambda x: x,
GLOBAL_ENV)))))))))
_('equal?', 2, lambda x: x.car == x.cdr.car,
_('pair?', 1, lambda x: isinstance(x.car, Cell),
_('null?', 1, lambda x: x.car is NIL,
_('not', 1, lambda x: x.car is False,
_('list', -1, lambda x: x,
GLOBAL_ENV))))))))))
@ -393,8 +399,8 @@ def apply_function(fun, arg, k, env):
elif isinstance(fun, tuple): # as a continuation
return arg.car, fun, env
else:
raise TypeError('not a function: ' + stringify(fun) + ' with '
+ stringify(arg))
raise TypeError('wrong type to apply: ' + stringify(fun) + ' with '
+ stringify(arg) + ' instance is ' + str(type(fun)))
def _push_RESTORE_ENV(k, env):
if k is NOCONT or k[0] is not RESTORE_ENV: # unless tail call...

View File

@ -21,6 +21,9 @@
socket.on("state", (data) => {
applyState(data);
});
socket.on("eval output", (data) => {
document.getElementById('eval-output').value = data;
});
socket.on("sensors", (data) => {
add_plot_data(data);
render_sensors(data);

View File

@ -61,12 +61,13 @@
</header>
<div class="card-content">
<div class="content">
<div class="field has-addons">
<textarea class="textarea" value="#t" id="scheme-eval"/></textarea>
<a class="button is-info" onclick="eval_scheme('scheme-eval')">
Eval
</a>
</div>
<textarea class="textarea" value="#t" id="scheme-eval">
</textarea>
<a class="button is-info" onclick="eval_scheme('scheme-eval')">
Eval
</a>
<textarea class="textarea" value="#t" id="eval-output" readonly>
</textarea>
</div>
</div>
</div>