-
Notifications
You must be signed in to change notification settings - Fork 26
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
Print argument of arbitrary type #320
Comments
Your solution does not seem to be a good solution. Why should |
Yes, you're right, I have checked that and the printing results of |
History repeats itself :) #46 I think printing a polymorphic value should not be allowed as it breaks the abstraction of parametricity. Also, we cannot be sure that the actual type is something that has a sensible string representation (it could be a closure for example) unless we have some kind of bounded polymorphism (something like |
To put an end to this, I suggest checking the arguments of |
I found the typeToPrintfFstr :: Ty.Type -> String
typeToPrintfFstr ty
| Ty.isIntType ty = "%lli"
| Ty.isRealType ty = "%f"
| Ty.isStringObjectType ty = "%s"
| Ty.isStringType ty = "%s"
| Ty.isCharType ty = "%c"
| Ty.isBoolType ty = "bool<%zd>"
| Ty.isRefType ty = show ty ++ "<%p>"
| Ty.isFutureType ty = "fut<%p>"
| otherwise = case translate ty of
Ptr something -> "%p"
_ -> error $ "Expr.hs: typeToPrintfFstr not defined for " ++ show ty and in -- count("{}", stringLit) = n
-- E |- arg1 : t1 .. E |- argn : tn
-- ---------------------------------------------
-- E |- print(stringLit, arg1 .. argn) : void
doTypecheck e@(Print {args = []}) = do
let meta = emeta e
eFormatString = setType stringType $ StringLiteral meta "\n"
return $ setType voidType e {args = [eFormatString]}
doTypecheck e@(Print {args = [arg]}) =
do eArg <- doTypecheck arg
let meta = emeta e
eFormatString = setType stringType $ StringLiteral meta "{}\n"
let newArgs = [eFormatString, eArg]
return $ setType voidType e {args = newArgs}
doTypecheck e@(Print {args}) =
do eArgs <- mapM typecheck args
let meta = emeta e
fst = head eArgs
rest = tail eArgs
sugaredFst = fromJust $ getSugared fst
unless (isStringLiteral sugaredFst) $
tcError $ "Formatted printing expects first argument '" ++
show (ppSugared fst) ++ "' to be a string literal"
let formatString = stringLit sugaredFst
noArgs = T.count (T.pack "{}") (T.pack formatString)
unless (noArgs == length rest) $
tcError $ "Wrong number of arguments to format string. " ++
"Expected " ++ show noArgs ++ ", got " ++
show (length rest) ++ "."
let eFormatString = setType stringType $
StringLiteral meta formatString
newArgs = eFormatString : rest
return $ setType voidType e {args = newArgs} |
@PhucVH888: Your first snippet is part of the backend (that generates C-code from Encore code) and it finds the correct format specifier for the resulting Your second snippet is the type checking code for the |
@EliasC Did you implement this fix? What is the status on this? |
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.
Fixed (by disallowing printing of polymorphic values) by #380 |
I got this error message when I defined a method to print an argument of arbitrary type.
Here is the example code. At first, I intended to post the question, however, I found the simple solution later, so I am not sure if it is suitable to post it here.
Solution: Instead of using
print x
directly, I slightly change toprint (Just x)
and then it works well. Just in case others can have the same problem to me in the future.The text was updated successfully, but these errors were encountered: