wolfgangj / bone-lisp

The Bone Lisp programming language
Other
321 stars 21 forks source link

Add sys.gettimeofday? and std/bench #7

Closed dubek closed 8 years ago

dubek commented 8 years ago

Commit 1

Microsecond-timing available via sys.gettimeofday? (added tests/posix.bn too):

Bone Lisp 0.4.0-pre
@0: (sys.gettimeofday?)
(1467210688 959696)
@1: (sys.gettimeofday?)
(1467210694 231724)

Commit 2

Add std/bench module to allow measuring elapsed time of code:

Bone Lisp 0.4.0-pre
@0: (use std/bench)
(std/bench)
@1: (mysub (long-op x) (unfoldr =0? id -- x))
#sub(id=0x7f993fee00d5 name=long-op argc=1 take-rest?=#f)
@2: (long-op 10)
(1 2 3 4 5 6 7 8 9 10)
@3: (say-time (long-op 10))
Running (long-op 10) ... Elapsed: 30 usecs
#t
@4: (say-time (long-op 100))
Running (long-op 100) ... Elapsed: 233 usecs
#t
@5: (say-time (long-op 1000))
Running (long-op 1000) ... Elapsed: 2341 usecs
#t
@6: (say-time (long-op 10000))
Running (long-op 10000) ... Elapsed: 8607 usecs
#t

As for the second commit, I'm not sure the names I chose (usec-diff, measure, say-time) are the best fit. Suggestions for changes are welcome.

wolfgangj commented 8 years ago

This is cool... and looks good so far. A few thoughts:

usec-diff seems generally useful in combination with sys.gettimeofday?, maybe it should be in a posixprelude.bn file that gets loaded by boneposix.c, what do you think?

Since sys.gettimeofday? may return false on failure, we should check for that. Probably posixprelude.bn should contain a convenience subroutine like:

(defsub (gettimeofday)
  "..."
  (aif (sys.gettimeofday?)
       it
    (err "...")))

How about renaming usec-diff to timeofday-diff? This suggests the relation to sys.gettimeofday?.

Maybe rename measure to measure-time?

wolfgangj commented 8 years ago

By the way, what about copyright notices and licensing info in the files?

dubek commented 8 years ago

All suggestions sounds good, I'll try them (not sure I'll get to it today).

As for the copyright notices, I'm not sure what I should do. How is it different than adding some lines to an existing file? I don't mind handing you the copyright to the code (it's gonna stay in your project...). Let me know if I should copy the template from the other files.


BTW - I have a hidden agenda with all these small contributions - I want to try to implement Mal ( https://github.com/kanaka/mal ) in bone-lisp. I'm still not sure how can I implement something like env_set (mutable key-value map) using bone-lisp (and there's the memory mgmt thing to wrap my head around, but that's the whole idea of this exercise :-).

wolfgangj commented 8 years ago

Copyright: The correct thing would probably be to add your name to all files that you have changed, and put only your name in files that you created. Copyright assignment is not possible in all countries. But if you prefer to stay anonymous, you can also just copy the header with my name from other files. The most important thing is that there is a license statement.

Mal: That's going to be interesting. If you use a tree to store an environment, you don't have to copy too much data when creating a new version of the environment. You could try to use reg-loop as a copying garbage collector (but currently, copying does not recognize shared subtrees).

The easy solution would be to add mutable hash tables that need to be deleted manually. There is a hash table implementation already, so it's trivial to make it available to Bone code. But then you've got nothing to wrap your head around anymore. ;)

Feel free to always discuss your ideas about implementing Mal here (you could open an issue for such a discussion, for example).

wolfgangj commented 8 years ago

I just realized: Since bone_init() does not load prelude.bn, bone_posix_init() also should not load posixprelude.bn. That should be done in main() to be consistent. I got that wrong above.

dubek commented 8 years ago

We can have (use posixprelude) at the end of prelude.bn, or add a bone_load("posixprelude"); in main.c. Identical effect, I believe. IMO clearer in main.c.

dubek commented 8 years ago

Re: mutable hash table - I thought all bone data types are immutable... So I assumed you wouldn't want to add it.

I don't mind performance, so the env map can be alist and set(k,v) can return a new alist, and then use reg-loop to replace the "current-env". Then comes the atom data type (similar to Clojure atom) which is mutable... The Erlang implementation of Mal resorts to holding a separate erlang process for each mutable object (mal env or mal atom).

dubek commented 8 years ago

Another try at gettimeofday and std/bench (force-pushed to same branch).

wolfgangj commented 8 years ago

Re posixprelude: This should not be in prelude.bn, because the POSIX module is supposed to be optional. main() is a good place because that's where we decide whether we activate the POSIX bindings. I.e. a program that wants to include Bone Lisp as a scripting language would not include main.c anyway and should be able to use prelude.bn unaltered.

Re immutability: Well, I am not dogmatic about it at all (in fact, there is already _var! which changes a global binding, though it's intended for internal use only), but there is a reason for chosing immutability: It's the simplest way to ensure that there won't be any dangling pointers. For example:

(with x 0
  (in-reg (set! x (list 0)))
  x

This would return a dangling pointer. For the same reason, Bone does not have reg-new/reg-destroy! but restricts the use of regions to in-reg and reg-loop.

However, there is nothing preventing us from providing an unsafe module. (But note that the current VM implementation does not allow the implementation of set! because closures have their own copys of bindings; this avoids a bit of indirection when accessing free variables).

I did not work on this so far because I want to see how far I can get without it, and don't want to be tempted to use these features all the time. :) But I expect that eventually they will probably be added anyway.

dubek commented 8 years ago

Thanks for the sys.errno fix.

Re: immutability: According to the classic Lisp process, eventually you'll have to write a Bone Lisp evaluator in Bone Lisp :-) The question is whether you have the tools to do it. I'm also interested in the "how far can you go without mutability".