<rking>
eam_: Iunno. It's hard to say what the right way to map a string to an integer might be. Leading zeros have the "octal" meaning in some contexts.
<eam>
certainly there should be one method, yeah?
<drbrain>
eam: for example: sprintf "%d", "5 cats" #=> ArgumentError
<eam>
perl doesn't have this split-brain behavior
<drbrain>
eam: to_i is like atoi(3)
<drbrain>
Integer is strict
<eam>
so ruby has multiple implementations of string => integer
jstemmer has quit [Ping timeout: 256 seconds]
<eam>
that's ... unfortunate
<drbrain>
to_i is better for string processing, Integer is better for strict handling
ddd has quit [Quit: fixing client]
<drbrain>
no, it's very fortunate
sailias has joined #ruby-lang
ddd has joined #ruby-lang
<eam>
hahahaaha, we can agree to disagree on that one
<drbrain>
I can choose how to compose data properly since I have choice
matti has left #ruby-lang ["8-X"]
<lewis1711>
ruby isn't flawless, but I don't see what behaviour you'd have instead
<lewis1711>
ie, if you wanted to convert an octal number in a string
jstemmer has joined #ruby-lang
<eam>
lewis1711: surely a consistent conversion method
<drbrain>
before Integer existed you needed to check "cats".to_i to see if 0 meant the string started with a "0" or not
<lewis1711>
such as?
<eam>
drbrain: yeah I get why this problem might occur
<eam>
lewis1711: as I said, for example Perl has a consistent conversion
<drbrain>
eam: what value does "cats" have in perl?
<eam>
not aware of any popular language implementations that freely mix stuff like this in the stdlib
<drbrain>
I don't know enough perl ☹
<eam>
drbrain: 0 numeric
randallagordon has joined #ruby-lang
ddd has quit [Client Quit]
<drbrain>
so how do you get "there is no number in 'cats'"?
<lewis1711>
though looking at it again - an octal number is still an integer
<eam>
Scalar::Util::looks_like_number()
ddd has joined #ruby-lang
<eam>
the point is that there's one uniform process (across all core stdlib) to go from string -> number
<eam>
not contextual
<eam>
this is the first language implementation I've encountered (I think) where this isn't the case
<drbrain>
Integer doesn't string -> number
<Aria>
That's because there's no one true definition of string -> number. Strings are essentially data without mentioning their type.
<drbrain>
it does object -> number
<eam>
Aria: there is
<lewis1711>
I think the error message should be clearer
TheNotary has quit [Quit: Leaving]
<drbrain>
lewis1711: it is in 2.0.0: -e:1:in `sprintf': invalid value for Integer(): "08" (ArgumentError)
<lewis1711>
drbrain: it could be clearer than that, mention octals
<eam>
drbrain: yes
<drbrain>
eam: why?
<eam>
because it is. The implementation is consistent
<drbrain>
that's not a reason
<Aria>
Consistency is overrated when it's often or even usually the wrong answer.
<drbrain>
absent ruby, perl, or whatever, why is "5 cats" a number?
<eam>
it's not a question of the rules of parsing strings into numbers being complex or arbitrary, it's an issue of not having more than one competing implementations in the core lib
<drbrain>
eam: there is only one implementation, String#to_i
<drbrain>
if you want to convert arbitrary objects to integers, use Kernel#integer
<drbrain>
#Integer
<Aria>
I personally want at LEAST hexadecimal, decimal and base64 in a programming language I use every day.
<drbrain>
eam: also, note that #to_i, #to_s and other short-name are cast-like operators that are fuzzy
<drbrain>
Integer, URI, Float, etc. are strict conversion
<drbrain>
and #to_int, #to_str, etc are for conversion of alternate representations
<eam>
Aria: that's fine, just don't include different implementations
<Aria>
What does the implementation matter? It's the interface that's important.
<drbrain>
eam: then ruby wouldn't be ruby anymore
<eam>
very odd and abnormal design decision
<Aria>
Seems normal to me. C has many conversion functions, perl has its 'number-like' scalar interpretation (plus wacky stuff like setting an object's scalarism to be something other than it seems...), Java has many, many conversions.
<Aria>
If anything, perl's rules are weird in that 'scalarism' is orthogonal to the other properties of a variable, and it's pretty fast and loose with the conversions, since the operators, not the variable, supply the interpretation.
<eam>
no, none of those implementations have different type conversion functions
<eam>
int -> float has very consistent rules in C
<eam>
ruby is the first implementation I've seen which has two totally separate core functions for implicit type conversion
<eam>
this is very surprising
<drbrain>
C does not define string -> integer
<eam>
correct -- and it's consistent in that
<eam>
C converts other types
<drbrain>
eam: uh, there is only one implicit type conversion in Ruby for String -> Integer
<eam>
poerl does define string -> integer, and does not contain multiple conversion methods
<eam>
perl^
crudson1 has joined #ruby-lang
<drbrain>
and sprintf in ruby does not use implicit type conversion, only explicit
<eam>
those words don't mean what you think they mean
<eam>
there are no explicit type conversions in the code I included above
<drbrain>
sprintf tried to explicitly convert "08" into an Integer at your direction
<drbrain>
such a thing is not possible
<drbrain>
that's what "%d" in the format string means to ruby
<eam>
that's implicit, not explicit. Without implicit conversion of the argument (which is of type Integer) sprintf would raise when handed a String
<eam>
again, that is not what those terms mean
PantsMeh has joined #ruby-lang
<Aria>
There's aton and ntoa in the c stdlib.
<drbrain>
I think comparing C to ruby here is the worst idea possible
abstr4ct has quit [Ping timeout: 256 seconds]
<Aria>
Indeed. Very different ideas of what 'data' and 'variables' mean.
<drbrain>
and I still don't know why a regular person would consider "5 cats" a number
<eam>
I think you're fundamentally misunderstanding the difference between implicity type conversion and functions
<drbrain>
regular people don't know what "type conversion" is
<drbrain>
if you want to make a feature request to change the behavior of Kernel#integer and all the #to_i methods to be consistent, you'll need to explain why
<Aria>
Ruby has none that are truly implicit, then. There's some behind the scenes, but they call well-defined methods. Functions!
<drbrain>
part of that is going to be why "5 cats" is a number
<drbrain>
↑ yes
<Aria>
Heh, indeed. Also why "cats 5" is or is not. And why "5" is or is not.
<drbrain>
and why "I have 5 cats" is or is not
mistym has joined #ruby-lang
mistym has quit [Changing host]
mistym has joined #ruby-lang
tylersmith has quit [Quit: tylersmith]
<Aria>
And why "" is or is not.
<eam>
Aria: again, if you pass a String into a function that takes Integers and it handles it, it's an implicit conversion (regardless of how you implemented the conversion)
<Aria>
And internally, explicit. Turtles all the way down.
<Aria>
And it's not part of the runtime, it's part of the core library. It's exposed.
<eam>
Aria: do I need to explain the difference between implementation and internals?
<Aria>
Do I need to explain that internals have implementations, and implementations have internals?
<eam>
it's very confusion behavior, other platforms don't have this problem
<eam>
confusing even
<Aria>
Indeed. And ruby doesn't have a problem with it ;-)
<Aria>
There's only one method that will be called for you, the short version.
<eam>
drbrain: as for why a given string is a number or not, that's per the implementation's rules. And generally there's /one/ implementation per platform, not two
<drbrain>
eam: if you use the latest ruby it tells you exactly why the conversion attempt failed
<eam>
drbrain: that's more helpful, but still doesn't make the inconsistency any less weird
<drbrain>
eam: there's only one way to convert a String to an Integer, and that is String#to_i
toertore has quit [Quit: This computer has gone to sleep]
<drbrain>
there is also a way to convert any object to an Integer, and that is Kernel#Integer
<eam>
logically inconsistent, as Strings are Objects
idkazuma has quit [Remote host closed the connection]
<eam>
first statement is false
<drbrain>
but objects are not strings
<eam>
no one said they were
<drbrain>
I don't see that there is a requirement on commutativity
<Aria>
Indeed not. Otherwise having a decode_base64 function would break the world.
<eam>
irrelevant as to the inaccuracy of the statement " there's only one way to convert a String to an Integer"
<Aria>
Since that's another way to convert a string to an integer.
<Aria>
I hate trolls.
<eam>
I hate it when people construe honest feedback about confusing language behavior as a troll
<eam>
you guys are being really obnoxious
<eam>
anyway I'm done
<Aria>
Ruby 0.9 was years ago.
<Aria>
And the existing behavior is useful.
chimkan has quit [Read error: No route to host]
<Aria>
And unsurprising when you use it. If you assume there's only one way to do all things, Ruby will surprise you in a great many ways.
<eam>
unsurprising - HA
techlife has quit [Ping timeout: 276 seconds]
chimkan has joined #ruby-lang
<eam>
it's a complete outlier
<Aria>
Never surprised me or anyone I've taught.
<eam>
an entire office of folks who know many, many languages are WTF'ing at this right now
<Aria>
Well-defined "accepting" conversion, and a "strict" conversion that throws.
<eam>
this is not something that happens in other platforms
lcdhoffman has quit [Quit: lcdhoffman]
<eam>
just take the feedback
<Aria>
How about "never gonna happen, this is ruby 2.0, not 0.1"
<drbrain>
matz programmed our brains to accept that both are useful, and they are
<Aria>
This language is old, mature, and has a great quantity of existing work on the existing behavior.
pygmael has joined #ruby-lang
<eam>
you're confusing "can fix" with "should fix"
<Aria>
Behavior that's quite useful.
<eam>
I completely understand unfixable bugs
<bnagy>
plus, lobbing up on IRC and acting like a wanker is not 'feedback'
<eam>
bwahahaha
<eam>
ok kids, later
soknee has quit [Quit: Leaving.]
<Aria>
feedback.status = :NOTABUG
<Aria>
Especially since the only 'implicit' conversion is completely consistent.
codejury_ has quit [Remote host closed the connection]
techlife has joined #ruby-lang
codejury has joined #ruby-lang
slyphon has joined #ruby-lang
lcdhoffman has joined #ruby-lang
jonahR has joined #ruby-lang
TheNotary has joined #ruby-lang
t_ has quit [Read error: Operation timed out]
t_ has joined #ruby-lang
symm-_ has quit [Ping timeout: 246 seconds]
TheNotary has quit [Quit: Leaving]
chessguy has quit [Remote host closed the connection]
symm- has joined #ruby-lang
dustint has joined #ruby-lang
<lewis1711>
this is almost as bad as the time I asked why the ruby interpreter couldn't pick up on misspelled method names until run time
<lewis1711>
and everyone got extremely upset that I'd bring that up, and one person, ignored, calmly and clearly told me why. granted that was in #ruby I think
<whitequark>
#ruby
Gaelan has joined #ruby-lang
<whitequark>
that explains everything
sailias has quit [Quit: Leaving.]
* lewis1711
nods sagely
havenwood has joined #ruby-lang
chao has joined #ruby-lang
wallerdev has joined #ruby-lang
lsegal has joined #ruby-lang
Guest85414 has joined #ruby-lang
amerine has quit [Quit: Computer has gone to sleep.]
soknee has joined #ruby-lang
Domon has joined #ruby-lang
Technodrome has joined #ruby-lang
xxaM has quit [Remote host closed the connection]
amerine has joined #ruby-lang
gregmore_ has quit [Remote host closed the connection]
xxaM has joined #ruby-lang
chessguy has joined #ruby-lang
lcdhoffman has quit [Quit: lcdhoffman]
lcdhoffman has joined #ruby-lang
lcdhoffman has quit [Client Quit]
pygmael has quit [Quit: pygmael]
randallagordon has quit [Ping timeout: 256 seconds]
chimkan has quit [Quit: chimkan]
randallagordon has joined #ruby-lang
woollyams has joined #ruby-lang
gabito has joined #ruby-lang
Aria has quit [Read error: Connection reset by peer]
Aria has joined #ruby-lang
matti has joined #ruby-lang
pr0ton has quit [Ping timeout: 256 seconds]
gabito has quit [Remote host closed the connection]
Tectonic has joined #ruby-lang
gregmoreno has joined #ruby-lang
fosky has quit [Remote host closed the connection]
Gaelan has quit [Remote host closed the connection]
Gaelan has joined #ruby-lang
elight has quit [Remote host closed the connection]
arooni-mobile has quit [Ping timeout: 256 seconds]
tylersmith has quit [Quit: tylersmith]
Gaelan has quit [Ping timeout: 264 seconds]
Technodrome has quit [Quit: Technodrome]
kain has joined #ruby-lang
lewis1711 has quit [Quit: ChatZilla 0.9.90 [Firefox 19.0.2/20130307122351]]
jonahR has quit [Quit: jonahR]
Technodrome has joined #ruby-lang
MehLaptop has joined #ruby-lang
tsion has joined #ruby-lang
tsion has quit [Changing host]
tsion has joined #ruby-lang
tomzx_mac has quit [Ping timeout: 264 seconds]
dhruvasagar has joined #ruby-lang
CoverSlide has quit [Ping timeout: 256 seconds]
CoverSlide has joined #ruby-lang
dhruvasagar has quit [Remote host closed the connection]
ivanoats has quit [Remote host closed the connection]
Wardrop has joined #ruby-lang
Domon has joined #ruby-lang
<Wardrop>
Does anyone the best way to get the file and line a Proc is defined in?
<Wardrop>
I'm adding verbose logging to a framework of mine, and want to show the user which proc is currently running, and the filename and line seem to be the best way to do that
<tsion>
Wardrop: Try Proc#source_location.
Domon has quit [Remote host closed the connection]
Domon has joined #ruby-lang
<Wardrop>
tsion: nice, that seems to work. Otherwise I was going to have to use regex on the #inspect output
pr0ton has joined #ruby-lang
pr0ton has quit [Client Quit]
kgrz has joined #ruby-lang
dhruvasagar has joined #ruby-lang
mistym has quit [Remote host closed the connection]
Nisstyre-laptop has quit [Quit: Leaving]
kgrz has quit [Ping timeout: 245 seconds]
randym has quit [Ping timeout: 258 seconds]
herpless___ has quit [Ping timeout: 258 seconds]
akahn has quit [Ping timeout: 258 seconds]
|Vargas| has joined #ruby-lang
|Vargas| has joined #ruby-lang
kgrz has joined #ruby-lang
dhruvasagar has quit [Ping timeout: 276 seconds]
Wardrop has left #ruby-lang [#ruby-lang]
dhruvasagar has joined #ruby-lang
<amerine>
5 cats
<amerine>
heh
bzalasky has quit [Remote host closed the connection]
smt has joined #ruby-lang
spuk has quit [Ping timeout: 260 seconds]
tpope has joined #ruby-lang
bzalasky has joined #ruby-lang
Technodrome has quit [Quit: Technodrome]
smt has left #ruby-lang [#ruby-lang]
vlad_starkov has joined #ruby-lang
Technodrome has joined #ruby-lang
MehLaptop has quit [Remote host closed the connection]
Oloryn_lt2 has quit [Quit: Leaving.]
Tectonic has quit []
chessguy has quit [Remote host closed the connection]
spuk has joined #ruby-lang
nXqd has joined #ruby-lang
tcopp has quit [Ping timeout: 256 seconds]
workmad3 has joined #ruby-lang
chendo has joined #ruby-lang
crynix has joined #ruby-lang
chendo has quit [Ping timeout: 245 seconds]
thebastl has joined #ruby-lang
chendo has joined #ruby-lang
wallerdev has quit [Quit: wallerdev]
dhruvasagar has quit [Quit: Lost terminal]
vlad_starkov has quit [Remote host closed the connection]
dkannan has joined #ruby-lang
mytrile has joined #ruby-lang
woollyams has quit [Ping timeout: 240 seconds]
dkannan_ has joined #ruby-lang
xxaM has quit [Ping timeout: 260 seconds]
dkannan has quit [Ping timeout: 256 seconds]
dkannan_ is now known as dkannan
mjio has quit []
workmad3 has quit [Ping timeout: 260 seconds]
gregmoreno has quit [Remote host closed the connection]
xxaM has joined #ruby-lang
dr_bob has joined #ruby-lang
solars has joined #ruby-lang
benlovell has joined #ruby-lang
Technodrome has quit [Quit: Technodrome]
havenwood has quit [Remote host closed the connection]
nertzy has joined #ruby-lang
symm- has quit [Ping timeout: 256 seconds]
solars has quit [Ping timeout: 248 seconds]
havenwood has joined #ruby-lang
havenwood has quit [Remote host closed the connection]
MrWGW- has joined #ruby-lang
<MrWGW->
good evening
<MrWGW->
how would I, in one line, without three separate if statements, check to see if three variables are all non-nil?
<MrWGW->
i.e. if var != nil
<tsion>
MrWGW-: var1 && var2 && var3
<tsion>
That means non-nil and non-false
<bnagy>
[a,b,c].none? &:nil? is more accurate
<bnagy>
but uglier :)
<tsion>
If you don't want to mean non-false: !var.nil? && !var2.nil? && !var3.nil?
<bnagy>
:<
<tsion>
Yeah, pretty ugly. bnagy's list might be best
<bnagy>
I think collection.all? is probably prettiest, but that will be false if any are false or nil, as above
<MrWGW->
so if !var1.nil? && !var2.nil? && !var3.nil; # then the other stuff
solars has joined #ruby-lang
<MrWGW->
also can you require a file given as a variable? So a user can supply a filename, and that file will be evaluated?
glebm has joined #ruby-lang
<MrWGW->
I'm writing a simple program to start KVM VMs,
<MrWGW->
and to store the parameters of them in something like a VMware .vmx file, I thought I'd just store it in an actual Ruby file and just require the filename
<MrWGW->
is that possible?
<bnagy>
have you looked at libvirt?
<MrWGW->
and yes I realize a malicious psuedo-VMX could wreak havoc, but this code is only for use in my lab
<MrWGW->
bnagy: not an option on Illumos :)
Technodrome has joined #ruby-lang
<MrWGW->
or OmniOS to be precise
<bnagy>
it's not? I don't know what an illumos is, but if it's linux then it should Just Work
<bnagy>
not the crappy gui stuff, just virsh
<MrWGW->
nor is porting Joyent's SmartOS fabric controller an option, because it has behavior that I odn't want (it runs each KVM VM in its own zone, which is a drain on system resources)
<MrWGW->
bnagy: Illumos is a community-developed fork of OpenSolaris
<bnagy>
gives you xml domains for config properties and some basic commands
<MrWGW->
its at the heart of Joyent's SmartOS and public cloud services, the OmniOS server operating system, the OpenIndiana distro, and the Nexenta storage platform, among other projects
<MrWGW->
I'm writing my own lightweight tool to manage VMs on an Illumos box in my lab, partly for fun
<bnagy>
ok, then I'd probably look into storing machine params as yaml or something
<bnagy>
then build the raw command-line from that
<bnagy>
yaml is nice and human readable / editable
<MrWGW->
I might do that if I do a production release
<MrWGW->
but is it possible to require something based on a variable name?
<bnagy>
sure, require just takes a string
<MrWGW->
ok cool
vmoravec has joined #ruby-lang
judofyr has joined #ruby-lang
rippa has quit [Ping timeout: 240 seconds]
akahn has joined #ruby-lang
mytrile has quit [Ping timeout: 256 seconds]
Wardrop has joined #ruby-lang
glebm has quit [Quit: Computer has gone to sleep.]
pbjorklund has quit [Read error: Operation timed out]
<tsion>
crynix: My first guess is differences between different Ruby versions
<tsion>
_why's guide was written for 1.8.something, and you're probably running 1.9 or 2.0
agarie has joined #ruby-lang
<crynix>
I'm surprised they made changes to the way scope is handled.
<crynix>
How could I adjust the code to be compatible for 1.9/2.0?
<judofyr>
crynix: yeah, in 1.9 block variables shadows other local variables
<crynix>
Define shadows.
<tsion>
crynix: Use a different variable name for the block or the outside variable
jhn_ has joined #ruby-lang
<judofyr>
tsion: that won't work.
<tsion>
crynix: When one variable 'a' shadows another 'b', then variable 'b' is just hidden from sight and you can't access 'b' in that scope
<judofyr>
tsion: he wants "electrocuted" in the last line.
<tsion>
judofyr: woops... I wasn't thinking about the actual problem, just avoiding the shadowing
<crynix>
judofyr: rescued is the expected output
<judofyr>
crynix: oh, sorry
<crynix>
But since handling of scope is change that's irrelevant.
<crynix>
*has been changed
<judofyr>
crynix: I get expected in 1.9
glebm has joined #ruby-lang
<crynix>
Ruby version?
dr_bob has quit [Quit: Leaving.]
<judofyr>
crynix: yeah. and actual in 1.8
<crynix>
Oh.
<crynix>
Whoops. I thought I was running 1.9
<crynix>
Turns out this computer has 1.8.7 on it. Time to compile Ruby from source!
jhn has quit [Quit: Page closed]
<tsion>
I must have been wrong about what I said earlier then. That example in _why's guide seems to show 1.9 behaviour
<crynix>
How stable is master of Ruby usually?
<tsion>
I have no idea, but why are going with master?
<crynix>
*trunk
<crynix>
tsion: Why not?
<drbrain>
crynix: it varies
<crynix>
*Why not go with the tip of the branch?
dhruvasagar has joined #ruby-lang
solars has quit [Ping timeout: 245 seconds]
dr_bob has joined #ruby-lang
* drbrain
remembers a bug in the nightly releases of firefox that would delete all the files in your downloads directory… which was typically the desktop on windows
<drbrain>
↑ that's why you don't go with the tip of the branch
<drbrain>
or, if you're cool with discovering dataloss and crash bugs, that's why you go with the tip of the branch
<tsion>
Sometimes the tip is too pointy
<bnagy>
twss
<crynix>
Let's cross our fingers than.
<crynix>
*then
<drbrain>
I've never heard of such a dangerous bug in ruby trunk, though
glebm has quit [Quit: Computer has gone to sleep.]
<crynix>
I know there was a bug that broke Github's enterprise mailing thing, but that's the worst I've heard.
<drbrain>
and that was in a release of Rails
<crynix>
Didn't realize. Thanks for the correction.
<drbrain>
specifically, a security fix that (for obvious reasons) didn't get wide-spread circulation before release
apeiros_ has joined #ruby-lang
JohnBat26 has joined #ruby-lang
glebm has joined #ruby-lang
lele|w has quit [Ping timeout: 246 seconds]
randym has joined #ruby-lang
herpless___ has joined #ruby-lang
mytrile has joined #ruby-lang
<crynix>
Wow.
<crynix>
That compiled quickly.
lele|w has joined #ruby-lang
tsion has quit [Quit: Leaving]
glebm has quit [Quit: Computer has gone to sleep.]
<MrWGW->
btw how do I create the socket in the first place?
<MrWGW->
i.e. like how oyu create a fifo with the command mkfifo
dr_bob has joined #ruby-lang
solars has quit [Ping timeout: 246 seconds]
Mon_Ouie has joined #ruby-lang
mbj has quit [Ping timeout: 240 seconds]
mixandgo has joined #ruby-lang
dkannan has joined #ruby-lang
r0bglees0n has joined #ruby-lang
rsl has quit [Quit: Computer has gone to sleep.]
lele|w has quit [Ping timeout: 246 seconds]
solars has joined #ruby-lang
vlad_starkov has quit [Remote host closed the connection]
<charliesome>
MrWGW-: theres a mkfifo syscall
vlad_starkov has joined #ruby-lang
solars has quit [Ping timeout: 256 seconds]
gnufied has joined #ruby-lang
lele|w has joined #ruby-lang
face has joined #ruby-lang
vlad_starkov has quit [Ping timeout: 264 seconds]
faces has quit [Ping timeout: 264 seconds]
<MrWGW->
right I know about mkfifo
<MrWGW->
but how do I create a socket?
solars has joined #ruby-lang
<MrWGW->
when I try to open it with UNIXSocket.new(path)
<MrWGW->
I get an ENOENT
blacktulip has joined #ruby-lang
Domon has quit [Remote host closed the connection]
flori has quit [Quit: leaving]
flori has joined #ruby-lang
weeb1e has quit [Quit: No Ping reply in 180 seconds.]
weeb1e has joined #ruby-lang
xxaM has quit [Quit: ZzZz]
Guest36393 has joined #ruby-lang
Guest36393 has quit [Client Quit]
soknee has joined #ruby-lang
nertzy has quit [Ping timeout: 256 seconds]
alessio_rocco has joined #ruby-lang
robbyoconnor has quit [Ping timeout: 256 seconds]
agarie has quit [Remote host closed the connection]
certaint1 has left #ruby-lang [#ruby-lang]
adambeynon has joined #ruby-lang
amerine has quit [Quit: Computer has gone to sleep.]
gnufied has quit [Ping timeout: 264 seconds]
gnufied has joined #ruby-lang
Squarepy has joined #ruby-lang
Squarepy has quit [Changing host]
Squarepy has joined #ruby-lang
gnufied has quit [Client Quit]
gnufied has joined #ruby-lang
KU0N has joined #ruby-lang
maxmanders has joined #ruby-lang
KU0N has left #ruby-lang [#ruby-lang]
maxmanders has quit [Quit: Computer has gone to sleep.]
sepp2k has joined #ruby-lang
sepp2k has quit [Client Quit]
sepp2k has joined #ruby-lang
GarethAdams has joined #ruby-lang
fosky has quit [Remote host closed the connection]
crudson1 has left #ruby-lang [#ruby-lang]
<shachaf>
If an array might have duplicates, is there an easy way to delete the first/last occurrence of a particular element?
<shachaf>
#delete deletes all of them.
<GarethAdams>
shachaf: well #uniq will leave one copy of each element but that doesn't sound like exactly what you want
<shachaf>
No, I want to go from [1,2,1,3,1] to [1,2,1,3] or [2,1,3,1] or something.
<shachaf>
I'm not sure it really matters which one of those in this case.
<judofyr>
shachaf: delete_at + index
<shachaf>
I guess that's the best you can do.
<shachaf>
Thanks.
dhruvasagar has quit [Ping timeout: 256 seconds]
dhruvasagar has joined #ruby-lang
nXqd_ has joined #ruby-lang
mbj has joined #ruby-lang
nXqd has quit [Ping timeout: 264 seconds]
chessguy has joined #ruby-lang
chessguy has quit [Remote host closed the connection]
Domon has joined #ruby-lang
Domon has quit [Remote host closed the connection]
Hanmac1 has joined #ruby-lang
<Hanmac1>
can someone tell me why ObjectSpace.each_object(Bignum).min may returns something like 3 or something like 0? and why they are Bignum and not fixnum?
<Ridders24>
How can I append the file, so that for every loop the data is presented on a new line, rather than overwriting the last, I can seem to get 'a' to work on this spreadsheet: http://pastebin.com/0sQVfhxG
<whitequark>
I currently see three solutions to this problem
<yorickpeterse>
ah, so you want a start and exit location
<whitequark>
first, I can make the method name a node on its own, then it's trivial
<whitequark>
second, I can add something like self_location and expr_location to *all* nodes. self_location will only highlight the +, expr_location will highlight the (...)
<whitequark>
third, I can make a subclass of Sexpr specifically for the (call) nodes with the custom metadata they need
<whitequark>
e.g. (lit) nodes do not need the self_location/expr_location.
<whitequark>
thoughts?
<yorickpeterse>
whitequark: why not add #start_location and #end_location to the node class?
<mbj>
whitequark: The highlighting is not restricted too call nodes? So the "first" option confuses me.
<whitequark>
also F5 the gist
vlad_starkov has quit [Ping timeout: 256 seconds]
<yorickpeterse>
hm
<yorickpeterse>
In that case I'd make the `+` a node
<whitequark>
yorickpeterse: because it doesn't make any sense? I have two *ranges*
<yorickpeterse>
Ripper currently uses Symbols for that which pisses me off
<yorickpeterse>
even for the stuff that actually are methods (e.g. ==)
<whitequark>
mbj: highlihting is not restricted to call nodes, of course
<whitequark>
all nodes which can be located in the source have associated source ranges
<whitequark>
(there is stuff like implicit (begin) nodes in compound statements like this: "a;b")
<mbj>
whitequark: So add expr_location to all nodes.
<mbj>
whitequark: And downside I do not see?
<whitequark>
mbj: 1) memory consumption 2) I don't think nodes to which expr_location is not applicable should have it
<mbj>
whitequark: 1) benchmark 2) initialize with nil on this cases?
<mbj>
I do not think 1k ranges do have such a high impact.
<whitequark>
1) most nodes do not require expr_location, so why store 4 fields instead of 3?
<whitequark>
mbj: it depends on the amount of source and nodes :)
<mbj>
whitequark: yeah
<whitequark>
mbj: what do you think about making the method name a node on its owh?
<mbj>
whitequark: We do not store 4 fields in case :expr_location is not in the metadata
<whitequark>
*own
<whitequark>
mbj: we do, if it's JRuby and it optimizes instance variables to offset storage
<whitequark>
(same for RBX I think)
<whitequark>
hence the subclassing suggestion, it'd avoid the storage cost
<mbj>
whitequark: Does JRuby can predict an ivar offset table from hash?
<yorickpeterse>
whitequark: what nodes do you think *don't* need location info?
<mbj>
yorickpeterse: I think this implicit begin "a;b" ?
<mbj>
I'd imagine heredocs do not leed location info.
<mbj>
s/leed/need/
<whitequark>
mbj: JRuby can compute an offset table for any case where ivar names converge at some point of time
<whitequark>
mbj: heredocs, of course, do
<whitequark>
mbj: this is a PITA but I can compute and represent location for heredocs, including nested heredocs
<whitequark>
actually, for anything which can be lexed.
<mbj>
whitequark: okay
<mbj>
whitequark: Why dont start with 4 fields for all nodes and optimize later?
<mbj>
whitequark: re JRuby I need to read more source ;)
<whitequark>
mbj: because this is a public interface for which dependent code cannot be trivially changed
scampbell has joined #ruby-lang
<whitequark>
for other things it could be easier, for example if I decide to not store SourceFile in the SourceRange
<whitequark>
but this requires significant API changes *and* sexp format changes
<yorickpeterse>
mbj: of course heredocs would
<yorickpeterse>
at least from an analysis perspective
<mbj>
yorickpeterse: Yeah, its is an array of ranges.
<yorickpeterse>
whitequark: also, I'm not sure how this would affect the sexp format
<yorickpeterse>
I mean, it doesn't when using Furnace::AST::Node since you add it as metadata
<whitequark>
yorickpeterse: to excise a field we will need to extract it into a node?
<yorickpeterse>
eh?
<whitequark>
(call nil :a) w/self_loc and expr_loc -> (call nil (lit :a)) w/ only self_loc
<mbj>
whitequark: If a public interface consumer must need to know in adwance wher #expr_location is possible or not the api is a PITA
Hanmac1 has left #ruby-lang [#ruby-lang]
<mbj>
whitequark: If we return nil on nodes that dont have them it acts like ruby-2.0 Enumerable#size
<whitequark>
mbj: this is exactly what I'm talking about
retro|cz has quit [Ping timeout: 256 seconds]
<injekt>
:/
<whitequark>
mbj: how about having a PrimitiveSexp which will forward expr_location to self_location and not store it, and CompoundSexp which will store both self_location and expr_location?
<whitequark>
distinct classes, distinct ivar offset tables, same duck type.
<mbj>
whitequark: That PrimitiveSexp will forward to parent / child / whatever ?
<whitequark>
mbj: no, to self_location of itself
wmoxam has joined #ruby-lang
<whitequark>
so for example for "1" (lit 1) both self_loc and expr_loc point at the "1"
<whitequark>
but for "1 + 2" (call ...) self_loc points at "+" and expr_loc at "1 + 2".
<mbj>
okay, got the point.
<mbj>
+1
<whitequark>
yorickpeterse ?
<mbj>
whitequark: Why we need a distinction between self_loc and expr_loc at all?
<whitequark>
mbj: um, I think I've explained it in the gist
<mbj>
whitequark: Because we need to highlight the full expression or the operator.
<whitequark>
yep.
<whitequark>
also, for heredocs, it would be highlighting either <<EOF or the text
<mbj>
whitequark: Was about to type this just after my question.
<whitequark>
and I think there'll be some other cases.
<yorickpeterse>
whitequark: I thought you were specifically talking about what fields to store the info in in a Node
swav_ has joined #ruby-lang
<yorickpeterse>
not how to store the nodes in the first place
<whitequark>
basically a distinction between a token which is critical to recognizing the expression, and the expression overall
<whitequark>
yorickpeterse: this is related
swav has quit [Read error: Connection reset by peer]
<mbj>
whitequark: What is self_loc with the ternary operator, two points?
<whitequark>
if by introducing additional nodes to the AST I can represent it in a more convenient way to work with, I'll do that
<whitequark>
mbj: hmm
<mbj>
whitequark: a ? b : c, self_loc would refer to "?" and ":"
<whitequark>
this actually boils down to whether I'll allow to represent range unions in a single SourceRange
<whitequark>
so far I'm opposed to it
<whitequark>
it has a significant runtime cost and only useful for some corner cases
<mbj>
whitequark: We could also have a special subclass for this.
<whitequark>
mbj: I'm not even sure if sexp format is appropriate, anymore
madb055 has joined #ruby-lang
<yorickpeterse>
what other format would you use?
<whitequark>
yorickpeterse: like Rbx AST
<mbj>
whitequark: As long we use Funace::AST::Node and avoid gazillions of subclasses +1
<whitequark>
mbj: well, that implies a gazillion of subclasses
<mbj>
whitequark: why? we could mix sexp and ast.
<whitequark>
wat?
<mbj>
whitequark: Node#type returns the sexp identifier
<mbj>
whitequark: Node#children the body.
<mbj>
whitequark: Or I have a big misunderstanding of Funace::AST::Node.
<whitequark>
the problem here is pretty simple
altrim has quit [Quit: Leaving.]
<yorickpeterse>
whitequark: I'm not following along entirely here (busy with work), but I don't really see the issue with Sexp
<whitequark>
yorickpeterse: Sexp cannot represent the metadata we need well enough
<whitequark>
btw, clang has getColonLoc(), getQuestionLoc() and getExprLoc()
<yorickpeterse>
if it's metadata, does it *have* to?
<whitequark>
for the ternary
retro|cz has joined #ruby-lang
<yorickpeterse>
You said it yourself: metadata doesn't belong in the AST (at least something along those lines)
<whitequark>
yorickpeterse: yes, because the whole point of the parser gem is proper metadata.
<TvL2386>
hi guys, I want to create an application that is able to configure network switches. Because I have multiple vendors and types, I want it to be modular. I'm thinking about Vendors, types, transport methods (ssh/https). Can anybody recommend me some literature or example app on how to accomplish something like this? (I'm used to plain/dirty programming but would really like to make something I'm proud of)
<whitequark>
yorickpeterse: well, maybe I was wrong
<yorickpeterse>
whitequark: then use Node#metadata?
<whitequark>
yorickpeterse: and what's inside?
<mbj>
whitequark: Mom, I have a misunderstanding. A structure where the first tuple item returns the type of the node is an "s-exp" for me.
<whitequark>
mbj: yep
<mbj>
whitequark: [:lit, 1] trivial sexp
<yorickpeterse>
whitequark: pass a Hash to it, keys get set as variables, add reader, done
<whitequark>
yorickpeterse: too slow and memory-hungry
<mbj>
whitequark: When we use Funace::AST::Node we are creating an ast. Not an sexp.
<mbj>
whitequark: ?
<yorickpeterse>
whitequark: I don't see how this is slower than the other solutions
anonymuse has joined #ruby-lang
<whitequark>
yorickpeterse: consider engines which are more clever than MRI: JRuby and Rbx
<yorickpeterse>
I'm also pretty sure it's actually not that slow since it's what I'm currently doing and having no issues with it
<whitequark>
they can optimize for instance variable access
<yorickpeterse>
*every* node with the exception of symbols (e.g. :+) have location details, no issues so far
<yorickpeterse>
(in my linter)
llaskin has joined #ruby-lang
<mbj>
whitequark: But when we use AST::Sexp#s we create AST::Node with sexp notation.
<whitequark>
yorickpeterse: *shrug* please compute the overhead for storing a Hash. the overhead for stroing an ivar is one machine word.
<mbj>
whitequark: So we never had an *real* sexp tree? Because we used AST::Node internally.
<whitequark>
mbj: "AST" doesn't mean "tons of subclasses". sexps are ASTs. Rbx's format is AST, too.
<mbj>
whitequark: I thought sexp must be an array of arrays.
<yorickpeterse>
whitequark: again, come up with some benchmarks first
<whitequark>
mbj: AST::Node is almost an array, except that it makes access to the first element easier
<yorickpeterse>
I seriously doubt it's going to be worth it to instead use a dozen classes that effectively do the same
<yorickpeterse>
Not to mention you'd end up storing similar amounts of data anyway
llaskin has quit [Changing host]
llaskin has joined #ruby-lang
<llaskin>
#{(date + 5).strftime("%m/%d/%Y")}#{(time + 600).strftime("%l:%M %p")} given that %l adds a whitespace when there is a single digit in the Hour field(so 8 is printed as " 8") and this runs multiple times throughout the day, sometimes it puts a space, sometimes it doesn't. How do I fix this so that it will print "04/03/2013 12:03 PM" as well as "04/03/2013 2:03 PM "
<yorickpeterse>
Also, since the Hash is not internally stored it will be garbage collected anyway
<yorickpeterse>
so it's not like it's a massive leak
<mbj>
whitequark: okay.
<mbj>
whitequark: back in sync.
<injekt>
llaskin: lstrip the whitespace
<whitequark>
yorickpeterse: (benchmarks) open jvisualvm; a=[]; 100000.times{a<<{range: rand..rand}}; measure the consumption.
chrismar035 has joined #ruby-lang
<yorickpeterse>
Good job on benchmarking something that has nothing to do with what the end code will be doing
<whitequark>
yorickpeterse: this is *exactly* what the end code will be doing
<whitequark>
creating tons of similar location hashes
<llaskin>
injekt: thanks that makes perfect space
<yorickpeterse>
whitequark: hey wtf, where did your ast/ directory go in Furnace
<whitequark>
yorickpeterse: gem 'ast'
<yorickpeterse>
right
<yorickpeterse>
you'll want to add that as a dep
<whitequark>
yorickpeterse: you don't need Furnace anymore
<yorickpeterse>
I don't see you storing the Hash there
<yorickpeterse>
You just use it to iterate over
<yorickpeterse>
Using that method you don't end up storing it somewhere which in turn would leak
hackeron has quit [Read error: Operation timed out]
<yorickpeterse>
if it were seriously that much of an issue I wouldn't be sitting at around 15MB of memory for my entire test suite
<whitequark>
yorickpeterse: right. now please read the docs on this method, which suggest that the user should override it
<mbj>
whitequark: Lets reverse the discussion. What API the user needs. Node#self_location Node#expression_location + some special stuff as #colon_location, ... for nodes like the ternary operator.
<mbj>
whitequark: Some nodes dont provide #self_lcoation and #expression_location
<yorickpeterse>
whitequark: tbh I think you're overcomplicating by something that can be resolved when it actually becomes a problem
<yorickpeterse>
s/by/
<mbj>
whitequark: We should define the API first and than think about an implementation.
<whitequark>
yorickpeterse: and they should, because proper runtimes (anything except MRI) optimize instance variable storage to offset
<mbj>
whitequark: We need a gist with all edge cases.
<whitequark>
yorickpeterse: (overcomplicating) I believe it couldn't be resolved, as this is going to be embedded deeply within the API. That's the main reason I'm discussing it now
<whitequark>
mbj: Right.
<whitequark>
The main problem with subclassing Nodes is that they would be then polymorphic by two unrelated factors
<yorickpeterse>
whitequark: you don't per se have to use that method. I just think it's a stupid reason to either 1. Go full Rbx and use dozens of classes (I've been there, hated it) 2. somehow modify the AST to be different (based on my understanding of your examples)
MartynKeigher has quit [Excess Flood]
vlad_starkov has joined #ruby-lang
<whitequark>
mbj: first, the `type', and second, the `class`
llaskin has left #ruby-lang [#ruby-lang]
<mbj>
whitequark: first the type sencod the API!
MartynKeigher has joined #ruby-lang
<mbj>
whitequark: From grouping the APIs we get our classes.
<whitequark>
and of course users are going to select the right codepath by looking at the `type'
<mbj>
whitequark: So :ternary, #self_loc #expression_loc #colon_loc ...
<mbj>
whitequark: Than we can group by API and get our classes. I expect 6-8 at maximum.
<mbj>
whitequark: Far easier than 181 in RBX ;)
<whitequark>
mbj: I believe that simultaneously making Nodes polymorphic by type and class is quite wrong
<mbj>
whitequark: Can be solved via a #location object.
<mbj>
whitequark: That contains the API.
<whitequark>
mbj: exactly what I was going to suggest.
<mbj>
whitequark: good point btw.
<whitequark>
for the consumers which mainly care about sexps, present a simple interface
<mbj>
whitequark: Dunno if compilers could "embed" the location object, but should be fast enough.
<whitequark>
for the consumers who need the full info, present a full one
<whitequark>
mbj: I believe they cannot
bryanl_ is now known as bryanl
<whitequark>
but yeah, it is much better than storing a Hash
<mbj>
whitequark: We could also store the informations to recover #location in a packed binary form.
<mbj>
whitequark: And unpack into real object on access.
<whitequark>
nah, that isn't going to matter. String is fatter than a class with one or two ivars
<mbj>
whitequark: I have in mind the jruby parser has one version with metadata and one without. The first is for consumers that need metadata the second for the actual jruby one.
voker57_ has joined #ruby-lang
Voker57 has quit [Ping timeout: 246 seconds]
<whitequark>
mbj: well, you do need precise location info for good runtime error reporting
<mbj>
whitequark: Because the overhead of storing the #location information was big.
<whitequark>
mbj: exactly. in this case, I know that parsing with metadata is going to be primary mode of operation, at least for me, so I'm going to optimize for it
<mbj>
whitequark: I think we can easily go the #location route, and can optimize it later.
soknee has joined #ruby-lang
<mbj>
whitequark: So we need polymorphic #location objects.
<whitequark>
mbj: yep
<mbj>
whitequark: ?
<mbj>
whitequark: okay
<mbj>
whitequark: So we are back at the gist and grouping by api.
<whitequark>
yep.
slyphon has quit [Ping timeout: 245 seconds]
changelog has joined #ruby-lang
<mbj>
whitequark: BTW I think this design is easier to test.
<changelog>
Hi everyone! Is this the place to ask about ruby's internals?
<mbj>
whitequark: Lets change selector to something better?
TvL2386 has quit [Remote host closed the connection]
<whitequark>
mbj: `method` would clash with standard names
<whitequark>
`selectors` is how methods are called in Smalltalk; I think it's good enough
scottj has joined #ruby-lang
<mbj>
whitequark: okay
bantic has joined #ruby-lang
<whitequark>
I'll be off for next ~40m. some examples of what is missing from the gist: modifier if, operator-assignment (||=), multiple assignment, regexp options, heredocs, string interpolation
wallerdev has joined #ruby-lang
<mbj>
whitequark: Having some operations trouble, when I find the time I'll add some stuff.
wallclockbuilder has joined #ruby-lang
mytrile has quit [Remote host closed the connection]
wallcloc_ has joined #ruby-lang
baba has quit [Ping timeout: 276 seconds]
wallclockbuilder has quit [Read error: Connection reset by peer]
wallclockbuilder has joined #ruby-lang
wallclo__ has joined #ruby-lang
jasiek_ has left #ruby-lang [#ruby-lang]
wallcloc_ has quit [Ping timeout: 260 seconds]
mistym has quit [Remote host closed the connection]
baba has joined #ruby-lang
wallclockbuilder has quit [Ping timeout: 245 seconds]
wyhaines has joined #ruby-lang
dkannan has quit [Quit: dkannan]
wallclockbuilder has joined #ruby-lang
wallcloc_ has joined #ruby-lang
jacktrick has joined #ruby-lang
wallclo__ has quit [Ping timeout: 245 seconds]
wallclo__ has joined #ruby-lang
wallclockbuilder has quit [Ping timeout: 255 seconds]
wallclockbuilder has joined #ruby-lang
mistym has joined #ruby-lang
mistym has joined #ruby-lang
mistym has quit [Changing host]
wallcloc_ has quit [Ping timeout: 256 seconds]
wallcloc_ has joined #ruby-lang
wallclo__ has quit [Ping timeout: 245 seconds]
dhruvasagar has quit [Ping timeout: 276 seconds]
wallclo__ has joined #ruby-lang
wallclockbuilder has quit [Ping timeout: 264 seconds]
wallcloc_ has quit [Ping timeout: 258 seconds]
mytrile has joined #ruby-lang
wallclockbuilder has joined #ruby-lang
bantic has quit [Quit: bantic]
wallerdev has quit [Quit: wallerdev]
wallclo__ has quit [Ping timeout: 276 seconds]
cored has quit [Ping timeout: 256 seconds]
bantic has joined #ruby-lang
<mbj>
whitequark: How does "foo" (implicit call to self) looks in sexp vs "self.foo" explicit call to self. I'd use only one ":call" node with specialized receivers.
<mbj>
whitequark: I love the baseclass as namespace pattern.
vlad_starkov has joined #ruby-lang
vlad_sta_ has joined #ruby-lang
vlad_sta_ has quit [Remote host closed the connection]
<whitequark>
mbj: implicit call to self is (call nil :foo)
<whitequark>
vcall_style is only used to differentiate between "m" and "m()". the first produces an error message "undefined local variable or method", the latter "undefined method"
<whitequark>
I'm considering making an explicit node for argument list. (arglist ...), instead of (call nil :foo (lit 1) (lit 2)), i.e. splatted arguments
vlad_starkov has quit [Ping timeout: 252 seconds]
<whitequark>
(pass blocks) it's a syntax tree. (block-pass something) as the last argument
<mbj>
whitequark: I saw vcall style having more semantic
<mbj>
whitequark: Do not exactly remembering it, I only reversed it until it worked on to_source ;)
<whitequark>
mbj: I think it's the only difference. Back in a while, I spent a whole lot of time digging MRI internals about that
<mbj>
whitequark: I only talk about the RBX vcall style.
<whitequark>
it's the same as in MRI, afaik.
<mbj>
mom, refreshing my brain
<mbj>
whitequark: you are correct.
<mbj>
whitequark: I'd love to have a separate argument list node.
<mbj>
whitequark: BTW rbx has send and send_with arguments.
<mbj>
whitequark: Lets only have one with arglist beeing nil or so.
<mbj>
whitequark: In RBX arguments is a primitive Array.
cmckni3 has joined #ruby-lang
cmckni3 has left #ruby-lang [#ruby-lang]
cmckni3 has joined #ruby-lang
<whitequark>
mbj: hmm.
<whitequark>
why do you have to differentiate between a call with arglist and one without?
<mbj>
whitequark: "m" is (send nil :m, nil)m "m(1)" is (send nil :m, (arglist, (lit 1)))
chendo has quit [Quit: Computer has gone to sleep.]
<mbj>
whitequark: In rbx there is different bytecode for send with and send without.
<whitequark>
my point being, "m" and "m()" have the same execution semantics
<mbj>
whitequark: They aligned the AST to the bytecode structure.
<mbj>
whitequark: We need to be able to reconstruct m or m()
<mbj>
whitequark: I'd love if "m".to_ast.to_source => "m" and "m()".to_ast.to_source = "m()"
<whitequark>
does "m()" *actually* produce SendWithArguments in rbx?
<mbj>
whitequark: mom
<whitequark>
I don't see the point
<mbj>
whitequark: it produces a send without arguments.
<mbj>
whitequark: a plain Rubinius::AST::Node::Send.
<whitequark>
yep.
<whitequark>
mbj: I think that there might be some value in reproducing the "m"/"m()", but this is essentially source-level information, useful only for error messages
spuk has quit [Quit: Human beings were created by water to transport it uphill.]
<whitequark>
thus, presence or absence of arglist will be embedded in "location".
<mbj>
whitequark: Lets say we write a source transformation tool and users likes to use "m()" our source transformation tool that should "only" for example to a variable rename.
<mbj>
whitequark: But if we force the user into a specific style "m" he might not like to use the tool.
<mbj>
whitequark: Sorry confusing english.
<mbj>
whitequark: Next try:
<whitequark>
mbj: "m" produces either a (call) or (lvar) depending on context, so that is not a problem
<whitequark>
a variable read will never produce a (call) node.
<mbj>
whitequark: I just talk about reproducing the source.
carloslopes has joined #ruby-lang
<mbj>
whitequark: If we loose the information if ti was "m" or "m()" we cannot reproduce the source.
<mbj>
whitequark: We can reproduce equivalent source, bot not identical.
<whitequark>
mbj: we unfortunately already lose too much information
<whitequark>
clang, for example, does not rewrite the source from scratch from an AST
<whitequark>
it basically has two modes of operation
<whitequark>
one is pretty-printing an AST, I guess that's self-explanatory
<whitequark>
the second one is _modifying_ the source. "add a statement here", "remove an argument there"
yalue has quit [Ping timeout: 260 seconds]
<whitequark>
i.e. it does not first read the source, convert it to an AST and then write it back; it reads an AST and uses it as a guideline for operating on the original source text
<mbj>
whitequark: It is no problem for me to loose the "m" vs "m()" information.
<whitequark>
I believe this is the only realistic way to perform source-to-source transformations in Ruby
<eam>
is there a reason that a=[1,2,3]; [4, *a] works, but [4, *a, 5] doesn't?
<whitequark>
mbj: the "m"/"m()" should and will be represented in the location
<eam>
whitequark: enterprise development for large orgs requires a lot more than a 5 year lifecycle. I've had to support perl from the late 90s, that's a reality of software development.
<whitequark>
eam: that's what paid support is for
<eam>
I'm not particularly happy about it, but it's a reality
<mbj>
whitequark: "a + b" #expression => "a + b", "a.b" #expression => "a" TBH this is confusing.
Ridders24 has joined #ruby-lang
mytrile has quit [Remote host closed the connection]
<whitequark>
but if you decompose it into its components and extract just the node for the receiver, it'd be "a"
<mbj>
whitequark: ahh you just do not like #recevier
<eam>
whitequark: that kind of attitude is amatuerish
<Ridders24>
whats gem is best suited to creating xlsx files that I can add a new line to after each loop?
solars has quit [Ping timeout: 255 seconds]
<mbj>
whitequark: full act I could just call call_node.children[0].location.expression.
<whitequark>
mbj: I don't like denormalization in the sexps
<whitequark>
yeah
<mbj>
whitequark: got the point.
<judofyr>
eam: the release schedule (and end-of-life'd) of 1.8.7 has been known for a while. anyone is free to maintain it, but no-one in the community cared enough about it.
<judofyr>
eam: I believe EngineYard took over maintenance of 1.8.6 for a while
<mbj>
eam: For me all this enterprise needs longer support cycles sounds like: "We do not have tests, so we cannot change something".
<whitequark>
eam: the community is not obliged to provide anything to the enterprise. if the enterprise wishes, it can perform its own maintenance instead of relying on mostly unpaid volunteers.
<whitequark>
end of discussion.
<eam>
yeah, I got it. What I'm speaking to is the difference between an ideal (we think 1.8.7 is dead) and reality (it's clearly not)
maxmanders has quit [Quit: Computer has gone to sleep.]
<eam>
you're free to support what you like
wallcloc_ has joined #ruby-lang
<eam>
and I'm free to develop an opinion about that, so let's just drop it
<whitequark>
mbj: also the Location::Branch is weird
<whitequark>
the point is to have distinct location classes for syntactically distinct constructs to be able to reconstruct them precisely
yalue has joined #ruby-lang
<mbj>
whitequark: We can remove most of the stuff for the same reason as #receiver
<whitequark>
yet you've grouped ?: and if/else into the same location class
<eam>
k/win 1
<whitequark>
mbj: (remove most of the stuff) yeah, exactly my point
<judofyr>
whitequark: is this going to be open-source btw? is it a part of your ruby_parser refactoring?
<mbj>
whitequark: It was an idea to remove the amount of location odes.
<whitequark>
mbj: you have to maintain all of them anyway
<whitequark>
ie I might want (and I do want) to drop the (call) but keep its receiver, for example
<mbj>
whitequark: I think "if" and "ternary" can share the location node.
<whitequark>
and I want to keep the relevant location
<judofyr>
whitequark: hah, you're stealing all the generic names!
madb055 has quit [Ping timeout: 256 seconds]
<whitequark>
judofyr: hehe
tallship has quit [Quit: Too Hip gotta go - Going..... Down..... Mr. Tyler?]
<whitequark>
at least it isn't called "methadone" or whatever.
wallclockbuilder has quit [Ping timeout: 255 seconds]
<whitequark>
mbj: I don't think so
<whitequark>
they have distinct internal structure
<mbj>
whitequark: pls elaborate
<whitequark>
for example, ?: cannot exist without an else clause
<whitequark>
and the tokens/keywords are distinct as well
rue has quit [Remote host closed the connection]
<whitequark>
also, `elsif`.
rue has joined #ruby-lang
<mbj>
whitequark: this is a point.
<judofyr>
whitequark: no parser/ruby19 yet?
<mbj>
whitequark: Did not thought about elsif.
<whitequark>
judofyr: nope
<whitequark>
judofyr: not that ruby18 works
<whitequark>
well, you can parse trivial statements but that's it
<whitequark>
judofyr: are you interested in this work?
nXqd has quit [Ping timeout: 240 seconds]
<mbj>
whitequark: So I think I got the point about the direction for Locations.
<judofyr>
whitequark: maybe :)
<whitequark>
mbj: very well!
kgrz has quit [Quit: Computer has gone to sleep.]
<mbj>
whitequark: Should we go on with implementation or fill the holes in the gist?
bashdy has joined #ruby-lang
<whitequark>
mbj: I have first a discussion about the anatomy of Diagnostics
gnufied has quit [Quit: Leaving.]
<mbj>
heh
<mbj>
whitequark: 5 min afk to grep a coffee
<whitequark>
mbj: so. the whole Diagnostic system is more or less modelled after clang, because clang is awesome *rainbows and unicorns*
<whitequark>
in clang, apart from having lots of weird optimizations, a Diagnostic consists mostly of a level, a message, a location, a set of ranges and a set of fix-it hints.
<whitequark>
level and message should be self-explanatory.
<whitequark>
the location is an instance of SourceLocation, which point to a particular character in the source
<whitequark>
the ranges is a set of SourceRange-s, which consist of begin SourceLocation and end SourceLocation.
<mbj>
whitequark: The diagnostics kick in *before* there is an ast?
<mbj>
whitequark: lexer errors, etc?
<whitequark>
mbj: they're orthogonal to an AST
<whitequark>
yes.
<mbj>
go on pls.
snarfmason has joined #ruby-lang
<whitequark>
the fix-it hints is a set of quick hints, like "insert a semicolon here to make this code compilable."; a major requirement for them is that the compiler should be able to continue on its own if it issues a Fix-It hint
<whitequark>
I think we can omit them for now because I don't see how they are ever useful in ruby
<whitequark>
(plus it requires a fuckton of very clever code in the parser)
<whitequark>
so. let's dissect the following error message:
<whitequark>
the ranges are highlighted by ~~~ and the location is highlighted by ^.
dhruvasagar has quit [Ping timeout: 246 seconds]
randym has quit [Ping timeout: 240 seconds]
<whitequark>
currently, there is no concept of a Location in parser. SourceLocation mostly makes sense in clang because it's a very clever optimization which saves them a lot of storage space
<whitequark>
I believe it's not realistic to implement that in Ruby
<mbj>
okay so far.
<whitequark>
also, only using Location as the "main locator" for a diagnostic prevents it from highlighting the whole erroneous token, such as with "+=" case
<whitequark>
so, I suggest to avoid using Locations in the parser anywhere and represent everything as Ranges
<mbj>
If range is of size 1 we can output it as a location.
nXqd has joined #ruby-lang
<whitequark>
so the "main locator" for a diagnostic would be a SourceRange too, which would also allow it to highlight the entirety of multi-character operators, etc
<whitequark>
mbj: that's what the current code does
<mbj>
whitequark: yeah, I broke it ;)
<whitequark>
I dislike how it changes between ~ and ^ if I make a one-character lvar "a" or two-character one "aa"
<whitequark>
that doesn't make any sense
<mbj>
whitequark: you want to fix it?
<whitequark>
it should highlight the erroneous token regardless of how long it is.
solars has joined #ruby-lang
sailias has joined #ruby-lang
GarethAdams|Work has joined #ruby-lang
<whitequark>
mbj: I want the Diagnostic to have a "main location" highlighted by ^^^ and a set of secondary ranges hilighted by ~~~
<whitequark>
so we could have like:
GarethAdams has quit [Disconnected by services]
<mbj>
whitequark: what about highlithing the tokens like this ^~^ (token of size 3) ^ as start and end marker.
<whitequark>
aaa << bbb
GarethAdams|Work is now known as GarethAdams
<whitequark>
~~~ ^^ ~~~
<whitequark>
mbj: maybe, that doesn't matter much
<mbj>
whitequark: So a token of size 1 only has a single ^
<whitequark>
the point is in having a Range for the main location in a Diagnostic
<whitequark>
instead of just a Location
<whitequark>
this would also simplify quite a bit of code in lexer, parser, etc
rippa has joined #ruby-lang
<mbj>
whitequark: Currently there is both location and range in parser?
<whitequark>
mbj: we can bikeshed over ^~^ over ^^^ later :)
<whitequark>
mbj: currently there's no Location
<whitequark>
I kinda forgot to port it from clang
<mbj>
whitequark: heh
<mbj>
whitequark: So where this discussion is heading to? A change, a keep as is?
<whitequark>
mbj: I want to use Range instead of Location for the main Diagnostic location
<whitequark>
your opinion
<whitequark>
?
MaddinXx has quit [Remote host closed the connection]
apeiros_ has quit [Remote host closed the connection]
<whitequark>
since it doesn't give us any optimization benefits anyway.
<mbj>
whitequark: As location is a special case of range I agree.
stardiviner has joined #ruby-lang
<whitequark>
Ok.
<mbj>
From my point of view this decision looks solid.
<whitequark>
let's continue with the gist then
<mbj>
Cleaning it up already.
<whitequark>
I'll make the diagnostic location changes in the background.
jxie has quit [Read error: Connection reset by peer]
<mbj>
whitequark: Do we need to have a SourceLocation for the "if", "else", "elsif" terminal?
dkannan has joined #ruby-lang
<mbj>
whitequark: And what is the correct CS term for these?
<mbj>
whitequark: okay how this mixes with iter, arguments or body first?
<mbj>
whitequark: I'd say arguments.
sailias has quit [Client Quit]
<whitequark>
(iter (call...) (args) (... body ...))
<whitequark>
like in syntax.
<mbj>
whitequark: mom, now I realize that the iter wraps the call
<mbj>
whitequark: foo { bar } is (iter (send :foo) () ( (send bar) ) ?
<mbj>
whitequark: From my perspective the iter should not wrap the call the call should wrap the iter!
<mbj>
whitequark: call is receiver, selector, arglist, block
<whitequark>
mbj: Bison disagrees with you :)
<mbj>
whitequark: Where block is a block or a block pass.
<mbj>
whitequark: Can we workaround? RBX did.
gregmoreno has joined #ruby-lang
<whitequark>
I might change that in the future but for the time being I'd like to keep the structure of (iter)
<whitequark>
(in the future) before the release.
<mbj>
whitequark: It is pain in the ass to write to_source with such a structure.
<whitequark>
I'm not convinced that the fix is easy and/or beneficial
<mbj>
whitequark: Can you steal that part from rbx .y files?
<mbj>
Another blackbox to crack ;)
<whitequark>
mbj: I'll look into it
<mbj>
thx
<whitequark>
I'm actually not sure that (iter) is detrimental for to_source; it might turn out that it's beneficial
<whitequark>
but I need to think about that more
bashdy has quit []
<mbj>
whitequark: As longer I think about this you are correct with your assumption it is bad.
<mbj>
Most likely my POV was to bound to RBX.
<mbj>
s/is bad/not is bad/
<mbj>
Sorry for my english ;)
<mbj>
Just visit call before iter.
<mbj>
No magic indentation anymore.
<whitequark>
yep
<mbj>
heh
<mbj>
I'll use (block) instead of (iter) in my gist.
apeiros_ has joined #ruby-lang
gnufied has joined #ruby-lang
dr_bob1 has joined #ruby-lang
dr_bob1 has quit [Read error: Connection reset by peer]
dr_bob has quit [Ping timeout: 256 seconds]
dhruvasagar has joined #ruby-lang
<mbj>
whitequark: I love the arglist with reqarg, optarg, splatarg, kwarg this is far easier to emit/mutate than the rbx one.
<mbj>
whitequark: Had to stop gist refresh, antoher operations problem.
<whitequark>
'k
<mbj>
perils of a devops position ;)
Squarepy has quit [Quit: Leaving]
io_syl has joined #ruby-lang
Squarepy has joined #ruby-lang
dhruvasagar has quit [Ping timeout: 246 seconds]
sailias has joined #ruby-lang
<mbj>
whitequark: What about "[1, 2]" IMHO we need a source location also for "[" "," and "]", the brackets are easy
danishman has joined #ruby-lang
<whitequark>
mbj: to hell with commas
<mbj>
whitequark: But for the "," we'd need a "container" or ignore them ;)
<whitequark>
you don't realistically going to need their location
<mbj>
whitequark: heh, okay for me.
flak has joined #ruby-lang
<mbj>
whitequark: Same with "=>", ":" in hashes. { 1 => 2, 3 => 4 } (hash (lit 1) (lit 2) (lit 3) (lit 4)), "{" and "}" in Location as open and close. "=>" and "," ignored!
judofyr has quit [Remote host closed the connection]
flak is now known as Guest40383
rippa has quit [Read error: Connection reset by peer]
<mbj>
whitequark: If we have "a kvpair" node we could have "=>" and "," easily.
<whitequark>
mbj: no need to explicitly locate { and }
<whitequark>
again, you're not going to realistically need these tokens
<mbj>
whitequark: So we also do not capture "[" and "]" in array?
<whitequark>
just in .expression
<mbj>
okay
<mbj>
whitequark: Okay lets reparse rule of thump: All source information about terminals that are NOT repducible via Node#type!
<whitequark>
yep
<mbj>
This dramatically eases the job.
<mbj>
nice
pygmael has quit [Quit: pygmael]
kgrz has joined #ruby-lang
<mbj>
whitequark: Is there a term for operators like "+" that are implemented as methods. Used to call them "method-operators" ?
<mbj>
whitequark: the real operators I justed to call "real operators" ;)
altrim has joined #ruby-lang
<whitequark>
mbj: all operators except || and && are implemented as methods
<whitequark>
|| and && are "logical operators"
<whitequark>
(in 1.8, ! was also implemented as a logical op)
<mbj>
whitequark: Okay so we just use "operator" for the real operator and for the others as a "group" ?
<mbj>
When I whant to make clear I speak about the operators that are methods, what term I use?
<whitequark>
mbj: we use "selector" for methods, "+" is a "selector" too
<whitequark>
the node is the same, (call)
rockpapergoat has joined #ruby-lang
<mbj>
whitequark: I know
<whitequark>
and let's call "&&" and "||" "operators".
<mbj>
whitequark: This was clear from the beginning. Just like to know if there is a ruby specific term for operators that are methods.
__butch__ has joined #ruby-lang
<mbj>
whitequark: Lets ignore this. More interesting: When do do not track brackets fo literals, we do not have to track "do", "end", "{", "}" for blocks ?!
Gaelan has joined #ruby-lang
<whitequark>
hrm
<whitequark>
I guess same justifications generally apply to both...
<whitequark>
for now, let's compromise on this
<whitequark>
we already track the "keyword" for (if)
tbuehlmann has quit [Remote host closed the connection]
<whitequark>
let's track "keyword" for blocks, "{" vs "do"
<whitequark>
to allow reconstructing them
<whitequark>
I'll either leave this as is, or add tracking for "}"/"end" together with complete tracking of literals
<mbj>
whitequark: Okay. Also it is a real issue if you have a "do" or "{", precedence rules.
thebastl has joined #ruby-lang
<whitequark>
yepp
<whitequark>
well, no, not really
<whitequark>
you don't have precedence issues in an AST
<whitequark>
but it makes reconstructing way harder
<whitequark>
(it = absence of "keyword")
<mbj>
But you might have if you reproduce falsely ;)
<whitequark>
you could use parens ;)
<mbj>
I did excessive parens in to_source to make it correct, not beautiful.
<whitequark>
sure.
<whitequark>
I understand that.
<mbj>
I hope this parser can result in a real ruby sourcecode beautifier.
<whitequark>
so, we should have "keyword" in BlockLoc
<mbj>
We should have #open and #close
<whitequark>
it's hard but possible, yes.
thebastl has quit [Remote host closed the connection]
<mbj>
do and end
<mbj>
{ and }
<mbj>
BTW how do you like the Locator::Block namespacing within baseclass idea?
<mbj>
I like it, as it reduces Nameing duplication.
<whitequark>
mbj: (namespacing) Location::Block is okay-ish
<mbj>
BlocLoc, CallLoc. ... Loc all the time.
<whitequark>
please note that I use somewhat arbitrary names in IRC discussion, as long it's clear what class I'm referring to
<mbj>
noted
wallclockbuilder has joined #ruby-lang
<mbj>
whitequark: Such a prettfier would need to use somekind of optimization strategy. There are multiple ways to produce equivalent source, I thought about minimizing a badness value with multiple strategies.
<mbj>
whitequark: Breaking literals is big badness etc.
<whitequark>
mbj: there isn't really a sane way to produce an *equivalent* source wrt/ formatting
<whitequark>
we can pretty-print, or patch the original source
wallcloc_ has quit [Ping timeout: 245 seconds]
<whitequark>
even clang cannot reproduce an equivalent source.
__butch__ has quit [Remote host closed the connection]
wallcloc_ has joined #ruby-lang
<whitequark>
parser will allow for very clever pretty-printing, but it's still not original, and I believe it will never be
<mbj>
whitequark: equivalent for me is the following: parse(generate(parse(source))) == parse(source)
<whitequark>
roundtripping, of course
<whitequark>
it's simple
<mbj>
whitequark: Not this is explicit not source == generate(parse(source)) !
altrim has quit [Quit: Leaving.]
<whitequark>
but making a prettifier is much harder than roundtripping
__butch__ has joined #ruby-lang
<mbj>
s/Not/Note
<mbj>
yeah
<mbj>
I know, I tried ;)
wallclockbuilder has quit [Ping timeout: 245 seconds]
<mbj>
whitequark: BTW isnt there a reason why lexer and parser generators cannot generate an inverse transformator?
dc5ala has joined #ruby-lang
<whitequark>
mbj: yeah
<whitequark>
I won't go into details but LR parsers like Bison cannot, and PEG parsers, which also replace lexers, can
<whitequark>
but PEG has exponential time (or space, if you use a packrat parser) behavior
<whitequark>
and generally I'm fairly sure they are not acceptable for parsing significant amount of code fast.
wallclockbuilder has joined #ruby-lang
<mbj>
whitequark: With some very trivial EBNS parser I made something like this. But I never parsed something complex ;)
<whitequark>
LR is much harder to write, LL is somewhat simpler (and features better error recovery) but still harder than PEG
<whitequark>
still, they both have linear behavior
<mbj>
whitequark: okay, thx!
<whitequark>
well, LL has linear on the source code
<whitequark>
someone more knowledgeable than me could correct that...
wallcloc_ has quit [Ping timeout: 245 seconds]
<mbj>
whitequark: So essentially it is a typicall tradeoff. This time we trade parsing speed for inability of generation.
nXqd has quit [Ping timeout: 276 seconds]
<whitequark>
yep
<whitequark>
actually, I did not say that you can easily mutate PEG parse tree ;)
<whitequark>
because you cannot, and if you go to ASTs from PEG PT, then you lose all the PEG benefits
<whitequark>
(cannot = not easily.)
<mbj>
whitequark: Interesting topic. Back to my replication failure ;)
<whitequark>
btw... I'm not convinced that Ruby with heredocs and interpolations can ever be parsed by PEGs
<whitequark>
I believe it cannot.
<whitequark>
so it doesn't even matter much.
<mbj>
whitequark: Cant you mix PEG with others? So the "easy" parts are PEG and get wrapped by more powerful parsers?
tylersmith has joined #ruby-lang
<whitequark>
I'm not aware of such techniques
<mbj>
whitequark: You see I do not know most of the formal details, I stupidly used ragel before ;)
<whitequark>
my ideal ruby parsing suite would be the current Ragel lexer plus an LL(1) parser
<whitequark>
Coco/R for example
Ridders24 has quit [Ping timeout: 245 seconds]
<mbj>
whitequark: Te lookahead of 1 makes the parser efficient. Because it does not loose much work when it has to go back.
Ridders24 has joined #ruby-lang
<whitequark>
exactly
<whitequark>
PEGs have unlimited backtracking
<whitequark>
also LALR(1) means that you can execute side-effectful actions in the grammar, which ruby indeed does
<whitequark>
(they depend on particular lookahead behavior much.)
<mbj>
whitequark: So if you could generate a PEG from a ragel lexer and a parser via adding some additional information that is NOT used for lexing parsing you'd get a generator for free. BUT the AST has to look like a PEG parse tree.
<whitequark>
mbj: I do not think that makes any sense :)
<mbj>
whitequark: hehe
<mbj>
whitequark: I expected this.
<mbj>
Have to read more!
<whitequark>
btw I just banged some things together and:
<whitequark>
(string):1:1: error: cannot assign to self
<whitequark>
self = 1
<whitequark>
^^^^
<whitequark>
nodes have location info!
<whitequark>
but it's very preliminary
<mbj>
nice
<mbj>
whitequark: I head lots of people critisising rubies diagnostics.
<whitequark>
mbj: because they're ABYSMAL
<whitequark>
like, worst of every language I've ever seen
<mbj>
For me I'm typically very fast in finding the actual problem, but I a) use only a smaller subset of ruby b) can read ;)
Oloryn_lt2 has joined #ruby-lang
<mbj>
But such reporting will also cut roundtrip time for me! Nice.
maxmanders has joined #ruby-lang
forrest has joined #ruby-lang
<mbj>
whitequark: BTW I battle tested to_source via roundtripping /home/mbj/devel/**/*.rb and actually regenerating some well tested ruby code (such as veritas). We should do the same once we have someting stable.
<whitequark>
mbj: sure
<whitequark>
RP also does that
<mbj>
whitequark: nice
sepp2k has joined #ruby-lang
<mbj>
whitequark: Mutant also has a mode to mutate itself, it creates an in memory copy of its own source under the ::Zombie namespace.
kgrz has quit [Ping timeout: 255 seconds]
<whitequark>
cool
<mbj>
whitequark: It is itself not mutation covered. I plan this for 0.3
wallclockbuilder has quit [Ping timeout: 245 seconds]
<mbj>
If I whant to test that code I need an in memory copy.
<mbj>
But *only* for that code.
<whitequark>
hm...
<whitequark>
ok I'm off for a few hours
<whitequark>
later
robbyoconnor has joined #ruby-lang
carloslopes has joined #ruby-lang
jhn has joined #ruby-lang
Luwe has quit [Ping timeout: 246 seconds]
Ridders24 has quit [Ping timeout: 255 seconds]
apeiros_ has joined #ruby-lang
robbyoconnor has quit [Remote host closed the connection]
lcdhoffman has joined #ruby-lang
dr_bob has joined #ruby-lang
jxpx777 has joined #ruby-lang
dhruvasagar has quit [Ping timeout: 258 seconds]
pkrnj has joined #ruby-lang
ivanoats has joined #ruby-lang
ivanoats has joined #ruby-lang
ivanoats has quit [Changing host]
bantic has quit [Quit: bantic]
swav_ has quit [Remote host closed the connection]
randym has joined #ruby-lang
wallclockbuilder has quit [Remote host closed the connection]
Squarepy has quit [Remote host closed the connection]
Nisstyre-laptop has joined #ruby-lang
dr_bob has left #ruby-lang [#ruby-lang]
robbyoconnor has joined #ruby-lang
havenwood has quit [Remote host closed the connection]
brianpWins has joined #ruby-lang
towski has joined #ruby-lang
alessio_rocco has quit [Remote host closed the connection]
swav has joined #ruby-lang
Luwe has joined #ruby-lang
Luwe has quit [Client Quit]
wallclockbuilder has joined #ruby-lang
bluepojo has quit [Remote host closed the connection]
<mixandgo>
I have this regex /(one|two|three\+four)/ and I want to extract the keywords in a constant, is that possible ?
chrismar035 has quit [Ping timeout: 245 seconds]
workmad3 has joined #ruby-lang
mytrile has joined #ruby-lang
chrismar035 has joined #ruby-lang
<apeiros_>
mixandgo: not really following on what you want to do
<mixandgo>
apeiros_: I want to be able to reuse the keywords in other regexps like so: /(MY_KEYWORDS)/ which would translate into /(one|two|three\+four)/
<apeiros_>
you can interpolate a regex into another
<apeiros_>
a = /foo/; b = /bar/; c = /#{a}|#{b}/ # works as expected
mistym is now known as mistym_lunch
<mixandgo>
so MY_KEYWORDS = one|two|three\+four
furrrraahhhh has joined #ruby-lang
<mixandgo>
is that valid ?
<lianj>
MY_KEYWORDS = /one|two|three\+four/
<mixandgo>
or rather = /one|two|three\+four/
<lianj>
/(#{MY_KEYWORDS)}/
<lianj>
*})
<mixandgo>
oh, hmm
furrrraahhhh has left #ruby-lang [#ruby-lang]
zaddax has joined #ruby-lang
breakingthings has joined #ruby-lang
lcdhoffman has quit [Quit: lcdhoffman]
protagoras271 has joined #ruby-lang
protagoras271 has quit [Remote host closed the connection]
lcdhoffman has joined #ruby-lang
Hanmac1 has joined #ruby-lang
sush24 has quit [Quit: This computer has gone to sleep]
<mbj>
whitequark: Currently reading your Parser::Builder::Sexp, some specialized nodes in there that could be simulated by composition of two others.
<mbj>
whitequark: From my POV. But I'd like to be proven wrong ;)
jhn has joined #ruby-lang
<whitequark>
mbj: such as?
<whitequark>
mbj: btw, singletons are represented as (true) (false) (nil)
<whitequark>
this is related to assignment processing
<mbj>
whitequark: Yeah
<whitequark>
remember that Builder is essentially a set of reduction rules for the LR parser
<mbj>
whitequark: Why do we have a global variable assignmend node, a local variable assignend and an instance variable assignment one?
<whitequark>
they're handled differently?
<mbj>
whitequark: In my gist I only have one "parameterized" assignment node.
<whitequark>
from to_source POV the distinction isn't sensible, from everything else POV it is
<mbj>
whitequark: Tell me!
<whitequark>
hm?
<mbj>
whitequark: From bytecode emitter there is a difference, but this difference could also be taken into account with reading children[0]
<whitequark>
why should I have to?
<whitequark>
it's easier to converge several types into one than to distinguish different types
<whitequark>
like, way easier.
<mbj>
whitequark: Depends on the bytecode to emit.
<mbj>
whitequark: On what needs this parser focuses on?
<mbj>
ruby implementation I guess.
<mbj>
So let it be multiple nodes ;)
crynix has quit [Remote host closed the connection]
pr0ton has joined #ruby-lang
<mbj>
whitequark: Is there a need for a special attribute assignment node, rbx does have it?
retro|cz has quit [Ping timeout: 258 seconds]
<mbj>
whitequark: The current parser18.y calls methods on @builder, but still calls inexistend stuff like argl. Mostlikely argl and new_call are not prorted from ruby parser. My question: Port / change .y / or implement those on builder?
mytrile_ has joined #ruby-lang
<whitequark>
I believe that any backend would make a difference between ivars, cvasrs and lvars.
<whitequark>
mbj: it is simply very incomplete
<mbj>
whitequark: But what direction it is heading?
<mbj>
whitequark: I'd love to complete it. I could also copy over all stuff from RP and refactor afterwards.
cwd1 has joined #ruby-lang
cwd1 has quit [Remote host closed the connection]
cwd1 has joined #ruby-lang
<whitequark>
mbj: I'm not yet sure about some rules :) Let's first finish with the sexp spec
<mbj>
Sorry but IMHO such stuff should just be removed. but my POV is naive, I did not implemented a ruby.
<whitequark>
mbj: there is nothing to "remove".
<whitequark>
it's not "removing features". it's "adding anti-features".
<whitequark>
maybe it should be done but I'm not sure this will ever happen.
<mbj>
whitequark: I already thoght about an restricted ruby parser that only accepts a subset of ruby. So I could verify myself nor my dependencies use such stuff.
<whitequark>
mbj: I think this is best done in a linter
Luwe has quit [Quit: leaving]
<whitequark>
and with `parser`, you could verify most of this stuff
<mbj>
whitequark: Yeah
bluepojo has quit [Remote host closed the connection]
<whitequark>
mbj: (capture = in optarg) I'm not sure what's the point
mytrile has quit [Remote host closed the connection]
<mbj>
whitequark: Do we need the location of the = in an optional argument in #location of Node
<mbj>
whitequark: With the assignment operator we "capture" the =, as the optarg is some kind of a "default assignment" I thought we should capture it also.
<whitequark>
mbj: I'm not sure it is valuable to capture = in the assignment
glebm has quit [Ping timeout: 258 seconds]
<whitequark>
but that's another point completely
<whitequark>
lemme finish updating the gist
<mbj>
whitequark: Think about a multline assignment it might be valuable to see the assignment operator highlighted.
<whitequark>
mbj: if so, we should capture it everywhere, I agree
glebm has joined #ruby-lang
<whitequark>
re block-pass: block-pass signifies &block.
<whitequark>
you don't want to transform "m{}" to "m(&lambda{})" or smth like that.
<whitequark>
mbj: I think we decided against using (arglist) ?
<mbj>
whitequark: no, I when pointed on this I think my use of block-pass is inconsistend through the document.
bluepojo has joined #ruby-lang
<whitequark>
just add open/close to the call so one could transform it back to "m" / "m()"
<whitequark>
in the former open/close would be nil
<mbj>
whitequark: tbh I do not remember. But arglist is some kind of a "typed array".
<mbj>
And having a bunch of nodes in the children without grouping is something I do not really like.
<whitequark>
mbj: it does not add any semantics to the sexps
<whitequark>
hence, there is no point in keeping it.
<asahi>
hello, i installed gist with gem install gist. however if I type in 'gist', bash isn't able to located the executable. i'm using rbenv. can someone point me in the right direction?
<whitequark>
asahi: `rbenv rehash`
wallclockbuilder has quit [Remote host closed the connection]
wallclockbuilder has joined #ruby-lang
<asahi>
whitequark: ahh. you have to do that whenever you install a new gem?
<whitequark>
asahi: yes
<asahi>
thx
<mbj>
whitequark: Gist diffs do not have line comments :(
<whitequark>
a gem with executables, that is
<whitequark>
mbj: now it's time to talk about various assignments! :D
<whitequark>
see, there's a problem with your "match lhs to rhs" proposal
<whitequark>
a, b, c = *d
<whitequark>
a[1], b.c = *d
<whitequark>
plus there could be these kinds of assignments:
<whitequark>
mbj: let's pull it in the repo, then?
<mbj>
whitequark: yeah
<mbj>
whitequark: I forgot about the unbalanced masgn
<mbj>
whitequark: Got them correct in ductrap ;)
<mbj>
whitequark: s/ductrap/to_source/
<whitequark>
so
<whitequark>
ruby_parser solves this by turning mlhs to "incomplete assignments"
<whitequark>
so that "$a, @b = *c" turns to (masgn (array (gasgn $a) (iasgn @b)) (splat (lvar c)))
tylersmith has joined #ruby-lang
<whitequark>
this is why we need attrasgn: self.a, self.b = *c
<mbj>
whitequark: yeah, I remember the case
<mbj>
whitequark: ack as a solution to this problem.
<mbj>
whitequark: But, can we come up with something better?
<whitequark>
I don't think so
<mbj>
whitequark: not without some tricy datastructure that does not fit within an ast / sexp
<whitequark>
so if something disagrees, RP wins, as it follows the MRI parse tree
<mbj>
yeah
<whitequark>
see above.
<mbj>
But do we need this crazy nodes?
<whitequark>
of course
<mbj>
As we could remove attrasgn we might be able to remove these also?
<whitequark>
the problem is that the parser cannot desugar "a.b.c &= 1" to "a.b.c = a.b.c & 1" as it does for ivars/gvars
postmodern has joined #ruby-lang
sailias has quit [Quit: Leaving.]
<whitequark>
you know why?
<mbj>
okay the first one is basically foo[i] = foo[i] << 1
<mbj>
the second is foo.send(:[]=, 1)
<mbj>
the second is foo.send(:[]=, 1, 1) sry
<whitequark>
the second is send, indeed
bantic has quit [Quit: bantic]
<whitequark>
but the first is not equivalent to foo[i] = foo[i] << 1
<mbj>
lemme think a while
<whitequark>
def foo.[]; @counter += 1; end
<whitequark>
sorry :)
<mbj>
yeah, Im stuck with Array#[] semantics ;)
<whitequark>
so if something in op-asgn includes side effects, they must be executed only once
<mbj>
This is an ugly part of the ruby language.
<whitequark>
no, this is how it must wor
<whitequark>
*work
<mbj>
yeah I accept.
<whitequark>
every language which has op-asgn works this way
<whitequark>
the parser could desugar that by introducing an additional lvar binding but this would be Lisp macros then :)
<mbj>
heh
<mbj>
We need to create a mostly side effect free ruby sometimes.
<whitequark>
(because it will have to choose the binding so as not to clash with existing ones--hygienic macros--and also local_variables will get screwed)
<whitequark>
mbj: as the saying goes, "there are no functional languages, just functional programs"
<whitequark>
an ability to use side effects is an important one and should not be forbidden by the language
<mbj>
hence the mostly ;)
<whitequark>
but we need to watch our code.
cirenyc has quit [Quit: Leaving...]
<mbj>
So I aggree we need op_asgn1
<whitequark>
same for op_asgn2
<mbj>
Whats this in RP ?
<whitequark>
&=, &&=
rockpapergoat has quit [Remote host closed the connection]
<mbj>
lemme install ruby parser, mom
<whitequark>
also RP has plain op_asgn but I couldn't yet get it to emit that
<mbj>
Can we get a rid of the 1, 2 postfixes?
towski has joined #ruby-lang
<mbj>
op_assign_or op_assign_foo ?
<whitequark>
mbj: sure, I was going to rename them for a long time already
<mbj>
nice
mrfelix has joined #ruby-lang
<whitequark>
also I don't like how & and && are very distinct in the normal AST
<whitequark>
but they're conflated in op_asgns
<whitequark>
log_asgn?
<mbj>
log is to far to logarith or logging
<mbj>
logarithm
<whitequark>
the meaning is actually quite different. self.a ||= b will not execute b if a is true, I believe
<mbj>
If the target of the assignment is something that cannot be read side effect free implementation should emit correct bytecode / do the right thing.
<whitequark>
the ast captures semantics, so yes
<whitequark>
though we really need to think about it better. it's ugh :/
<mbj>
Okay, do we need a distinction between read side effect free op_asgn nodes and possibly side effectful nodes?
sandbags has joined #ruby-lang
sandbags has quit [Changing host]
sandbags has joined #ruby-lang
<mbj>
As long as the implementation sees: Do an op_assign here, the ast did its job.
<mbj>
The ast and the source communicates intention, not implementation.
<whitequark>
you're right here
<whitequark>
hrrrm
<mbj>
I'd bet implementations check for unoverridden Array#[] to perform optimizations.
<whitequark>
mbj: not "might". they must be implemented so that all operations are called only once.
<whitequark>
it's not even about efficiency
<mbj>
whitequark: They cannot with custom #[]
<mbj>
They can with local variable reads
<mbj>
Or instance variable reads.
<mbj>
Or anything else user cannot override.
<whitequark>
mbj: it doesn't matter; a.b.c[1] ||= 1
<whitequark>
the chain a.b.c must also be executed once.
<whitequark>
a.b.c[@a += 1] ||= d.e
<mbj>
this is: tmp = a.b.c; tmp[1] ||= 1
<whitequark>
so?
<mbj>
I'm not very sure why we try to do the job of an optimizer.
<mbj>
It is totally okay for local variables ivars gvars etc.
<whitequark>
mbj: explain how are you going to do this transformation.
sailias has joined #ruby-lang
<mbj>
But for the #[] case I think we should somehow should use a stupid send. Maybe we just need an op_assign node that wraps the expanded shorthand. Implementation can do all it whants with it.
<mbj>
For the more low level onces I totally agree with specialized nodes.
<whitequark>
mbj: you can't do that without introducing a local binding
<whitequark>
and you cannot introduce such bindings in a Ruby parser, because for example #local_variables
<mbj>
we only need to have enough information, not the actual binding.
<mbj>
so we have a specialized node again.
<whitequark>
this basically leads us to an op_asgn node :)
<whitequark>
yep.
<mbj>
okay
<whitequark>
there's a reason this is done via a specialized node
<mbj>
whitequark: okay, to_source will be a virtue with this ast...
<mbj>
whitequark: We have a circular dependency between parser and builder, the api builder uses from parser is also quite complex. So I do not see any nice way to refactor it away.
<whitequark>
mbj: it is expected and natural here.
<whitequark>
builder is basically externalized parser actions
<whitequark>
they are designed to be tightly coupled.
<whitequark>
better than replicating rules in .y's :)
<mbj>
whitequark: or having a giant base class.
<whitequark>
yea
<whitequark>
also did you know this:
<whitequark>
whitequark@raidho:~/parser (master)$ ruby -rruby_parser -e 'p Ruby19Parser.new.parse("a while b")'