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

Improved printing support #380

Merged
merged 1 commit into from
Apr 18, 2016
Merged

Improved printing support #380

merged 1 commit into from
Apr 18, 2016

Conversation

EliasC
Copy link
Contributor

@EliasC EliasC commented Apr 15, 2016

This commit improves the printing support and fixes #352 and fixes #320.
The following list summarizes the current printing behavior:

  • Reference types T are printed as T@0x012345, where the hexadecimal
    value is the address of the object. The same thing goes for futures,
    streams, arrays and ParT-values. null is printed as T@0x0.
  • Values whose type isn't statically known cannot be printed. This
    includes any polymorphic values.
  • Closures cannot be printed.
  • Values of embedded types cannot be printed. You can (and should) drop
    down to C if you really need to print such a value (or closures or
    polymorphic values for that matter).
  • Ranges are printed as [1..10 by 1]. The by part is always included
    for simplicity.
  • Maybe types are printed like they should, although the generated code
    is a bit nasty. For each maybe type, a string is allocated for the
    sole purpose of being printed. The length of this string is
    approximated by summing approximations of the lengths of all
    subexpressions. Strings use their dynamic lengths and tuples the sum
    of the approximations of their contents. All other lengths are
    approximated as the length of their type plus 30 (compare with how
    reference types are printed). The 30 should be enough to hold any
    addresses, integers or reals. It would be better to calculate a
    maximum depending on the type, but if you're doing things like
    printing Maybes, you probably don't care about performance anyway.
  • Tuples are also printed like they should, and since their shape is
    known statically, the code isn't as bad.
  • Values of void type are always printed as ()
  • Strings, chars, ints, booleans and reals are printed like you would
    expect. The only news here is proper printing of booleans as true
    and false.

The existing tests already test much of the printing, and some of them
have been updated to align with the new syntax. The test printf tests
some of the new printing.

Testing this has reminded me that the lack of proper inference for
null and bottom is annoying, but fixing this does not belong in this
PR.

@kikofernandez
Copy link
Contributor

the error doesn't seem to have anything to do with this PR. The error detected by the CI server is related to the ParTs. Reviews of this PR should be done with care (just in case)

@kikofernandez
Copy link
Contributor

I am not sure why the CI printed this error:

encorec: I don't know how to translate Bottom to pony.c
./test.sh: line 34: ./printf: No such file or directory

As I said, the reviewer of this PR should proceed with caution. ParTs have produced an error but the error mentioned above was raised in the same build

@EliasC
Copy link
Contributor Author

EliasC commented Apr 15, 2016

No, that's me being sloppy... Had forgotten a type annotation in the test. Should be working now!

@TheGrandmother
Copy link
Contributor

I have tested this and it works on my machine and the tests pass and the code looks pretty :)

@albertnetymk
Copy link
Contributor

It's unclear to me why printing closure and other things are disabled, while printing future is allowed. IMO, having pointer address is good default for to_str.

Should Tertiary be Ternary? https://blogs.msdn.microsoft.com/ericlippert/2010/02/18/whats-the-difference-between-ternary-and-tertiary/

The code for printing Just is quite elaborate; shouldn't this be implemented as to_str on encore level instead of in the compiler directly?

The type change in range is rather insightful; possibly negative ranges never worked.

It's better to limit touched/new lines below 80 columns, IMO.

@EliasC
Copy link
Contributor Author

EliasC commented Apr 17, 2016

It's unclear to me why printing closure and other things are disabled, while printing future is allowed. IMO, having pointer address is good default for to_str.

My motivation was that futures are objects (values) while closures are functions. The concept of identity (which is what we would print) makes sense for a future, but not for a function. We could print the address of the closure, but if someone ever decides to rely on this printing, we would lose possible optimization opportunities of for example reusing equivalent closures.

