Currently, DMLInterpreter.eval_and_print() is defined as
def eval_and_print(self, expr: str) -> Delayed[tuple[dmf_lang.Type, Any]]:
print(f"Interactive cmd: {expr}")
def on_val(pair: tuple[dmf_lang.Type, Any]) -> None:
ret_type, val = pair
if ret_type is dmf_lang.Type.ERROR:
print(f" Caught exception ({type(val).__name__}): {val}")
elif ret_type is dmf_lang.Type.NO_VALUE:
print(f" Interactive command returned without value.")
else:
print(f" Interactive cmd val ({ret_type.name}): {val}")
return self.evaluate(expr).then_call(on_val)
If all goes well, it prints out the return type and value, but it does so using the Python conversion routines, so you get things like
Interactive cmd: (1,1)'s drop
Interactive cmd val (DROP): Drop[Pad(1,1), 0.6300541919999999 μl of unknown]
This is nice as a trace for the Python developer, but it would be nice if both the type and the value were printed in a way that matched the syntax of DML, something more like
Interactive cmd val (a drop): 0.630 μl of unknown at (1,1)
This would require two changes. First, we would need to have a way to map types to strings. This could be done as part of Type, but I'm a little leery of doing that, as the types are really still somewhat independent of the language. So it might make more sense to put it in DMFInterpreter or even DMLInterpreter. (Yeah, like that isn't confusing.) But if I'm going to do this, it would be nice if Func.type_error() and possibly even the exceptions TypeMismatchError and ConversionError use them rather than just using type.name.
Actually, for that one, we may want to leave the exceptions as they are and change the ret_type is Type.ERROR branch to do the transformation, possibly by adding a pretty-print method on EvaluationError and maybe making TypeMismatchError a CompilationError which also pretty-prints.
Since Type also has the notion of the compiler registering conversions (and thereby breaking language independence), I guess we can use the same notion to allow the language to register print forms or provide a mapping, with the notion that if the print form is unspecified, you fall back to the Python conversion.
The second part is changing the way values are printed. Currently, this is simply done by a str conversion, as shown above, and in the print expression, it's done by calling print(). There's also a str built-in that's currently defined as
In theory, we should just be able to add extra methods onto that and the closest one to the actual type would be used. If we register that Func with Type, then it could have a pretty_print(val) method on Type that looked there to see how to format, and since it had a default of str, it would be guaranteed to succeed.
We could then modify
def visitPrint_expr(self, ctx:DMFParser.Print_exprContext) -> Executable:
arg_text = (self.text_of(c) for c in ctx.vals)
def print_vals(*vals: Sequence[Any]) -> Delayed[BoundImmediateAction]:
def do_print() -> None:
print(*vals)
name = f"print({', '.join(arg_text)})"
return Delayed.complete(BoundImmediateAction(do_print, name = name))
vals = tuple(self.visit(c) for c in ctx.vals)
sig = Signature.of(tuple(v.return_type for v in vals), Type.ACTION)
return self.use_callable(print_vals, vals, sig)
to add a call to Functions["STRING"] into each arg path in vals, meaning that what comes to print_vals would be a Sequence[str]. (The alternative would be to do the work in print_vals(), but then (1) we'd need to allow for a conversion potentially not being immediate and (2) we'd need to squirrel away a list of types for the arguments. It's probably easier just to let them happen as the values are produced.)
Migrated from internal repository. Originally created by @EvanKirshenbaum on Jun 03, 2023 at 3:06 PM PDT.
Currently,
DMLInterpreter.eval_and_print()
is defined asIf all goes well, it prints out the return type and value, but it does so using the Python conversion routines, so you get things like
This is nice as a trace for the Python developer, but it would be nice if both the type and the value were printed in a way that matched the syntax of DML, something more like
This would require two changes. First, we would need to have a way to map types to strings. This could be done as part of
Type
, but I'm a little leery of doing that, as the types are really still somewhat independent of the language. So it might make more sense to put it inDMFInterpreter
or evenDMLInterpreter
. (Yeah, like that isn't confusing.) But if I'm going to do this, it would be nice ifFunc.type_error()
and possibly even the exceptionsTypeMismatchError
andConversionError
use them rather than just usingtype.name
.ret_type is Type.ERROR
branch to do the transformation, possibly by adding a pretty-print method onEvaluationError
and maybe makingTypeMismatchError
aCompilationError
which also pretty-prints.Since
Type
also has the notion of the compiler registering conversions (and thereby breaking language independence), I guess we can use the same notion to allow the language to register print forms or provide a mapping, with the notion that if the print form is unspecified, you fall back to the Python conversion.The second part is changing the way values are printed. Currently, this is simply done by a
str
conversion, as shown above, and in theprint
expression, it's done by callingprint()
. There's also astr
built-in that's currently defined asIn theory, we should just be able to add extra methods onto that and the closest one to the actual type would be used. If we register that
Func
withType
, then it could have apretty_print(val)
method onType
that looked there to see how to format, and since it had a default ofstr
, it would be guaranteed to succeed.We could then modify
to add a call to
Functions["STRING"]
into each arg path invals
, meaning that what comes toprint_vals
would be aSequence[str]
. (The alternative would be to do the work inprint_vals()
, but then (1) we'd need to allow for a conversion potentially not being immediate and (2) we'd need to squirrel away a list of types for the arguments. It's probably easier just to let them happen as the values are produced.)Migrated from internal repository. Originally created by @EvanKirshenbaum on Jun 03, 2023 at 3:06 PM PDT.