#qi-hardware IRC log for Saturday, 2013-03-16

hellekinOMFG. OMFG. https://twitter.com/Sysadm_Borat/status/312705773333524480/photo/1 "for loops are for pussies"00:45
whitequarkhellekin: I dunno why, but asian embedded really, really frequently features such code00:48
whitequarkit's not even funny00:48
hellekinwhitequark: really? Wow. That's scary.00:50
hellekinWhen "don't fix it if it works" doesn't apply, for reason that newbies could start contaminating their code with stupidity. 00:50
whitequarkhellekin: yeah. from a 1.5-second delay for boot led from nops00:52
whitequarkto literally such unrolled shell loops I've been shown just days ago by a fellow dev00:52
whitequarkI'd say it's scary for another reason00:53
whitequarknetworked embedded is generally very security-sensitive. and I don't want people writing such code anywhere near anything sensitive.00:53
hellekintrue00:55
hellekinI've never learned coding formally, but I would never even think of doing such horrible code00:55
hellekinI'm pretty sure it requires a mouse, because people who knows how to copy-paste with the keyboard cannot be that lazy and stupid. Or can they?00:56
hellekins/knows/know/00:56
viricsure, acn00:58
viriccan00:58
viricpeople use *fancy* editors for that.00:59
whitequarkI don't wanna know...00:59
hellekinit's even longer to type than the real thing. You gotta be braindead to write such "code"01:07
hellekinah. skip it. There's enough shit in this world01:07
kyakviric: it's more clear now for me why you have to create the complete query every time17:32
kyaki.e. even if i change one parameter, i send all the others in the form as well17:33
kyakit is also clear now why C is not something one should use to handle WEB :)17:33
kyakthe problem is, you don't have persistent storage.. You fork every time for new request, and children don't have any knowledge about the client's state17:34
kyakthat is why, the client has to send the complete state every time: "show read", "single page", "local image" and so on..17:35
kyak..and it took me hell of a lot of time to realize why "extern" variable is reset to 0 every time17:36
kyakbecause of fork, of course17:36
whitequarkmy compiler can now infer types for and compile fib()!17:40
whitequarkhttps://gist.github.com/whitequark/2d1d44ed5d97ddc9c93317:40
kyakviric: there is something called a "Persistent CGI", which is probably worth having a look into..17:42
larscwhitequark: nice17:42
whitequarklarsc: actually you don't see the majority of the interesting things there :D17:43
whitequarki.e. how it handles the ruby object system17:43
whitequarknext on the roadmap are proper machine ints (currently it's a single, degenerate ptr-sized type), and lambdas17:44
whitequarkthe cycle in `main' should look like `10.times { trace fib(10) }'17:44
whitequarkbut compile to exact same code, because why not?17:45
pcercueiwhitequark: compiler for what?17:46
whitequarkpcercuei: http://whitequark.org/blog/2012/12/06/a-language-for-embedded-developers/17:46
larsc10.times ? so you can do like Integer n = 5; n.times { ... }?17:46
whitequarklarsc: why "Integer n = 5"? just n = 5; n.times { ... }17:47
whitequarkand yes I can17:47
whitequarkthe compiler features both local type inference by bidirectional dataflow analysis on static single information form and interprocedural type inference via cartesian product algorithm17:48
larschow does the algorithem work? I'm currently working on something very similar for migen17:49
whitequarklarsc: which one?17:49
larsc type inference17:49
whitequarkwell there are two: local and interprocedural :)17:49
larscstart with local17:49
whitequarkit's a distant derivative of Hindley-Milner17:50
whitequarkmy IR is in SSA/SSI form, which can be thought of a purely functional language (SSA is isomorphic to CPS, used in functional compilers)17:50
whitequarkso HM works perfectly on the SSA values17:51
whitequarktype unification in canonical HM corresponds to SSA phi nodes17:51
larscthe current migen algorithem, if you even can all it that, is dead stupid. just tries to derive the type 'for' each signal in a loop until each signal has one17:51
whitequarklarsc: HM is not significantly more clever17:51
whitequarkbut it can handle conflicts17:51
whitequarklike e.g. if foo; 1; else "2"; end17:52
whitequarkthe HM-derived resulting type would be Integer|String17:52
whitequarkwhat I do in these cases is restrict the resulting unions so that runtime perf would be manageable17:53
whitequarkTrueClass|FalseClass is reduced to Boolean (internal, not ruby type)17:53
whitequarkBase|Derived is reduced to Base17:53
whitequarkUnrelatedA|UnrelatedB is reduced to Object, well, because everything inherits from Object17:53
larscmakes sense17:54
whitequarkalso NilClass|Whatever is reduced to nullable<Whatever>17:54
whitequarkand that's mostly all17:54
whitequarkotherwise you would end up with union types which would require essentially dynamic dispatch17:54
whitequarkand perf will go nowhere17:54
whitequarkalso I handle types for mutable local bindings in a very similar fashion17:54
larscmutable local bindings?17:55
whitequarkaka "variables" :)17:55
larscah, ok17:55
whitequarkthe kink with local variables is that they're mutable and HM is purely functional17:55
whitequarkloop { a = 1; a = "2" if rand > 0.5; p a }17:56
virickyak: I fork in offrss because I don't want memory leaks17:56
whitequarklarsc: now there's also upwards DFA, which handles closures17:56
whitequarksee, the type of a closure is derived from its usage, as opposed to definition17:57
virickyak: and it's a matter of taste, when to fork.17:57
whitequarklarsc: def loop(&block); while true; block.call(); end; end17:57
virickyak: I fork at the very start, because it's like CGI. I don't think I need much persistent storage. Does it run slow for you?17:57
whitequarklarsc: as you can see this method has a well-defined type of `block', but downwards DFA could not infer it...17:58
whitequarklarsc: the other clever thing one could do with bidi-DFA is latent predicates17:59
whitequarklarsc: for example this: def foo(bar); if bar.is_a?(Integer); bar + 1; else nil; end; end17:59
whitequarklarsc: without #is_a?(Integer), the method could not typecheck if I pass a String there17:59
whitequark*would18:00
larsci see18:00
kyakviric: nah, it's not slow at all. I just don't like the way you have to construct the complete query (i.e. configuration) every time18:00
whitequarklarsc: it's like pattern matching from haskell, but with none of the monads :D18:00
kyakviric: it looks redundant in C code, and you have to think about the complete configuration all the time18:01
whitequarklarsc: now, interprocedural inference is even simpler. imagine that every function, initially, has a polytype where each argument is assigned its own type variable18:01
kyakviric: why am i even talking about  - i'd like to have "mark all as read" button, and the design is such that it can't be easily extended18:01
virickyak: I could use a cookie. But I never learnt cookies18:01
whitequarklarsc: forall(a,b) Integer#+(a self, b other)18:01
whitequarklarsc: note how self doesn't have a monotype either. this is because you can inherit from Integer, and in the derived class self would not have the type Integer18:02
virickyak: yes, web without cookies is harder. :) Maybe they'd really simplify all18:02
whitequarklarsc: now, if you encounter a call, say, (Fixnum < Integer) Integer#+(Fixnum 1, Fixnum 2), you specialize the method for that particular call site.18:03
virickyak: but then the state is not per browser window, but per browser.18:03
larscwhitequark: what does #+ do?18:03
whitequarklarsc: addition18:03
whitequark1 + 218:03
whitequark# is just a separator between class name and method name.18:03
larscand the hash means that it's a method of the type... ok18:03
whitequarklarsc: so, now instead of a method which can accept anything you have a method which only accepts Fixnums18:04
whitequarkso you can eliminate a ton of redundancy. type checks, range checks (sometimes), etc. you can do inlining. it's awesome actually18:04
whitequarkyou can do partial specialization. say if you don't know what the second argument is, you infer forall(a) Integer#+(Fixnum 1, a var)18:04
whitequarkyou still can eliminate half of the redundancy and maybe inline the method18:05
whitequarkand the algorithm is closed over composition, that is, you can specialize the methods over and over again if you know more and more about your code18:05
kyakviric: i'll try to implement that button, and we'll see how it goes. If it turns into a monster, perhaps it's a good sign to rewrite server.c :)18:05
whitequarklarsc: what's even more interesting is what happens when you get to parametric types. you can do restrictions on type variables!18:06
whitequarksay we have a generic List18:06
whitequarkforall(a) List#append(List<a> self, a elem)18:06
virickyak: ok :) think of a cookies model if you want18:07
whitequarklarsc: this method can be specialized for any element type, but only ones which match the type of the list18:07
whitequarkwhat actually happens is that 18:07
whitequarkyou speculate that you can specialize this method for List<Integer>, so you basically replace a with Integer18:07
whitequarkthen, if the result, being substituted at the original callsite, still typechecks, this means we're good18:08
whitequarkotherwise someone screwed up :)18:08
larscso what does forall do?18:08
larscis it a predicate?18:08
whitequarkhah, I actually have this on my compose key18:09
whitequarkyes.18:09
whitequarkit does not figure in the language syntax itself, of course (neither does `#'); I'm using this because it's common notation18:09
kyakviric: i just want to make it completely clear. For example, when i click the yet-to-be-implemented "mark all as read" button, i need to send not just the state of this button, but also all the other states - like "show read", "local images" etc. Otherwise, the state of the client (my web browser session) would become inconsistent. For example, clicking this button would reset the "local images" button state18:10
whitequarkyou can think of it as a type constructor, if that's simpler. »’a.List<a>’a’List<a>18:10
larscyea18:11
virickyak: I think you are not very used to web programming :)18:11
whitequarklarsc: ok. so. when you already have types dependent on terms, you can add types dependent on values!18:11
virickyak: or are you?18:11
whitequarkfor example forall(Integer a) MachineInt<a width>18:12
whitequarkyou see where it goes :)18:12
larscno18:12
whitequarkok18:12
virickyak: I mean... one think would be to have a persistent storage based on some id, that identifies the browser windows. But that's not very common I think; Most people use cookies, and cookies are per browser and not per window.18:12
whitequarklarsc: MachineInt is a generic class, but it does not accept a type as its parameter, but a value (constant number)18:12
virickyak: giving weird results if you have multiple windows on the same served pages.18:12
whitequarklarsc: the intended result is that we can get to manipulate this number both in the type system, as if it were a type, and, say, typecheck machine int addition:18:13
virickyak: but persistent storage would allow to pass only an id instead of all. But whether it's hard to send an id or send all, is a matter of good programming. Of course I wrote offrss with some kind of 'minimal effort for what I need'. I'll see if I can improve what you want. :)18:13
whitequarklarsc: forall(Integer a) MachineInt#+(MachineInt<a> self, MachineInt<a> other)18:13
kyakviric: i have no idea why you start talking about browser windows. I'm only talking about one window, or one tab now18:13
virickyak: yes, but multiple tabs has to work too18:14
viric(at least, I want it to work)18:14
viric:)18:14
viricwell, I'm sorry but I've to leave now. Tomorrow more!18:14
larschm18:14
virickyak: I quite finished a recent project that took my time, and I can get into it18:14
whitequarklarsc: *and* also as a value. for example: class MachineInt; def <<(Integer bits); raise ArgumentError if bits > @@width; ...; end; end18:14
viric?>:0!18:15
kyak?>:0 :)18:15
whitequarklarsc: (@@width would be a Ruby syntax to extract the value from the corresponding type parameter)18:15
larscok18:15
whitequarklarsc: so, as you can see, we take here a type, governed and enforced by type system rules, and compare it with a user-provided value!18:15
whitequark(in order to prohibit shifts too wide to handle, or whatever)18:16
whitequarknow, the most interesting part of this everything is how it works with Ruby metaprogramming18:16
whitequarkand the answer, it works so well that C++ programmers will die from envy :)18:17
larschehe18:17
whitequarka Ruby class is a type; a Ruby class is also a value; the type system can represent and work with both classes and plain old data18:17
whitequarkand you can directly manipulate everything of this with just Ruby code18:18
whitequarkso, if you need a friggin' compile-time loop, you go and write `while' there. no weird template magic attached18:18
whitequarkif you need to define a method derived from some other runtime property, here you are18:18
whitequarkdynamically generate constant? ok18:18
whitequarkso we have a language which is as fast as C++, strictly more powerful and way easier to write in :D18:19
whitequarkalso if you're going to do something similar, please note that type variables are only a property of, and attached to, and have sense in the context of functions.18:21
larscand I guess you'll be able to attract ruby programmers18:21
whitequarklarsc: that is the point. Ruby, Python, JS, *and* C++ (because some of them do have sense)18:21
whitequarkthe main reasons I chose Ruby as the base for the language are: 1) it is quite well-known 2) sensible, Smalltalk-derived OO model, unlike Java/C++ 3) easy and mostly quite logical metaprogramming18:23
whitequark3) is a total clusterfuck in python18:23
larsctried that today18:23
whitequarkthat didn't stop someone from writing a thing similar to mine called Starkiller as a phd project18:23
whitequarkit is however too academic to be usable18:24
whitequarkWAY too academic.18:24
whitequarkruby's syntax is sometimes really meh (seriously, \C-? in the core of the language?!), but I can fix that18:25
whitequarkruby's stdlib is sometimes (quite rarely) weird, but that's simple and I will fix that18:25
whitequarkwhoever wrote Encoding support was high on something evil18:26
whitequarkoh some other features I have for free in ruby:18:26
whitequark - interpolations. if you write stuff like "this is a long format string: #{foo.to_s}" then what happens? the first part of the long format string is stored in the .rodata; result of foo.to_s is calculated; these two are combined into a rope.18:27
whitequark... which is an implementation detail completely transparent to user code, because user code iterates strings with #each18:27
whitequarkso you can have *very* efficient iteration which is also flash-friendly18:27
larscbut also means that strings are a core feature of the language18:28
whitequarkthey are indeed18:28
whitequarkeven more; in Foundry, UTF-8 is a core feature of the language. (Unless you disable it, but I advise strongly against.)18:28
whitequarkit stores data in UTF-8 to save space and iterates it as UTF-16 or UTF-32 (machine words are 32-bit anyway). corner cases such as surrogate pairs are already handled.18:30
larscI guess one advantage when you are dealing with hdl languages is that all objects are instantiated at synthesis time, so you don't have to deal with unions18:30
whitequarklarsc: indeed18:30
whitequarkHDL is much more declarative than Foundry18:30
whitequarkit's *completely* declarative D:18:30
whitequark*:D18:30
larscalthough it could come in handy knowing which types are compatible, so you can do time multiplexed sharing of blocks18:30
whitequarkyea18:30
whitequarklarsc: one thing I was also thinking about is deeply integrating regexps within compiler18:31
whitequarkso that during compilation it would generate the optimal state machine18:31
larscuh18:31
larscyea, precompling the regex may make sense18:31
whitequarkyou could then trivially parse URIs or HTTP or whatnot; flex is essentially a regexp -> state machine generator either.18:31
whitequarkit can simply invoke ragel and then link the result, as I'm ABI-compatible with C18:32
whitequarkand LLVM's LTO means that it won't generate cruft on the boundary18:32
larscisn't there this google lib for efficent regexes?18:32
whitequarklarsc: hm, not sure18:32
whitequarkruby uses oniguruma. a ruby parser in oniguruma is 2x slower than ruby parser in flex+bison18:33
whitequarkwhich I guess means that oniguruma is a hell of a fast library18:33
larscre218:34
larsca nfa based regex implementation18:35
whitequarkyea I see18:35
whitequarkI wonder if I can disembowel it and generate LLVM or C from the result18:36
whitequarkhttp://lwn.net/Articles/378440/18:37
whitequarkactually, ragel can simply emit ruby code, which I can compile18:41
whitequarkno need in anything extra...18:41
whitequarkbbl18:44
paul_boddiewhitequark: You mentioned Starkiller, but did you look at Shedskin?23:11
Action: paul_boddie knows that whitequark always checks the logs.23:16
--- Sun Mar 17 201300:00

Generated by irclog2html.py 2.9.2 by Marius Gedminas - find it at mg.pov.lt!