--- Log opened Mon Jul 01 00:00:49 2013 |
00:02 | | You're now known as TheWatcher[zZzZ] |
00:42 | <&McMartin> | Heh. Most of my commentary for this file is a justification for why I'm not just using sys/tree.h~ |
00:49 | | Vornicus [vorn@ServerAdministrator.Nightstar.Net] has quit [[NS] Quit: Leaving] |
00:59 | | Derakon is now known as Derakon[AFK] |
01:21 | <@Azash> | <X> Do we care if incompetent people are able to use good software? Is friendliness to incompetence otherwise any indication of a piece of software's quality? |
01:21 | <@Azash> | Oh dear |
01:22 | <&McMartin> | opensource.txt |
01:22 | <@Azash> | McMartin: Pretty much |
01:23 | <@Azash> | This guy is also an FSF activist and blames proprietary users to be willing servants to a grimdark corporate future |
01:23 | <&McMartin> | That said: "Yes. Software with laxer preconditions and stricter postconditions is better software" |
01:23 | <&McMartin> | "It works with more things out of the box and will be a lesser source of bugs down the road." |
01:24 | <@Azash> | Mm |
01:25 | <&McMartin> | I might be being unfair in equating "laxer preconditions" with "friendliness to incompetence" in his book. |
01:25 | <&McMartin> | But I'm probably not. |
01:26 | <&McMartin> | I might also be unfair in assuming that the person quoted explicitly doesn't consider *using* software to be the point, and as such usability except in the context of developing other things is pointless. |
01:26 | <&McMartin> | I'm more confident that this assumption is entirely warranted~ |
01:27 | | Derakon[AFK] is now known as Derakon |
01:31 | <@Azash> | Might be, I have him ignored and only got that quoted to me :P |
01:31 | <@Azash> | But even so, a tool that's hard to use is rarely worth the time to learn |
01:31 | <@Azash> | Unless it's something general-purpose like vim |
01:45 | <@Alek> | or vigor |
01:48 | <&McMartin> | Is that an actual program because I'd be totally unsurprised if it were |
01:51 | <&ToxicFrog> | ...yes, it is. |
01:51 | <&ToxicFrog> | It is an implementation of Clippy for vi. |
01:51 | <&McMartin> | ... that is quite possibly the worst idea I have ever heard |
01:58 | < ktemkin> | Googling that shows such gems as "Are you sure you want to move left?" |
02:01 | <@Reiv> | ... clippy for vi /why/ |
02:02 | < ktemkin> | It was sacrastically featured in a webcomic; and thus someone made it, apparently. |
02:14 | <&Derakon> | An AI to guide you through vi's UI wouldn't be a terrible idea; the problem is with making that AI be Clippy. |
02:15 | <@Azash> | Wait |
02:15 | <@Azash> | Clippy as in.. that god damned helper? |
02:16 | | * Alek can't stop laughing. |
02:16 | <@Azash> | I hope it at least has an april fool's mode to turn into an emacs proponent |
02:16 | <@Azash> | "It looks like you are trying to X. Have you considered how much easier it would be in emacs?" |
02:18 | < ktemkin> | I read that at "Is looks like you are trying to use X. Have you considerd how much easier it would be in emacs?" |
02:18 | < ktemkin> | *that _as_ |
02:19 | <&McMartin> | I often run Emacs in a terminal despite having an X session handy, no joke |
02:19 | < ktemkin> | I could understand that, I dislike UI chrome. |
02:21 | < ktemkin> | Most of the time, X is just a nice application that lets me run five different virtual terminals on five different monitors. |
02:22 | <&McMartin> | It does also give me the occasional OpenGL context. |
02:41 | | Turaiel[Offline] is now known as Turaiel |
02:46 | | Vorntastic [Vorn@Nightstar-f9558889.sub-70-211-4.myvzw.com] has joined #code |
02:50 | | RichyB [RichyB@D553D1.68E9F7.02BB7C.3AF784] has quit [[NS] Quit: Gone.] |
02:53 | | RichyB [RichyB@D553D1.68E9F7.02BB7C.3AF784] has joined #code |
02:54 | | * Derakon briefly thinks he has finished the code review, only to realize he accidentally skipped 700 lines in the middle of the file. |
02:54 | <&Derakon> | (1000 lines down, 178 lines of commentary created) |
03:11 | <&Derakon> | \param alignOffset - alignment offset |
03:11 | <&Derakon> | Thank you, that's very useful. |
03:17 | < Vorntastic> | When you say "commentary" what sort of things are you saying? |
03:18 | <&Derakon> | I'm typing up the changes I want the submitter to make. |
03:18 | <&Derakon> | (209 lines now...) |
03:19 | < Vorntastic> | I think as someone who mostly works solo I'd like to see that. |
03:19 | <&Derakon> | I can link you the pullreq once I've posted my comments. |
03:20 | <&Derakon> | Most of them are just "you aren't following the style guide", "more comments please", or "why is this code here instead of over there"? |
03:20 | <&Derakon> | s/"?/?"/ |
03:20 | < Vorntastic> | That'd be good. |
03:24 | | * McMartin throws a hundred million random trees at his code, heads off to dinner. |
03:25 | <&McMartin> | The first million have worked! |
03:25 | <&Derakon> | \o/ |
03:25 | <&Derakon> | Are you doing procedural generation of some kind? |
03:25 | <&McMartin> | Well, sort of |
03:26 | <&McMartin> | In that I'm feeding a subset of the 2 trillion permutuations of range(16) to my red-black tree implementation and the same to FreeBSD's, and then doing pointer compares |
03:26 | <&McMartin> | I'm also deleting each element of that tree individually (with recreation afterwards so restore the state precisely) to test those cases. |
03:26 | <&Derakon> | What on earth is this for? |
03:26 | <&Derakon> | 500 lines of diff to go... |
03:27 | <&McMartin> | Removing Monocle's somewhat obnoxious dependency on libstdc++, which plays hilariously poorly with DLL export. |
03:27 | <&McMartin> | Which means "I need to replace std::map", because that was the only actually tricksy thing I used. |
03:28 | <&McMartin> | Which meant "I need a red-black tree", and while RichyB helpfully pointed me at the one in the FreeBSD standard headers, that is one of those horrible implementations that is like 400 lines of macro definitions that need to be massaged just so to actually work. |
03:28 | <&Derakon> | Oh fun. |
03:29 | <&McMartin> | So I'm using that as a reference implementation for my clean-room reimplementation that uses single inheritance instead of template instantiation, and also NO MACROS WHATSOEVER, THANK YOU VERY MUCH. |
03:29 | <&McMartin> | And while I have constructed examples to hit what all the algorithmic corner cases, and those all work, before I feel confident actually folding it into Monocle I want it to take on the Infinite Monkeys Challenge. |
03:29 | <&McMartin> | So now it's doing that. |
03:29 | <&McMartin> | 4.6 million and counting~ |
03:30 | <&McMartin> | (This is a pretty weak machine, but it is getting Work To Do, ho yez) |
03:30 | <&Derakon> | I wonder what the performance difference is between your version and the FreeBSD version. |
03:30 | <&Derakon> | Presumably those 400 lines of macro definitions gain them something~ |
03:30 | <&McMartin> | My guess is speed is similar, and I have better space compaction |
03:30 | <&McMartin> | What they gain is that it's possible with their system for a data type to have intrusive pointers that let it be part of two data structures at once. |
03:31 | <&Derakon> | Part of the pullreq commentary: "For god's sake, it doesn't cost you much to name something "next" instead of "nxt". Vowels are cheap." |
03:31 | <&McMartin> | They do *not* gain inlining efficiency because they're *still using a comparator function* inside those 400 lines. |
03:31 | <&Derakon> | Oh dear. |
03:31 | <&McMartin> | And they don't gain access efficiency because single-inheritance in C is "free" |
03:31 | <&Derakon> | So their system is more flexible but less efficient. |
03:31 | <&McMartin> | Yeah. |
03:32 | <&McMartin> | But I suspect they have need of that, so more power to them. |
03:32 | <&McMartin> | And it's been in their OS for ten years now with no changes, so I bet it's basically right~ |
03:32 | <&McMartin> | Tee hee. The resident memory usage appears to be 320KB. |
03:33 | <&McMartin> | 92.5% CPU usage~ |
03:33 | <&McMartin> | (This poor machine is single core) |
03:33 | <&McMartin> | I guess I can also check in in 20 minutes to see if those numbers don't change, but this is a good sign that I *also* have no memory leaks. |
03:34 | <&McMartin> | (Not that this would impact the library; both FreeBSD's and my code never allocate or free anything, and do everything with surgery on pre-existing pointers) |
03:35 | <&McMartin> | Right, heading off, thanks to the magic of screen |
03:36 | <&McMartin> | Up to 9 million and memory usage is totally flat |
03:36 | <&McMartin> | PRetty sure there's no leaks. |
03:37 | <&Derakon> | If you leaked even 1 byte/iteration you'd have lots several megs by now. |
03:37 | <&Derakon> | Er, lost. |
03:49 | <&Derakon> | There! 307 lines of commentary, but I'm done. >.< |
03:50 | <&McMartin> | Yes indeed. |
03:50 | <&McMartin> | It looks like it's taking it 15 minutes to do 10% of the test load. |
03:50 | <&McMartin> | So I guess the whole run has about 2 hours left in it. |
03:51 | <&McMartin> | At this point that's basically a victory lap, but~ |
03:51 | <&Derakon> | Okay, Vorn, the bottom comment here: https://bitbucket.org/derakon/pyrel/pull-request/39/an-initial-attempt-at-charac ter-generation/diff |
03:51 | <&Derakon> | That's my comments on his pullreq. |
03:52 | <&Derakon> | (You might also be interested in the Pyrel style guide, since I make reference to violations of it: https://bitbucket.org/derakon/pyrel/wiki/StyleGuide ) |
04:04 | | VirusJTG [VirusJTG@Nightstar-09c31e7a.sta.comporium.net] has quit [[NS] Quit: Program Shutting down] |
04:28 | | Vornicus [vorn@ServerAdministrator.Nightstar.Net] has joined #code |
04:28 | | mode/#code [+qo Vornicus Vornicus] by ChanServ |
04:28 | | Vorntastic [Vorn@Nightstar-f9558889.sub-70-211-4.myvzw.com] has quit [[NS] Quit: Bye] |
04:28 | <&Derakon> | Vornicus: you saw my links? Just checking. |
04:29 | <~Vornicus> | I did. |
04:29 | <~Vornicus> | and now I can read them in something other than 7 point type~ |
04:29 | <&Derakon> | Heh. |
05:14 | | Derakon is now known as Derakon[AFK] |
05:31 | | Kindamoody[zZz] is now known as Kindamoody |
06:30 | | ErikMesoy|sleep is now known as ErikMesoy |
06:34 | | ktemkin is now known as ktemkin[awol] |
07:39 | | Kindamoody is now known as Kindamoody|out |
07:55 | | celticminstrel [celticminst@Nightstar-8403057e.dsl.bell.ca] has quit [[NS] Quit: KABOOM! It seems that I have exploded. Please wait while I reinstall the universe.] |
07:55 | | celticminstrel [celticminst@Nightstar-8403057e.dsl.bell.ca] has joined #code |
07:55 | | mode/#code [+o celticminstrel] by ChanServ |
07:56 | | Turaiel is now known as Turaiel[Offline] |
08:09 | | AverageJoe [evil1@Nightstar-4b668a07.ph.cox.net] has joined #code |
08:10 | | celticminstrel [celticminst@Nightstar-8403057e.dsl.bell.ca] has quit [[NS] Quit: And lo! The computer falls into a deep sleep, to awake again some other day!] |
08:17 | | cpux|2 [cpux@Nightstar-98762b0f.dyn.optonline.net] has quit [Client closed the connection] |
08:17 | | cpux|2 [cpux@Nightstar-98762b0f.dyn.optonline.net] has joined #code |
09:08 | | You're now known as TheWatcher |
09:31 | | AverageJoe [evil1@Nightstar-4b668a07.ph.cox.net] has quit [[NS] Quit: Leaving] |
10:13 | | Karono [Karono@Nightstar-03f66622.optusnet.com.au] has joined #code |
10:27 | | Zandramus [Zandramus@Nightstar-60c8f748.optusnet.com.au] has joined #code |
10:32 | | Zandramus [Zandramus@Nightstar-60c8f748.optusnet.com.au] has left #code ["Leaving..."] |
12:07 | | Kindamoody|out is now known as Kindamoody |
12:34 | | * McMartin fails at sleep. |
12:34 | <&McMartin> | Also, I apparently find the Revised^5 and Revised^6 Reports on the Algorithmic Language Scheme to be riveting instead of, you know, sleep aids. |
12:35 | <&McMartin> | I am also no longer surprised at the lack of widespread support fo R6RS, seeing as how it changes the definition of what a program is. |
12:35 | <&McMartin> | (and appears to add a Schemely equivalent to everyone's favorite public static void main.) |
12:39 | <~Vornicus> | changes what the definition of a program is? |
12:40 | | * Vornicus plays Ultima at McM, again, apparently |
12:40 | <&McMartin> | In revisions prior to 6, a Scheme program is a collection of forms that are evaluated in sequence, from an unspecified source, possibly a file, possibly a REPL. |
12:40 | <&McMartin> | R6RS has explicit notions of modules, and of programs that use those modules. |
12:47 | <&McMartin> | Monocle's FFI is complicated by the fact that on Mac, main() is not allowed to be called main(). |
12:48 | <&McMartin> | I found away around it on Gambit, and pygame clearly has some way of defeating it, but I don't see techniques for this in Racket. |
12:48 | <&McMartin> | Er |
12:48 | <&McMartin> | Monocle has this property because it wraps SDL, which has this property. |
12:49 | <@TheWatcher> | ... main() is not allowed to be called main(), wut? |
12:55 | < RichyB> | ... main() is not allowed to be called main(), wat? |
12:56 | < RichyB> | <McMartin> Also, I apparently find the Revised^5 and Revised^6 Reports on the Algorithmic Language Scheme to be riveting instead of, you know, sleep aids. <- I have a similar story |
12:57 | < RichyB> | I once attempted to put myself to sleep properly at night for a few weeks once by reading a heavy book called "The Art of Prolog" that I'd found in my uni's library. |
12:57 | < RichyB> | The exercise was a complete failure. |
12:57 | < RichyB> | I still suffered insomnia, and now I suffer additionally from this damnable addiction to constraint programming and unification. |
13:00 | <&McMartin> | On OSX, SDL.h #defines main() to be SDL_main() so that the real main() may live in a separate Objective-C file that sets up Cocoa to actually work. |
13:00 | <&McMartin> | I suspect that something similar would need to happen on Windows, except that on Windows if you're going to play with the GUI the entry point isn't named main(), which means main() can just be any other identifier, and so it is. |
13:01 | < RichyB> | Oh this is SDL-and-OSX headache, not just OSX headache. |
13:01 | <&McMartin> | Yeah. |
13:01 | < RichyB> | That's less "wat". |
13:02 | < RichyB> | In fact I'd honestly call that SDL-wat, not OSX-wat. |
13:02 | <&McMartin> | p. sure it's Cocoa wat. |
13:02 | <&McMartin> | And SDL has this headache because one of its goals is that the *text* of the source should be the same across platforms. |
13:02 | <&McMartin> | And X11 has an unusually strong separation between GUI elements and the rest of the system, for both good and ill. |
13:03 | <&McMartin> | Windows, however, plays more nicely with the C standard here, assuming that's what's going on at all. I'm not 100% sure about that. |
13:03 | <&McMartin> | Windows does require you to link in a libSDLmain.a or SDLmain.lib to work right, but I think that's defining WinMain if you happened not to. |
13:04 | <&McMartin> | (And you aren't supposed to; you're supposed to define main() like a good cross-platform programmer.) |
13:04 | < RichyB> | I don't immediately see why you should have an preprocessor-overridden main() for the sake of initialising Cocoa + friends instead of a "you should call SDL_init() at the start of main()" and doing the work there. |
13:04 | <&McMartin> | I strongly suspect the answer is "because you don't have to do that on any of the other platforms, and OSX was a Johnny-come-lately that they had to back-hack in" |
13:04 | < RichyB> | Is this because there's something like WinMain that's the only place where you can get ahold of references to your window-manager handle or whatever the hell it's called? (HWND?) |
13:05 | <&McMartin> | NSApplication in this case, and I'm honestly not 100% sure how Cocoa rolls with that. |
13:05 | <&McMartin> | But note that on Windows WinMain is *not* the only way to get your HWND. |
13:06 | <&McMartin> | SDL on Windows works even when you link in console mode, where main() *is* the entry point, and console apps are totally allowed to open dialog boxes and windoes and stuff. |
13:07 | | * McMartin consults UQM's copy of SDLMain.m to see what he's got here. |
13:09 | <&McMartin> | Oh geeze. |
13:09 | <&McMartin> | Yeah, this is an OSX Wat. |
13:09 | <&McMartin> | Part of setting up a Cocoa application involves calling [NSApp run]. |
13:09 | <&McMartin> | This function does not return until the application quits. |
13:10 | <&McMartin> | So, they hook a notification to applicationDidFinishLaunching that then calls SDL_Main. |
13:10 | <&McMartin> | Win32 and X11, by contrast, require clients to poll their event loops and dispatch callbacks in that way. |
13:12 | <&McMartin> | There's a minor side effect that I'm not 100% sure if it matters: Win32 and X11 apps are invisible until, effectively, SDL_CreateVideoSurface (sp) is invoked. |
13:12 | <&McMartin> | That's not true on OS X because of the menu bar at the top of the screen. |
13:13 | <&McMartin> | Which Must Always Exist, while in X11/Win32 windows are allowed to not have menu bars (and, indeed, SDL-created windows do not). |
13:14 | <&McMartin> | But I think the real thing they're hurdling here is that Cocoa, like (IIRC) gtk and GLUT, does not expose its event loop; you set up your callbacks and then call ProcessEventsForever. |
13:16 | < RichyB> | By "are invisible" you mean "no GUI elements have been created yet"? |
13:16 | <&McMartin> | Created or modified, yes. |
13:17 | < RichyB> | Ah, it's [NSApp run] that invokes GUIfication, yes. |
13:17 | < RichyB> | For a millisecond I was wondering "but how do you create non-GUI programs?" :) |
13:17 | < RichyB> | BTW I assume that Win32's default WinMain stashes a copy of the HWND into a global variable somewhere and then calls the real main() |
13:18 | < RichyB> | Seeing as that's the obvious sensible thing and MS appear to have actually done it. |
13:18 | <&McMartin> | Probably, but not necessarily; it might just parse the command line and then call the real main(). |
13:18 | <&McMartin> | MS is shockingly sensible in this domain, making stuff that comes into the entry point available via API calls anywhere. |
13:18 | < RichyB> | Oh yeah, maybe the stub that calls WinMain() stashes the HWND object handle first. |
13:19 | <&McMartin> | There's certainly some way to get it. |
13:19 | <&McMartin> | Oh wait, it's not HWND, it's HINSTANCE or something. |
13:19 | <&McMartin> | Which SDL apps ignore. |
13:20 | <&McMartin> | Basically, when you open a file in an already running process, it opens a new copy of that process and tells it in the WinMAin args "hey, if you care, there's another one of you already running" and it can RPC over to say "hey load this file" or do nothing or quit or whatever. |
13:20 | <&McMartin> | Pretty sure SDL just ignores that and says "fuck it, new window time" |
13:20 | <&McMartin> | ... oh, right. |
13:20 | <&McMartin> | It's going to set up the redirections for stdout and stderr, which are actually unbound in nonconsole mode. |
13:24 | < RichyB> | "open a file in an already running process"? Huh? |
13:24 | <&McMartin> | Do the equivalent of "emacsclient" |
13:24 | < RichyB> | Process control/modification doesn't sound like something that, say, fopen() would do, so I assume that you meant something else. |
13:24 | <&McMartin> | That is, say you're running Word |
13:24 | < RichyB> | Ahhhh |
13:24 | <&McMartin> | And you have a doc open |
13:24 | <&McMartin> | And you doubleclick some other doc |
13:25 | <&McMartin> | That starts a new winword.exe process, and gives a link of some kind to the already-running process somehow |
13:25 | < RichyB> | I wonder how that's handled by Firefox on Linux. |
13:26 | < RichyB> | Oh, I think applications do something like put a Unix socket in /tmp/openoffice-${getuid()}/running-instance.sock |
13:26 | <&McMartin> | It's something more bizarre than just a PID or process ID for WinMain |
13:26 | <&McMartin> | They were clearly making shit up as they went along and weren't talking to each other while they did. |
13:27 | <&McMartin> | But they still managed to as a result get something that tends to do what it needs to. |
13:27 | <&McMartin> | It's the Anti-GNOME >_< |
13:30 | < RichyB> | What, as opposed to GNOME's habit of talking every issue to death until people give up and settle on an implementation that doesn't work? |
13:31 | <&McMartin> | They also talk only to one another~ |
13:31 | < RichyB> | I thought GNOME's actual habit in this day and age was to take all the features out without discussion and fuck you if doing that just make the desktop inaccessible for you. |
13:31 | <&McMartin> | Pretty sure they talk to each other before they do that because they're convinced it's an awesome idea and they had to achieve unity of consciousness somehow. |
13:31 | < RichyB> | Hahaha |
13:32 | <&McMartin> | But, well, *only* to each other |
13:32 | <&McMartin> | MS, I think, talks to random dudes in their focus groups and then hapazardly throws it all in with no regard for consistency~ |
13:35 | < RichyB> | MS is a different rant entirely. |
13:35 | <&McMartin> | Like I said; I think it's the opposite problem~ |
13:36 | <&McMartin> | But whatever it is, it didn't complicate SDL/pygame/etc |
13:40 | | Kindamoody is now known as Kindamoody|out |
14:11 | | Orthia [orthianz@3CF3A5.E1CD01.B089B9.1E14D1] has quit [Ping timeout: 121 seconds] |
14:20 | | Orthia [orthianz@3CF3A5.E1CD01.B089B9.1E14D1] has joined #code |
14:20 | | mode/#code [+o Orthia] by ChanServ |
14:34 | | Vornicus [vorn@ServerAdministrator.Nightstar.Net] has quit [[NS] Quit: Leaving] |
15:05 | | celticminstrel [celticminst@Nightstar-8403057e.dsl.bell.ca] has joined #code |
15:05 | | mode/#code [+o celticminstrel] by ChanServ |
15:36 | <@gnolam> | http://loremgibson.com/ |
15:46 | < RichyB> | http://www.rikeripsum.com/ |
18:42 | | Derakon [chriswei@Nightstar-a3b183ae.ca.comcast.net] has joined #code |
18:42 | | mode/#code [+ao Derakon Derakon] by ChanServ |
18:42 | | * Derakon ponders his current Pyrel project: write the game-state (de)serialization stuff. |
18:43 | <&Derakon> | This includes being able to handle objects who have function pointers as part of their state. |
18:43 | < RichyB> | This is in Python? |
18:43 | < RichyB> | Look into ZODB. |
18:43 | <&Derakon> | So I have to keep an eye out for things like "<bound method Foo.bar of <__main__.Foo instance at 0x1004a74d0>>", note the ID of the object and the name of the function, backreference the object ID to the IDs Pyrel uses itself, and reconstruct the whole shebang later. |
18:44 | < RichyB> | Python's pickle module can already do that to a limited extent. |
18:44 | < RichyB> | ZODB picks the idea up and runs with it. |
18:44 | < RichyB> | ZODB implements transparent persistence of pretty much arbitrary Python objects. |
18:45 | < RichyB> | It *won't* do certain specific things, such as closures, so if you really need callables to be persisted then you have to make classes out of them. |
18:45 | | Derakon_ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has joined #code |
18:45 | < RichyB> | Or store (function, args, kwargs) tuples instead of trying to store partially-applied functions. |
18:45 | < Derakon_> | Hm, I managed to hork my connection. |
18:45 | < RichyB> | hah |
18:45 | < RichyB> | What's the last line you got, please? |
18:45 | | Derakon [chriswei@Nightstar-a3b183ae.ca.comcast.net] has quit [NickServ (GHOST command used by Derakon_)] |
18:46 | | Derakon_ is now known as Derakon |
18:46 | | mode/#code [+ao Derakon Derakon] by ChanServ |
18:46 | <&Derakon> | A moment. |
18:46 | <&Derakon> | My line that started with "So I have to...". |
18:46 | <&Derakon> | Note one of my primary goals here is to have a savefile format that does not include bytecode or anything else like that. |
18:46 | < RichyB> | <RichyB> Python's pickle module can already do that to a limited extent. <RichyB> ZODB picks the idea up and runs with it. <RichyB> ZODB implements transparent persistence of pretty much arbitrary Python objects. |
18:46 | <&Derakon> | I want savefiles to be trustworthy. |
18:46 | < RichyB> | <RichyB> It *won't* do certain specific things, such as closures, so if you really need callables to be persisted then you have to make classes out of them. <RichyB> Or store (function, args, kwargs) tuples instead of trying to store partially-applied functions. |
18:46 | <&Derakon> | This is why pickle is out of the question. |
18:47 | <&Derakon> | As soon as you run pickle you have to know your input data is trustworthy. |
18:47 | < RichyB> | Pickle (and by extension ZODB) will happily deal with things like pointers to anything that's bound at top-level of a module. |
18:47 | | Derakon[AFK] [Derakon@Nightstar-a3b183ae.ca.comcast.net] has quit [Ping timeout: 121 seconds] |
18:47 | <&Derakon> | (In practice, nobody is likely to distribute untrustworthy Pyrel saves, but as a matter of principle I don't like it) |
18:47 | < RichyB> | Well... okay. You have severe problems there, though. |
18:48 | <&Derakon> | Oh? |
18:49 | <&Derakon> | I mean, I recognize that e.g. I can't capture lambdas with this approach. |
18:49 | <&Derakon> | But I think I can handle pretty much everything else. |
18:50 | < RichyB> | If your persistence mechanism can persist function pointers then you get the same trustworthiness problem that Pickle has; someone can encode a reference to a function in a place from which it doesn't expect to be called. |
18:51 | < RichyB> | The ability to persist references to functions and classes is most of the entire reason why pickle is untrustworthy. |
18:51 | <&Derakon> | I can recognize and ignore uses of builtin functions, allowing only functions that are part of Pyrel objects. |
18:51 | <&Derakon> | Which should leave me fairly safe in terms of what code can be executed. |
18:51 | < RichyB> | You really will need a specific whitelist of functions that should be persistable. |
18:51 | <&Derakon> | My main problem with pickle is that AIUI you can create a Pickle object that, when deserialized, does anything as part of that deserialization. |
18:52 | <&Derakon> | RichyB: yeah, the whitelist is "functions that are member fields of objects that I am also serializing." |
18:52 | < RichyB> | Your persistable functions will also need to be vetted to ensure that they can't ever be confused by giving them inputs of a wrong type, or which don't match up in some way. |
18:53 | <&Derakon> | I'm not persisting the arguments to those functions. |
18:53 | <&Derakon> | Oh wait, right. |
18:53 | <&Derakon> | My assumption here is that any function that has potentially harmful side-effects when called will be vetting its arguments. |
18:54 | <&Derakon> | Otherwise, you may make a savefile that crashes the game when run, but you're going to have trouble causing more harm than that. |
18:55 | < RichyB> | Remind me never to swap Pyrel saves with anyone for any reason ever. |
18:55 | <&Derakon> | Would you rather I used pickle? |
18:56 | <&Derakon> | I mean, I don't see that there is a good solution here. |
18:56 | < RichyB> | I really believe that you're right in that there is no good solution. |
18:57 | < ErikMesoy> | eval() on carefully vetted text that must match a regexp for safe function patterns. Now you have three problems. |
18:57 | <&Derakon> | ...yes, thank you, Erik. |
18:58 | <&Derakon> | While I'm at it, savefiles can't include the strings "SELECT", "DROP", "FROM", etc. |
18:58 | <&Derakon> | (Oh geeze, if savefiles ever did include SQL that would be horrible) |
18:58 | | ktemkin[awol] is now known as ktemkin |
18:59 | < ErikMesoy> | "N problems" joke aside, I'm serious. eval() seems to exist pretty much for recreating functions out of text files, and checking its plaintext definition seems to me like it would be easier than checking the safety of the encoded version. |
18:59 | <&Derakon> | No code, in any form, should be in the savefile. |
19:00 | <&Derakon> | Just references to functions that are defined elsewhere in the source code. |
19:04 | | Derakon_ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has joined #code |
19:04 | < RichyB> | ErikMesoy: I've seen two places where eval() is used correctly in Python. |
19:05 | < RichyB> | One's the "decorators" egg on PyPI, where it's used for metaprogramming. |
19:05 | < RichyB> | The other is the "Chameleon" templating system |
19:06 | | Derakon [chriswei@Nightstar-a3b183ae.ca.comcast.net] has quit [Operation timed out] |
19:06 | | Derakon [Derakon@Nightstar-a3b183ae.ca.comcast.net] has joined #code |
19:06 | | mode/#code [+ao Derakon Derakon] by ChanServ |
19:06 | < RichyB> | in both of those cases, the security implications are negligible. If you're calling one of those decorators then you're already writing Python code; stop trying to exploit the code around you and just run your payload already. ;) |
19:07 | < Derakon_> | Heh. |
19:07 | < RichyB> | Same for Chameleon; Chameleon templates are already explicitly allowed to contain arbitrary Python expressions and there's some verbiage in the docs about not running untrusted .pt files. |
19:08 | < ErikMesoy> | Is a cheat console also a valid use of eval() ? |
19:09 | < ktemkin> | They do call it a read-eval-print loop for a reason. |
19:10 | < ktemkin> | That's pretty much what a cheat console would be. |
19:14 | <@Tarinaky> | I guess the easiest sidestep would be to have some method-less objects (kinda like C structs), serialise those with JSON or something and use composition to have an owning class that isn't serialised that holds all the methods and 'program'. |
19:20 | < ktemkin> | "Just references to functions that are defined elsewhere in the source code." <-- All you're trying to capture in those fields is which method (from a set of methods) to call for a certain task? |
19:20 | < Derakon_> | Basically, yes. |
19:20 | < ktemkin> | And every method in that set expects the same argument types, and thus are interchangible? |
19:20 | < Derakon_> | No. |
19:20 | < Derakon_> | For ex |
19:20 | < Derakon_> | Er. |
19:20 | < ktemkin> | (Though you may have different sets for different fields.) |
19:20 | < Derakon_> | I guess it depends on how formal you're being here. |
19:21 | < Derakon_> | I don't have defined sets; everything is rather ad-hoc. |
19:21 | < Derakon_> | But for example, the Timer object has a countdown and a function pointer; when the countdown hits zero it calls the function with a predetermined set of arguments. |
19:21 | < Derakon_> | When a Timer is created, it's up to the creator to ensure that the function it provides to be called will be happy with those arguments. |
19:22 | < Derakon_> | So yes, in the case of serializing Timers, all of their function pointers should be basically interchangeable. |
19:24 | < Derakon_> | (But a different context would have function pointers expecting different arguments) |
19:30 | < ErikMesoy> | How impractical is it to split that into different things like PoisonTimer, DiseaseTimer, etc? |
19:30 | < Derakon_> | Completely. |
19:31 | < Derakon_> | One of the #1 goals of Pyrel is to not bundle game logic into the engine. |
19:32 | < Derakon_> | New effects should be able to be created by modifying data files and, occasionally, by creating a new bit of script in the "procs" section of the codebase (which is not considered part of the core engine). |
19:43 | | Karono is now known as Karono[zZz] |
20:04 | <&McMartin> | The procs section should have a map from strings to callables, and use those strings as the things persisted |
20:06 | | Kindamoody|out is now known as Kindamoody |
21:00 | < Derakon_> | McM: well, a Proc is actually an instance in addition to function(s). |
21:00 | < Derakon_> | Since some Procs are stateful. |
21:02 | < Derakon_> | (But yes, there's a mapping of strings to Proc constructors in that code) |
21:07 | | Kindamoody is now known as Kindamoody[zZz] |
21:18 | < Derakon_> | Hm, RichyB (or any other Python gurus present), any idea what the right way is to access the various values in e.g. "<bound method Foo.foo of <__main__.Foo instance at 0x1004a74d0>>"? |
21:19 | < Derakon_> | Particularly I want to get Foo, foo, and 0x1004a74d0. |
21:19 | < Derakon_> | That last one I can access via the builtin id() function, I know. |
21:20 | < Derakon_> | But that requires me to already have the Foo instance in question. |
21:20 | < Derakon_> | I could just use a regex but that seems hacky. |
21:23 | < RichyB> | Of a bound method im: im.im_class = Foo, im.im_self = foo |
21:24 | < RichyB> | im.im_func is the function foo.im(self, ...) |
21:24 | < RichyB> | You do not want to pickle the value 0x1004a74d0. |
21:24 | < Derakon_> | No, I'm aware of that. |
21:24 | < Derakon_> | I'm using it as a key to lookup the ID that I can serialize, so that later I can restore the proper relationships between objects. |
21:24 | < RichyB> | That is not going to be the address of the same function on the next program fun. :) |
21:24 | < Derakon_> | Quite |
21:25 | < RichyB> | Just use the function object as a hash key directly. |
21:25 | < Derakon_> | The idea here is that objects can just toss function pointers into their "ready-to-be-serialized" dicts, and the Serializer I'm writing will say "Hang on, that's a function pointer...okay, it's for object X, and the function is Y". |
21:25 | < Derakon_> | So it converts the function pointer into (Pyrel-generated ID for object X, name of function Y). |
21:25 | < RichyB> | There's a __hash__ and an __eq__ intrinsic to Python's `object` class which operates on object identity. |
21:26 | < Derakon_> | Which can be safely deserialized later. |
21:26 | < RichyB> | You can use anything immutable as a hash key - functions, classes, whatever. |
21:26 | < Derakon_> | Um, I'm not certain I'm tracking you. |
21:27 | < Derakon_> | When I serialize an object, I store the object's Python-generated ID (output of builtin func id()) and map it to the Pyrel-generated object ID. |
21:27 | < RichyB> | Ah. |
21:27 | < Derakon_> | I'm not examining the functions in that object though. |
21:27 | < RichyB> | I thought you were talking about using the id in a slightly different way. |
21:27 | < RichyB> | You have another problem, then. |
21:27 | < Derakon_> | The Python-generated ID is only used while constructing the serialization and doesn't show up in that serialization itself. |
21:27 | < RichyB> | In CPython, the id() of your function object is an int with value 0x1004a74d0 |
21:28 | < RichyB> | There's no way to get from the id number of an object to the object itself, barring cheating the interpreter (which there is a module for, called "di". Don't use it, it's made of segfaults.) |
21:28 | < Derakon_> | Heh. |
21:29 | < RichyB> | Also the id() of a given function will be different across runs of your program, because function objects are constructed at run time on the heap and yada yada address space layout randomisation I love pizza. |
21:29 | < Derakon_> | I don't care about the results of id() so long as they don't change while I'm actually in the process of serializing. |
21:29 | < Derakon_> | Hang on, am writing up pastebin. |
21:30 | < RichyB> | Then use the function itself as the hash key. |
21:30 | < Derakon_> | That requires me to store every function of every object. |
21:30 | < RichyB> | Your goal here is to have, in memory, a hash from function identities to... something, which lets you keep track of which functions are allowable? |
21:30 | < Derakon_> | Let me finish pastebin. :) |
21:31 | < RichyB> | The id() of a given object is not guaranteed to not alias the id() of any other object if the two do not have overlapping lifespans. |
21:31 | < Derakon_> | ...so, non-concurrent objects may share IDs. |
21:31 | < Derakon_> | Because they re-use memory. |
21:31 | < Derakon_> | Anyway, http://pastebin.com/g1Y2VZmz |
21:31 | < RichyB> | Excatly. |
21:32 | < RichyB> | Ohnoes, the poor ex-cat. ;-; |
21:32 | < Derakon_> | As long as nothing is created or destroyed while serializing I should be fine though. |
21:32 | < Derakon_> | (Nothing is created or destroyed that is being serialized) |
21:32 | < RichyB> | Right, right. |
21:32 | < Derakon_> | My issue here is with lines 12 and 13. |
21:32 | < Derakon_> | As I said, I could use a regex to get those values. |
21:32 | < Derakon_> | But I assume there's some obscure builtin that will do it for me. |
21:32 | < RichyB> | My issue here is with lines 3 and 14. |
21:32 | < Derakon_> | I just have no idea how to figure out what it is. |
21:33 | < RichyB> | Don't use the id()s of the objects, use references to the objects. |
21:33 | < RichyB> | Replace idToPyrelId[id(object)] with idToPyrelId[object] |
21:33 | < Derakon_> | That works iff I can get that same reference out of the function pointer. |
21:33 | < RichyB> | much safer, simpler semantics, will probably be faster under PyPy |
21:33 | < Derakon_> | Agreed. |
21:34 | < Derakon_> | As long as it's possible. :) |
21:34 | < RichyB> | That works iff you get the same objects. |
21:34 | < Derakon_> | The objects will be the same; I just have no idea how to access them. |
21:34 | < RichyB> | id() will not work under every single one of the possible situations in which that will not work. |
21:34 | < Derakon_> | IOW given a function, how do I get the object it is bound to? How do I get the function name? |
21:34 | < Derakon_> | If I can do both of those then I don't need id(). |
21:35 | < RichyB> | Given a foo.method, foo.method.im_class is Foo, foo.method.im_func is the function foo(self, ...), foo.method.im_self is foo. |
21:35 | < RichyB> | foo.method.im_func itself is the function object. |
21:35 | < Derakon_> | Ahh, thankee. |
21:35 | < Derakon_> | Sorry, I misunderstood when you said that the first time. |
21:35 | < Derakon_> | Right, no more need for id() then. |
21:36 | < RichyB> | It's okay. Talking about function, class, method and class objects ends up putting the terms together so many times in close succession that they kind of lose meaning and it's really hard to track, the first dozen times you do it. ;) |
21:36 | < Derakon_> | Yep. |
21:37 | < Derakon_> | It doesn't help that my example code had a class Foo with a method named foo, with an instance of the class having the name foo. :) |
21:37 | < Derakon_> | >>> foo.foo.im_self |
21:37 | < Derakon_> | <__main__.Foo instance at 0x1004a74d0> |
21:40 | < Derakon_> | ...okay, now I just need to recognize when a value I'm dealing with is a function. |
21:40 | < Derakon_> | I guess I could do hasattr(object, 'im_func'). |
21:41 | <&McMartin> | I?, hasattr()! |
21:41 | < Derakon_> | Quite. |
21:42 | | * Tamber grins. |
21:45 | < Derakon_> | Ahh, isinstance(object, types.MethodType) appears to be what I want. |
21:45 | < Derakon_> | Man, I would not have thought that developing a roguelike would involve so much introspection when I started this project. |
21:47 | <&McMartin> | You're not just trying to build A Roguelike |
21:47 | < RichyB> | Derakon: no, this is actually a good time to be using isinstance. :) |
21:48 | < RichyB> | Not hasattr()! |
21:48 | <&McMartin> | You're trying to build a roguelike *middleware* system. |
21:48 | < Derakon_> | RichyB: yes, I hadn't figured out what the right isinstance call was. |
21:48 | <&McMartin> | You're going to hit all the Enterprisey things. |
21:48 | < Derakon_> | Heh. |
21:55 | < Derakon_> | It's all good though; keeps things interesting and deepens my knowledge of Python. |
21:56 | <&McMartin> | Quite so |
22:00 | < Derakon_> | Okay, I think this is what I want: http://pastebin.com/RV10TKiT |
22:01 | < Derakon_> | Uh, but with an extra newline. WTF, paste. |
22:05 | | Derakon__ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has joined #code |
22:07 | | Derakon_ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has quit [Operation timed out] |
22:08 | | Derakon [Derakon@Nightstar-a3b183ae.ca.comcast.net] has quit [Ping timeout: 121 seconds] |
22:09 | | Derakon [Derakon@Nightstar-a3b183ae.ca.comcast.net] has joined #code |
22:09 | | mode/#code [+ao Derakon Derakon] by ChanServ |
22:12 | | Turaiel[Offline] is now known as Turaiel |
22:18 | | Vornicus [vorn@ServerAdministrator.Nightstar.Net] has joined #code |
22:18 | | mode/#code [+qo Vornicus Vornicus] by ChanServ |
22:22 | | ErikMesoy is now known as ErikMesoy|sleep |
22:27 | | Derakon_ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has joined #code |
22:30 | | Derakon [Derakon@Nightstar-a3b183ae.ca.comcast.net] has quit [Ping timeout: 121 seconds] |
22:30 | | Derakon__ [chriswei@Nightstar-a3b183ae.ca.comcast.net] has quit [Ping timeout: 121 seconds] |
22:30 | | Derakon [Derakon@Nightstar-a3b183ae.ca.comcast.net] has joined #code |
22:30 | | mode/#code [+ao Derakon Derakon] by ChanServ |
22:31 | | * Derakon_ mutters at Python, tries to figure out how to get his test script, located in util/tests, to run as if it were in . instead. |
22:32 | < Derakon_> | Because otherwise it can't import modules located in . |
22:35 | < Derakon_> | Bleh, the Internet suggests monkeying with sys.path. |
22:35 | <&McMartin> | Yup. -_- |
22:41 | | * Derakon_ writes a short script to run other scripts for him instead. |
22:42 | <&McMartin> | That is more or less what the in-place Ophis scripts do. |
22:42 | < Derakon_> | for filename in sys.argv[1:]: __import__(filename.replace(os.path.sep, '.')[:-3]) |
22:42 | < Derakon_> | I do like [:-3] |
22:42 | < Derakon_> | It looks like a face. |
22:43 | <&McMartin> | Heh |
22:43 | <&McMartin> | [<3] <-- ASCII Companion Cube |
22:43 | < Derakon_> | Yes. |
22:56 | < Derakon_> | Okay, basic test of the serializer is working... |
22:56 | < Derakon_> | Deserialization is going to be a bit trickier of course. |
22:58 | < Derakon_> | The main trick being recreating object relationships, which may be circular. |
22:58 | < Derakon_> | So I have to make "blank" objects to start out, and then fill them in later with the serialization stuff. |
22:58 | < Derakon_> | Once I have all of the object instances created, that is. |
23:08 | < Derakon_> | Bleh, the serializer module is going to depend on every module that creates any kind of in-game entity. |
23:08 | < Derakon_> | Since it has to be able to create all of 'em. |
23:09 | | * Reiv eyes that, muses. |
23:10 | <@Reiv> | Could it be done that the serializer instead accepts generic inputs? |
23:11 | < Derakon_> | I'm talking about deserialization now, note. |
23:11 | < Derakon_> | And ultimately the deserializer has to be able to recreate the objects that were used to generate the savefile. |
23:15 | < Derakon_> | I guess that the serializer module could have a "registerObjectClass()" function that accepts a string key (name of the class) and the function to call as its arguments. |
23:16 | < Derakon_> | That way every module containing a class type that wants to be serializable depends on the serializer class, instead of the other way around. |
23:17 | | * TheWatcher applies corn pops to Dera's code |
23:17 | | * Derakon_ bemoans the lack of milk. |
23:18 | <@TheWatcher> | Your code should decerealise it anyway!~ |
23:18 | | * Derakon_ aims for the cymbals, misses, baps TW on the head with his drumstick. |
23:19 | | * TheWatcher tings! |
23:19 | <~Vornicus> | Alternatively, you could have each object type register itself with the deserializer module. |
23:19 | < Derakon_> | That's what I just said, Vorn. |
23:19 | <~Vornicus> | oh you said that |
23:19 | < Derakon_> | GMTA~ |
23:19 | <~Vornicus> | I can read everything, really |
23:19 | < Derakon_> | Everything, eh? |
23:19 | < Derakon_> | I should send you some of the legacy code I have here~ |
23:20 | <~Vornicus> | oh god |
23:20 | <@TheWatcher> | Isn't that against the geneva convention, or something? |
23:20 | < Derakon_> | Neither of us are combatants~ |
23:37 | < Derakon_> | Testing savefile looks like this: http://pastebin.com/U12wUB3Q |
23:38 | < Derakon_> | DummyThing is a class that has two functions, testA and testB. I create two DummyThings with IDs 0 and 1, and set their "funcPointer" member fields to point to each others' functions. |
23:38 | < Derakon_> | There's also a Container that holds both DummyThings. |
23:42 | <@Reiv> | Derakon_: I suspect that the latter method, of registering with the deserializer module, would actually work out better. |
23:42 | < Derakon_> | Yes, that's what I'm going with. |
23:42 | < Derakon_> | Much, much better to have many modules depend on one module that doesn't depend on anything, than to have one module that depends on many modules that depend on all kinds of other htings. |
23:42 | <@Reiv> | It puts the onus on compatability with the modules as they're created, as opposed to trying to be maintained by the deserializer. |
23:42 | < Derakon_> | Er, things. |
23:43 | < Derakon_> | The latter is a recipe for circular dependencies, and those can be a pain to get rid of. |
23:43 | <@Reiv> | Yah |
23:43 | | * Reiv is Helping! Kind of! |
23:43 | | * Derakon_ patpats. |
23:44 | | * Reiv totally does understand mid-tier programming design, honest! |
23:45 | | * Reiv specifies mid-tier, because he's at least beyond basic, but not quite up to Advanced, and the skills he has are rapidly atrophying anyway >_> |
23:46 | < Derakon_> | This is what practice is for~ |
23:46 | < Derakon_> | (He says, knowing that many people don't have the time to practice, nor a specific project to work on) |
23:47 | <@Reiv> | I ssssort of have a project I could kiiiind of poke at |
23:48 | <@Reiv> | but its scope is beyond my skills, and I struggle to find somewhere to start. |
23:49 | | VirusJTG [VirusJTG@Nightstar-09c31e7a.sta.comporium.net] has joined #code |
23:56 | | Turaiel is now known as Turaiel[Offline] |
--- Log closed Tue Jul 02 00:00:03 2013 |