-
Notifications
You must be signed in to change notification settings - Fork 10
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
Instructions print via game #32
base: master
Are you sure you want to change the base?
Conversation
lib/scottkit/compile.rb
Outdated
@@ -25,17 +23,17 @@ def initialize(game, filename, fh = nil) | |||
end | |||
|
|||
# Compiles the specified game-source file, writing the resulting | |||
# object file to stdout, whence it should be redirected into a | |||
# object file to an IO string, whence it should be redirected into a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh this should be IO stream
lib/scottkit/game.rb
Outdated
@output = options[:output] || $stdout | ||
end | ||
|
||
def puts *args |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be #:nodoc:
right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know about :nodoc
-- I've abandoned the idea of using any of the inline documentation things, as I don't think anyone ever actually uses the resulting documents. See #19.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remind me, what is the difference in Ruby between making a method public (as in your commit) and making it private but the declaring it public after all (as in my original)? It's been a while since I read about how this stuff works in Ruby. Or is this just a style issue?
end | ||
|
||
def puts *args | ||
output.puts(*args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about overriding print
in game.rb
. Isn't the more honest approach you used in the previous commit also suitable here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh ... but you're not overriding print
, are you? You're just defining a method with the same name as the underlying primitive that it wraps -- so the invocation changes from print(x)
to @game.print(x)
. OK, that makes perfect sense. Carry on :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah kind of funky to have to do this but it's either this or passing the output object down to the instructions. This seemed cleaner and having it centralized would give you one place to hook in a driver.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, this is good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, the approach for compilation looks good to me. I think that play
should follow the same model, though, and use explicit input and output parameters, rather than relying on a new :output
option. We want the compilation and playing APIs to be compatible, right?
test/test_save.rb
Outdated
game.load(IO.read("games/test/crystal.sao")) | ||
withIO(StringIO.new("save game\nTMP"), File.new("/dev/null", "w")) do | ||
withIO(StringIO.new("save game\nTMP"), $stdout) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you no longer discarding the output of play
here? We don't want that output, just the save file that is generated along the way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change I could probably back out. I'd started out trying to see if I could totally remove the need for withIO
but left it here to pass in the save game command. Since withIO
requires both params so I had to pass something in... the output is still being discarded though via the output string instead of /dev/null
.
I think we probably could get rid of withIO
here by just loading the game file into a StringIO object and then appending "save game\nTMP"
. I'll give it a try and see if that end up looking cleaner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how writing the output of play
to $stdout
can discard it -- surely it will appear on standard output?
(Probably the Ruby library provides a null-file object somewhere, which exists to discard output; that would really be the best thing to use here.)
You know, it's kind of cool that something as trivial as withIO
lets you do so many things :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's nothing going to $stdout
because it's getting sent to the :output
stream instead. $stdout
is only used when nothing is provided. another option would be to modify withIO
to only assign non-nil values.
I think the end result is the same but just declaring it public to start results in less surprises. I remember reading through the code the first time and thinking "how is this working if these a private?" before coming across the access change later. Since they ended up public it seemed better to make the interface clearer from the start. |
Cool, thanks for clarifying that. I agree, the way you have it is better. |
I'm not sure if the other comments answered this or not:
I'm not sure I understand this. Play should be using the |
Sorry, this has got complicated because of all the different comment-threads! All I am saying is that if the compilation API is now But I do see that there is then an asymmetry with input. But remember that |
That last comment makes sense. I hadn't really understood that |
d26898f
to
8e389b5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realized I had misunderstood the last comment. I think the nicer thing about the compiler is that it's pretty distinct from the game (I'd actually make it more of an explicit split and just have the compiler take an options hash rather than relying on the game's options). If the player was also a distinct object that captured the instructions' output then having a play_with(input, output)
method would make a ton of sense. But since the play methods are tangled up with the Game object I don't think it makes sense to inject the input and output through the play methods.
But even with that misunderstanding I think It was a good push to add an input option. It lets us remove the last usages of withIO
.
def compile_to_stdout(filename, fh = nil) | ||
compiler = ScottKit::Game::Compiler.new(self, filename, fh) | ||
compiler.compile_to_stdout | ||
def compile(out, filename, fh = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not in love with this argument ordering but it felt like the least bad option considering the optional fh
argument. If it was me I'd just ditch this method and let the callers instantiate and call the compiler themselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it was me I'd just ditch this method and let the callers instantiate and call the compiler themselves.
I'm not following. What would that look like?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll respond on the main thread to keep things centrally visible.
There's only a couple of places where the compiler is used, in some tests and then in the
The thing that seems confusing to me about having
The This PR's grown big enough so I'm not looking to increase the scope any more, just pointing out things have have jumped out at me. If they're things you're interested in changing I'm happy to help. |
8e389b5
to
78d2c29
Compare
@MikeTaylor Just wanted to check in with you and see if this is something you're interested in pursuing or not. If not are there commits that you'd accept? I'm happy to just keep it in my fork but would love to land any changes that make sense to you. |
I agree there is a issue here, but it needs thought and I won't be able to give it any for 72 hours. If you can wait, that'd be best for me. |
No rush at all. Just wanted to give you an easy way to say no if it wasn’t a direction that makes sense to you. |
78d2c29
to
7dba848
Compare
This is a bit of a work in progress. I started out trying to get the
Instruction
objects sending their output to the game so my subclass could capture it. At that point it seemed pretty natural to try to handle a bit of #21. I didn't go all the way but it removes the need forwithIO
for output.The commits should be pretty self contained so probably best to go through that each of those. If you like the direction I can keep going and try to get the input converted to an optional option to the Game constructor.