Printing polymorphic values breaks the polymorphic abstraction. Just as you cannot (or at least should not be able to) compare the equality of two polymorphic values (because you can't be sure that there is a well-defined notion of equality for the actual type), you shouldn't be able to print a polymorphic value. If you need it for debugging purposes, you can embed the pointer and print it.

Should Tertiary be Ternary?

Yes! Fixing now.

The code for printing Just is quite elaborate; shouldn't this be implemented as to_str on encore level instead of in the compiler directly?

Yes, it's a bit complex... The problem with implementing it on the encore level is that we have no polymorphic functions. We would need a printing function of type (Maybe a, a -> void) -> void, where the second argument is a function that can print an a, and we would need to infer which function to use. I'm envisioning a future solution where printing is solved by boxing the arguments and calling the toString method. Maybe Int would then be translated into MaybeObject<Integer>, and both of these classes would implement the Showable trait.

The type change in range is rather insightful; possibly negative ranges never worked.

I think they worked, but probably through typecasting somehow. This makes more sense anyway!

It's better to limit touched/new lines below 80 columns, IMO.

Maybe I was a bit sloppy. Fixing this with the Ternary change.

@EliasC
Copy link
Contributor Author

EliasC commented Apr 17, 2016

Fixed Ternary and line widths.

@albertnetymk
Copy link
Contributor

I disagree about the comment on printing closures. Printing a closure is printing its string representation; it could be its identity or source code. Either is fine, but disallowing printing of closures is unreasonable, IMO.

p = console.log
f = () -> 1
p f
p "#{f}"
[Function]
function () {
    return 1;
  }

I don't think this is similar or equivalent to equality, just like Show and Eq are different typeclasses.

Yes, indeed, need dynamic dispatch to implement printing Maybe in encore directly; I overlooked it.

This commit improves the printing support and fixes #352 and fixes #320.
The following list summarizes the current printing behavior:

* Reference types `T` are printed as `T@0x012345`, where the hexadecimal
  value is the address of the object. The same thing goes for futures,
  streams, arrays, ParTs and closures. `null` is printed as `T@0x0`.

* Values whose type isn't statically known cannot be printed. This
  includes any polymorphic values.

* Values of embedded types cannot be printed. You can (and should) drop
  down to C if you really need to print such a value (or closures or
  polymorphic values for that matter).

* Ranges are printed as `[1..10 by 1]`. The `by` part is always included
  for simplicity.

* Maybe types are printed like they should, although the generated code
  is a bit nasty. For each maybe type, a string is allocated for the
  sole purpose of being printed. The length of this string is
  approximated by summing approximations of the lengths of all
  subexpressions. Strings use their dynamic lengths and tuples the sum
  of the approximations of their contents. All other lengths are
  approximated as the length of their type plus 30 (compare with how
  reference types are printed). The 30 should be enough to hold any
  addresses, integers or reals. It would be better to calculate a
  maximum depending on the type, but if you're doing things like
  printing `Maybe`s, you probably don't care about performance anyway.

* Tuples are also printed like they should, and since their shape is
  known statically, the code isn't as bad.

* Values of `void` type are always printed as `()`

* Strings, chars, ints, booleans and reals are printed like you would
  expect. The only news here is proper printing of booleans as `true`
  and `false`.

The existing tests already test much of the printing, and some of them
have been updated to align with the new syntax. The test `printf` tests
some of the new printing.

Testing this has reminded me that the lack of proper inference for
`null` and `bottom` is annoying, but fixing this does not belong in this
PR.
@EliasC
Copy link
Contributor Author

EliasC commented Apr 18, 2016

Reluctantly added support for printing closures... ;)

@albertnetymk
Copy link
Contributor

For record purpose, I am the one who insisted in adding the closure-printing features.

@albertnetymk albertnetymk merged commit 52dc242 into parapluu:development Apr 18, 2016
@TheGrandmother
Copy link
Contributor

For the record. I agree with @albertnetymk that printing closures is pretty nice!

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

Successfully merging this pull request may close these issues.

Maybe types and tuples don't get printed properly. Print argument of arbitrary type
5 participants