beneroth changed the topic of #picolisp to: PicoLisp language | The scalpel of software development | Channel Log: https://libera.irclog.whitequark.org/picolisp | Check www.picolisp.com for more information
galambo has joined #picolisp
galambo has quit [Quit: Leaving]
geri has quit [Remote host closed the connection]
taleon has quit [Quit: leaving]
taleon has joined #picolisp
<tankf33der> hi all
<tankf33der> abu[7]: do you care or have opinion about bitcoin privacy?
<tankf33der> do you care i know your BTC balance or can follow your transactions?
<abu[7]> I think it it not a good idea to communicate such info in the public
<abu[7]> This would invite attackers
<tankf33der> but user's public address is in public?! :/
<abu[7]> Yes
<tankf33der> it is so strange noone care.
<abu[7]> But they don't know the personn
<abu[7]> They might feel invited to even break into my house and steal hardware
<tankf33der> some robbers did this trick in california.
<tankf33der> 20 cases! insane.
<abu[7]> wow
<tankf33der> seen in reddit.
<abu[7]> Any robber reading here: Please don't try, I have nothing here in unencrypted form ;)
<tankf33der> :)
<tankf33der> discussion ended. thanks.
<abu[7]> 👍
galambo has joined #picolisp
galambo has quit [Quit: Leaving]
geri has joined #picolisp
<geri> hey, what does llvm~store do exactly?
<abu[7]> Nothing big. Just stores a number in memory
<geri> just replacing car of whatever you pass to it?
<abu[7]> Not necessarily a cell
<abu[7]> can also be on stack or in an array
<geri> hm
<geri> (use) was basically responsible for the bind stack right?
<abu[7]> right
<geri> so question is, when in a function i do (de symbol . things), it may just override a non-local binding?
<abu[7]> 'de' does a global 'set'
<geri> yeah
<geri> okay, that was what i was thinking
<abu[7]> Not binding in the sense of "local"
<geri> (use symbol (de symbol ...)) would work right?
<abu[7]> yes
<geri> okay
<geri> makes sense
<abu[7]> like setq
<abu[7]> just with some proper
<abu[7]> ties
<geri> yee
<geri> i was also wondering if up may get slow :D
<geri> if you search for a binding that was defined forever ago
<abu[7]> could be
<geri> aighty, thanks
<abu[7]> Such an 'up' would be unusual I think
<abu[7]> not very useful
<abu[7]> cause you cannot assume many levels up
<abu[7]> T used 'up' very seldom
<abu[7]> (or never in production?)
<abu[7]> Hmm, a few cases
<geri> its sad when you implement something and it never gets used...
<geri> also new question - how did (load) interact with transient namespace again?
<abu[7]> It clears the transients at start and at exit iirc
<abu[7]> no
<abu[7]> saves locally
<abu[7]> and then restores on exit
<abu[7]> ... (set $Transient Tr1)
<abu[7]> llvm~repl
<geri> setCooked? :D
<geri> is repl both for interaction and loading files
<abu[7]> yes
<abu[7]> (load)
<abu[7]> gives a nested repl
<geri> i dont get the arguments llvm~repl uses
<geri> Exe is the typical lisp arguments iirc
<abu[7]> right
<geri> then i guess pointer to a string with 8 bits per character?
<abu[7]> (load "-f00")
<abu[7]> hmm
<abu[7]> no
<abu[7]> this is the X arg
<geri> ah, (load NIL) is actual repl
<abu[7]> Exe is the standard one, as you said
<abu[7]> T
<abu[7]> The llvm~main loop uses stdRead and stdEval
<geri> hm
<abu[7]> "std" means stdio here
<geri> why not (load)?
<abu[7]> 'load' is a general case of all that
<abu[7]> higher level
<geri> like let vs use?
<abu[7]> goes to loadAll or repl
<abu[7]> it is more involved
<abu[7]> loadAll calls repl in a loop
<abu[7]> also from main
<abu[7]> for command line args
<abu[7]> Internally it boils down to stdXXX if on stdout
<abu[7]> stdin I mean
<geri> okay
<geri> i worked some more on my interpreter and i got namespaces now
<abu[7]> Great!
<geri> core:list is how you get a value out and :symbol force-interns the symbol in private namespace, which is first in search order
<geri> so kinda same thing as you said about "dynamic binding, lexical scoping"
<geri> it was tough but very fun :D
<geri> wanted to go with namespace.symbol, but dot is used for pairs already
<geri> does (apply) wrap arguments in symbols no matter if its a builtin or a lisp form
<abu[7]> correct
<geri> do you think itd be faster if you just pass arguments if its a builtin and wrap if its a lisp form?
<geri> sounds like less gc'ing
<abu[7]> You cannot just pass args to a builtin
<geri> why not?
<abu[7]> The point is to quote the evaluated args
<geri> im saying
<geri> quote if its a lisp level function
<geri> pass as is/cdr if its a builtin
<geri> cause all your builtins only take Exe as an argument
<geri> "apply" here is just passing args to the function
<abu[7]> You could make a 'applyExpr'
<geri> different if its lisp forms, there you need quoting
<geri> well that's what im thinking too
<geri> im not sure if itll actually give much of a bonus to performance though
<geri> im thinking about that cause i use basically mapcar with symbol wrapping in my eval for lambda case
<abu[7]> Not much performance gain I think
<geri> a bit less gc per call in theory
<geri> but you're probably right
<abu[7]> why gc?
<geri> you wrap stuff in symbols
<abu[7]> there is no consing
<geri> you create those symbols, no?
<abu[7]> but no gc
<abu[7]> on the stack only
<abu[7]> just push
<geri> like, you only use one symbol on the stack?
<abu[7]> You saw Apply in doc/structures
<geri> ye
<abu[7]> the tangled structure
<abu[7]> this is just a series of pushes
<abu[7]> and then popped off
<abu[7]> not gc'd
<geri> so the whole thing is on the stack?
<abu[7]> right
<geri> hmmm
<abu[7]> cells created on the stack
<geri> ah
<geri> so normal cells, just the compiler takes care of deallocating it
<geri> instead of gc
<abu[7]> T
<geri> neat
<abu[7]> runtime code created by compiler
<abu[7]> inc of SP
<geri> microforth in picolisp!
<abu[7]> :)
<geri> is there a "flat" version of use?
<geri> like match vs let
<abu[7]> 'use' only saves the values of symbols
<abu[7]> no nesting possible
<geri> hm
<abu[7]> It keeps the sym values unmodified
<geri> just adds the saved value to the bind stack until end of (use) call
<abu[7]> yes
<geri> does let call use many times?
<abu[7]> It does not call 'use'
<abu[7]> but like 'use' it saves the values
<geri> (set $Bind ...)
<abu[7]> plus sets new values
<geri> im confused now, is $Bind on the stack or heap? xd
<abu[7]> Bind is the pointer to a linked list completely on the stack
<abu[7]> Only 'cons' and deravates allocate on the heap
<abu[7]> at the end of @src/gc.l
<abu[7]> cons, consNum, consSym etc
<geri> fun stack programming
<geri> wait, (a b c .) is a reader syntax for circular list??
<abu[7]> T
<geri> kinda hard to read rdList
<geri> what's $Get?
<abu[7]> Fetch a single byte from the current stream
<geri> okay
<geri> what's with (let L R ...) part in last if?
<abu[7]> Iterate over R while keeping it
<geri> not that, im not sure what exactly its doing with setq's
<abu[7]> It finds the last cell in R
<geri> okay, and rdl?
<abu[7]> It is just a factorization of rdList to re-use certain parts
<abu[7]> All after (let (X (safe (read0 NO)) is for "~" read macros
<abu[7]> splicing
<geri> ah
<abu[7]> The loop in rdList in most of the cases xitd in (? (<> @ (char "~"))
<abu[7]> *exited
<geri> i dont get where the circular list reading is done
<abu[7]> in rdl
<geri> what does ? mean in pilsrc?
<abu[7]> Similar to T in loop in normal Lisp
<abu[7]> but ? may be in sub-expressions
<geri> hmm
<abu[7]> (in Lisp this is not feasible)
<geri> :(
<geri> like many options for TCO
<abu[7]> On llvm level we can jump anywhere :)
<abu[7]> T
<abu[7]> same thing
<abu[7]> jump
<geri> you got tailcall instruction in llvm ir
<geri> could maybe add a builtin to tail call current function for nearly free
<abu[7]> That's not the problem
<geri> wdym
<abu[7]> You have to jump to a completely different context
<abu[7]> Think of like:
<abu[7]> (de f () (while .. (in .. (if .. (f)))))
<abu[7]> Jump to the 'while'?
<geri> most likely
<abu[7]> How to clean up all between?
<geri> no idea!
<geri> im not very good with tco
<abu[7]> And all that to just avoid a loop!
<geri> mal has some strategy where if, prog and lambda actually loop back within eval at some point
<abu[7]> A loop is more clear in an iterative situation
<geri> so you get your tco
<geri> sometimes loop is better, other times recursion is better
<abu[7]> right
<geri> its just sad that without tco recursive option is gonna eat the stack up
<abu[7]> You need recursion to traverse trees
<geri> yeah...
<abu[7]> but not for liner code
<geri> linear*
<abu[7]> T :)
<geri> thats why recursive descent parsers, recursive eval, recursive print, etc.
<geri> :D
<abu[7]> Anyway TCO would be nice sometimes
<abu[7]> but not feasible for an interpreter
<abu[7]> not efficient at least
<geri> most options involve tons of overhead by allocating closures
<geri> or wrapping a lot of stuff in first class functions
<abu[7]> yeah
<geri> that's why im not really looking into tco for my interpreter currently, cause its supposed to be a pure interpreter xd
<geri> i love that in compilers you get to write the language in itself and it can be very efficient
<geri> llvm-ir is a good middle ground, but its not exactly the same language
<abu[7]> the same as what?
<abu[7]> ah
<abu[7]> itself
<geri> yes
<geri> pilsrc vs pil
<abu[7]> T
<abu[7]> It needs different semantics
<abu[7]> operates on different data structures
<geri> i mean, dont most compilers operate on ast?
<geri> and lisp is pretty much pure ast
<abu[7]> Yes Syntax
<abu[7]> the thing is semantics
<abu[7]> Lisp can't manipulate the stack for example
<abu[7]> PilSrc maps to a CPU
<abu[7]> not syms and cells
<abu[7]> The syms and cells are the product
<geri> :(
<geri> no stack for us
<abu[7]> On the semantic level, PilSrc is C and not Lisp
<abu[7]> Only syntax is Lisp
<geri> do you gain much from going to llvm instead of just writing C?
<abu[7]> yes
<abu[7]> stack manipulation
<abu[7]> and CPU flags
<abu[7]> (mainly carry flag)
<geri> okay
<abu[7]> L)
<geri> afaik llvm is incredibly complex though
<geri> probably worth it in some cases, maybe not in other
<abu[7]> Yes, but I don't use it. Only llvm-ir
<abu[7]> llvm-ir is a generalized assembler
<abu[7]> so more powerful than C
<geri> so you get assembly with at least somewhat familiar interface and its portable
<abu[7]> yeah
<geri> are cons cells on the stack only possible cause of llvm?
<geri> like new cells i guess
<abu[7]> No, in C you can have them too
<abu[7]> cell structs
<geri> hmmmmm
<abu[7]> But in C you cannot decrement the stack pointer in a loop, or create and jump between stack segments (needed for coroutines)
<geri> :(
<abu[7]> llvm~stack can get the current hardware stack pointer, and it can also set it to another value
<geri> you can probably do it with some inline assembly
<geri> but again, rip portability
<abu[7]> Yes, assembly
<abu[7]> Thats why the first versions of pil were asm, then C, then asm again and then llvm~ir
<abu[7]> AFAIK only Forth gives you such full control over the stack
<abu[7]> (RP here)
<geri> rp?
<geri> return stack pointer?
<abu[7]> yep
<geri> yeah, manual tco :D
<abu[7]> SP and RP in Forth
<geri> i doubt you can write an amazingly fast lisp interpreter in forth though
<geri> 😔
<abu[7]> probably not, frequent stack operations are expensive
<abu[7]> as opposed to registers
<geri> yeah..
<abu[7]> A hardware Forth CPU would be the best
<geri> think itd be comparable to x86 performance?
<abu[7]> At least a bit closer, if the stacks are in very fast internal memory (like the registers of a normal CPU)
<abu[7]> Execution may be slower, but the code be more compact, giving better cache efficiency
<geri> oh that's fun
<geri> ik some of the better forths use cache for a few of the top stack items
<geri> sorry, registers*
<geri> thats why treating the stack as an array is not recommended
<abu[7]> But this keepinp TOS and some more entries in register has other overhead
<geri> can't you just allocate a chunk of memory for the stack and "stack-allocate" in there?
<geri> cause memory is already allocated it should be fast
<geri> or stack manipulation is more about what usually happens behind the scenes in C
<abu[7]> Yes, you can do such tricks (in fact I had coroutines in lifo (in C)), but this always implies assumptions which are not guaranteed because C hat no concept of the stack in the language)
<geri> do you have examples of those assumptions?
<abu[7]> We have a model of a large array on the stack, but the compiler may optimize it away
<abu[7]> model in our mind I mean
<geri> i bet thats part of the reason the phrase "no compiler to mess with your code, you get what you see" has been said in regards to picolisp :D
<abu[7]> We allocate a big struct, but *mean* "please decrement the stack"
<abu[7]> Exactly :)
<geri> what's faster, (quote X) or a symbol constant, like T?
<geri> :)
<geri> to defer
<geri> deref*
<abu[7]> A symbol value
<abu[7]> inline 'eval'
<geri> aha
<geri> and if there wouldn't be inline eval?
<abu[7]> a single machine instruction for a symbol, but a complex function call for 'quote'
<abu[7]> Also
<geri> okay fair
<abu[7]> but one more call
<geri> one more call for quote?
<abu[7]> T
<abu[7]> eval as function and then quote
<geri> ah yeah
ygrek has joined #picolisp
<abu[7]> So the inline eval handles num and sym directly
<abu[7]> test and jump
<geri> "directly" like removing 1 function call?
<geri> eval is used a lot so probably more than worth it
<abu[7]> "directly" inline
<geri> oke
<abu[7]> no jump or call to it
<abu[7]> (cond ((num? X) X) ((sym? X) (val X)) ..
<abu[7]> only for lists it calls something
<geri> ahem ahem
<geri> *list processing*
<abu[7]> T
<abu[7]> The above 'cond' results in:
<abu[7]> testb $6, %al
<abu[7]> # %bb.1: #
<abu[7]> jne .LBB237_4
<abu[7]> testb $8, %al
<abu[7]> jne .LBB237_2
<abu[7]> 6 are the num tags
<abu[7]> 8 is s)m
<geri> lovely label names
<geri> very readable
<geri> :D
<abu[7]> indeed
<abu[7]> ah, also this instruction:
<abu[7]> .LBB237_2: #
<abu[7]> movq (%rax), %rax
<abu[7]> .LBB237_4:
<abu[7]> movq is (val X)
<geri> val did what again?
<abu[7]> So this 'eval' is absolutely minimal
<abu[7]> val does a pointer dereference
<geri> ah
<abu[7]> a CAR or a VAL
<geri> btw, example of my bad code if you're curious: https://0x0.st/8rFk.cy
<abu[7]> Is this your Lisp?
<geri> yes
<abu[7]> 👍
<tankf33der> looks like clojure.
<geri> its a bit of everything
<tankf33der> ok
<geri> not clojure yet though
<geri> :D
<abu[7]> nice
<geri> stole "nlambda" from interlisp
<geri> cause "macro" is inacurate, its just fexps
<geri> s/acu/accu/
<geri> but yeah, im having tons of fun :D
abu[7] has left #picolisp [#picolisp]
abu[7] has joined #picolisp
<geri> aighty, gotta sleep
<geri> laters
<abu[7]> o/
geri has quit [Quit: ERC 5.5.0.29.1 (IRC client for GNU Emacs 29.4)]
ygrek has quit [Remote host closed the connection]