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
fbytez_ has quit [Quit: byte byte]
fbytez has joined #picolisp
abu[7] has left #picolisp [#picolisp]
abu[7] has joined #picolisp
msavoritias has joined #picolisp
chexum has quit [Remote host closed the connection]
chexum has joined #picolisp
geri has joined #picolisp
<geri> hey, what's a typical dev environment for using pico?
<abu[7]> It is PicoLisp itself :)
<abu[7]> $ pil +
<abu[7]> Best if you know vi[m], because the "vip" editor integrates it all optimally
<abu[7]> *
<geri> oh, + makes readline work
<geri> good to know
<abu[7]> Yes, + is always recommended for interactive use
<abu[7]> (debug mode)
<geri> okee, thanks
<abu[7]> :)
<geri> is there a way to test if directory exists without (call'ing "test")?
<abu[7]> There is 'info"
<abu[7]> : (doc 'info)
<geri> doc info returns T lol
<geri> im on nix so something might be misconfigured
<abu[7]> hmm
<abu[7]> By default it calls w9m
<geri> ah nvm im just blind
<abu[7]> ok
<abu[7]> or (doc 'info "firefox") etc.
<geri> thanks :D
<geri> very nice
<abu[7]> Or try (vi 'info)
<abu[7]> Then click on symbols with ^K
<abu[7]> No
<abu[7]> it is K
<geri> does it work with any vi
<geri> i got nvi
<geri> (and emacs B))
<abu[7]> Not out of the box
<geri> oki
<abu[7]> Vip runs *inside* pil
<geri> vip is sadly cut out of this release
<geri> i might package it alter
<geri> i might package it later*
<abu[7]> Which version do you use?
<abu[7]> Vip is in the base system
<geri> 20.6.29 on nix
<geri> that last part is the killer
<abu[7]> Yeah, very outdated
<geri> its outdated too? damn
<abu[7]> 4 years
<geri> ouch
<abu[7]> You can download https://software-lab.de/pil21.tgz
<abu[7]> and follow INSTALL
<geri> oh thats why i said package it
<geri> you cant just install stuff on nix unless its packaged
<geri> i tried vip in docker though
<abu[7]> I see
<geri> and vim works
<geri> gotta attach emacs to it later
<geri> )
<abu[7]> Yes, older pil used Vim (and there was some support for emacs)
<abu[7]> But a *lot* less powerful
<abu[7]> Doesn't know about namespaces and built-ins
<geri> sad
<abu[7]> Sorry, in a hurry
<geri> np
<abu[7]> Back later :)
<geri> laters
<abu[7]> ret
<geri> hi
<abu[7]> Cheers
<geri> had to add a lot of (native) calls for filesystem operations xd
<geri> do you know how to check where symlink points to?
<geri> rn using readlink but its really slow
<geri> (call "readlink" dst)*
<abu[7]> Yes, look at the source of vip, it uses readlink
msavoritias has quit [Read error: Connection reset by peer]
<geri> well i managed to shave off like third of run time :D
<geri> vip uses kinda same thing i did but ig its the official way
<abu[7]> 👍
<abu[7]> Sometimes I use realpath() for similar purposes
<abu[7]> (=0 (%@ "realpath" 'N File '(R (`PATH_MAX C . `PATH_MAX))))
<geri> hm
<geri> returns a bunch of numbers
<abu[7]> which one?
<geri> realpath without =0 test
<abu[7]> Must returs a single number
<abu[7]> s/returs/return
<geri> returns 25458112
<geri> hmm
<geri> oh sec
<geri> switched 'N for 'S and it works
<geri> :D
<abu[7]> Can't be ,)
<geri> and guess what
<geri> suddenly clean run is like 1/4th of what it was
<abu[7]> A run of what?
<geri> time used
<geri> 0.2s vs 0.03
<geri> run of my "script"
<abu[7]> You are right, realpath returns a string
<abu[7]> char *realpath(
<geri> i couldnt figure out how to call it before your post xd
<abu[7]> Good :)
<abu[7]> But 'N is ok as we are only interested in null or not-null
<geri> i was interested in the path
<geri> basically checking "if this directory is a symlink and points to a proper file, dont do anything"
<abu[7]> The path is in 'R'
<abu[7]> If we don't pass a buffer, we need to free() the return value
<abu[7]> That's why the above way is used
<abu[7]> 'native' allocates and deallocates the buffer for us
<geri> (native "@" "realpath" 'S filePath '(R (`PATH_MAX C . `PATH_MAX)))
<geri> that's what im using, is anything wrong with it?
<abu[7]> No, but 'N avoids unnecessary building the string
<geri> well i need the path, so its necessary
<abu[7]> The path is returned as a list in 'R'
<abu[7]> from the automatic buffer created by native
<abu[7]> If you want to use 'S, you can pass null for the buffer
<abu[7]> but then you must keep the pointer
<abu[7]> and free() it
<abu[7]> i.e. use 'P or 'N
<abu[7]> convert to string using 'struct`
<abu[7]> then free the pointer
<abu[7]> tedious :)
<geri> do i have a memory leak rn?
<abu[7]> Not if you use (R (`PATH_MAX C . `PATH_MAX))
<abu[7]> Then native allocates *and* deallocabnes
<abu[7]> deallocates
<geri> scroll a bit up, i have 'S for return result and 'R for everything else
<abu[7]> Yes, I said it is fine
<geri> ok xd
<geri> im just confused at this point :D
<abu[7]> Just passing null would be easier but leak :)
<abu[7]> Sorry :)
<geri> hm
<geri> i mean, if i didnt pass anything it just crashed
<abu[7]> Crashing is easy :)
<abu[7]> btw, you don't need R then
<abu[7]> (NIL (`PATH_MAX C . `PATH_MAX))
<geri> to crash?
<abu[7]> so you can omit (use R ...)
<abu[7]> No, crashing is independent of that
<abu[7]> Just if you pass a variable R
<abu[7]> you need to bind it
<abu[7]> (use R ... (%@ ... '(R ...
<abu[7]> Because it is 'set' by the native call
<geri> (native "@" "realpath" 'S "/home/geri/.bashrc" (cons PATH_MAX C PATH_MAX))
<geri> something like that?
<geri> (i dont understand why cons works with 3 values
<geri> )
<abu[7]> (%@ "realpath" 'S filePath '((`PATH_MAX C . `PATH_MAX)))
<abu[7]> oops
<abu[7]> (%@ "realpath" 'S filePath '(NIL (`PATH_MAX C . `PATH_MAX)))
<abu[7]> Just replaced R with NIL
<abu[7]> To avoid (use R
<abu[7]> (I suspect you did not call 'use' or 'let' for 'R')
<geri> yeah thats the whole function
<abu[7]> So sorry, I did not want to confuse but just be correct
<abu[7]> A correct usage of storing in R needs binding R
<abu[7]> It works without, but may cause unexpected errors
<abu[7]> i.e. if some caller happens to use 'R' too
<abu[7]> It might get it overwritten
<geri> i dont really understand half of that readpath command xd
<geri> %@ is an alias for native "@", i.e. use librar(y/ies) current pil uses
<geri> 'S is the return type
<geri> filepath is self-explanatory
<abu[7]> Yeah, it is a typical C mess function
<geri> other stuff i dont understand
<geri> ik it should take a buffer and a buffer size but like what's going on at pico's side idk
<abu[7]> yes, a bit magic
<geri> most other native calls were easy at least
<abu[7]> Pil allocates a buffer, stores the result returned from C in 'R', and frees the buffer
<geri> /magic/ basically
<geri> :D
<abu[7]> Perhaps this is easier?
<abu[7]> (buf P 4096 (%@ "realpath" 'S "lib.l" P))
<abu[7]> i.e. we explicitly allocate a buffer on he stack
<abu[7]> in P
<geri> oh we can allocate stuff too?
<geri> amazing
<abu[7]> 'buf' came with pil21
<abu[7]> Many complicated constructs for 'native' may be not needed any mobe
<abu[7]> more
<geri> oh hey, pico's still going smaller? :D
<abu[7]> Always :)
<geri> sweet minimalism
<geri> time to try to write some more stuff
<abu[7]> Good
<geri> how is pico so fast while being interpreted anyway?
<abu[7]> It kind of "executes" the cell structures directly
<geri> how does it happen in cl/schemes in contrast?
<abu[7]> They are orientet towards compilation
<abu[7]> So they need static binding, which is fast when compiled but slow to interprete
<geri> ah, so embracing the interpretation lets you do that
<abu[7]> In addition, Pil lets each function evaluabne its args by itself
<abu[7]> yes
<geri> neat!
<abu[7]> Compiled code evaluates all args, then calls the function
<abu[7]> Thats a lot less efficient and has more overhead
<geri> oh yeah, i remember about conditional evaluation
<abu[7]> Pil just jumps from built-in to built-n using the cell pointers
bjorkint0sh has joined #picolisp
<geri> it kinda does half of what macros do too
<abu[7]> This is another issuue
<geri> at least most of my macros are like "please dont evaluate this"
<abu[7]> yes, macros are good for compiled code
<abu[7]> Pil uses FEXPs
<abu[7]> and all built-ins are FSUBRs
<abu[7]> so each fun decides what to do with the args
<abu[7]> very flexible
<geri> yeah
<abu[7]> and fast, as no "special" funs exist
<abu[7]> cond, setq etc.
<geri> so pretty much everything is up for edits?
<abu[7]> In which way?
<geri> like if nothing is special you can redifine almost everything
<geri> or something
<abu[7]> Right
<geri> nice
<geri> btw, where'd `de` come from?
<abu[7]> I think it is from Interlisp
<abu[7]> The main reason is shortness
<abu[7]> A predecessor of Pil was 8kLisp
<abu[7]> In 8 KiB
<abu[7]> so every byte was precious
<geri> ah
<geri> like ed!
<abu[7]> T
<abu[7]> sorry, bbl
<geri> but wait, if space was precious, why add space when paren ends on a different line? 🤔
<geri> guessing its easier to see where stuff ends then
<geri> also raydeejay sends their regards :D
<abu[7]> White space in source files does not matter, they are just I/O. But a symbol name like "de" is kept permanently in memory
<abu[7]> Regards to Raydeejay too ;)
<geri> dont extra spaces *technically* increase amount of io you gotta do, making it slower? :D
<abu[7]> That's true, a little
<abu[7]> but skipping white space is fast
<geri> was it fast back then too?
<abu[7]> Relatively, but of course a lot slower due to the hardware
<abu[7]> : (bench (fibo 23))
<abu[7]> 0.003 sec
<abu[7]> I think it was six minutes on 8kLisp
<geri> that's like 10 times faster than my bootstrapping script
<abu[7]> on CP/M 80
<geri> how *time flies*
<abu[7]> Yeah
<geri> also i imagined you going like "oh we need to support shebang? lets make all comments start with shebang, hell with those lisp traditions" and its very funny
<abu[7]> This was exactly the reason
<geri> i knew it
<geri> cause simplicity, fits the agenda
<abu[7]> Hash is "natural" is Unix
<abu[7]> T
<geri> yeah, ive done tons of scripting
<geri> emacs scripts are a hack
<geri> #!/bin/sh
<geri> :; exec emacs -Q --script "$0" -f bootstrap # -*- emacs-lisp -*-
<geri> thats current shebang for the bootstrap script
<abu[7]> uh
<abu[7]> ;)
<geri> :; is my bash prompt!
<geri> polyglot scripts are cool but an unobstructed shebang is nice to have
<abu[7]> yep
<geri> why does (setq a 'b) (print '(+ `a)) work but (let (a 'b) (print '(+ `a))) - no?
<geri> ive tried (let a 'b ...) too
<abu[7]> `a is a read-macro. It is evaluated at read time, not eval time
<geri> how do i unquote properly then?
<abu[7]> You mean the backquote in CL?
<abu[7]> I would not call this unquote, it is a replacement
<geri> yeah, like `(a b ,c) in cl
<abu[7]> 'fill' is similar
<abu[7]> but different syntax
<abu[7]> and more variations
<abu[7]> (let @X 7 (fill '(a b @X c)))
<abu[7]> (let X 7 (fill '(a b X c) 'X))
<abu[7]> and ^ splices whole sublists
<abu[7]> So a read-macro is something different
<abu[7]> The backquote is a nice short syntay
<abu[7]> syntax
<geri> oh great, worked
<abu[7]> Why waste such a precious char on a function
<geri> what does backquote do exactly?
<abu[7]> (the backquote in CL is in fact a function like 'fill)
<geri> yeah
<abu[7]> When the reader sees ` or ~, it reads the next expression, and uses the *result* in the expression being currently read
<abu[7]> Very similar to #define macros in C perhaps
<abu[7]> Well, just kind of :)
<geri> i think i need an example in this one
<abu[7]> (de f () (+ 2 `(* 3 4)))
<abu[7]> (pp 'f)
<abu[7]> gives (+ 2 12)
<geri> cause when i hear "read macros" im thinking something like 'thing gets read as (quote thing)
<abu[7]> Not so wrong
<geri> is it like for optimizations?
<geri> evaluate this once and never again
<abu[7]> Yes, optim, but also avoids re-evaluation
<geri> well, eval once, insert into whatever youve been reading and never waste cpu cycles on it again
<abu[7]> Right
<geri> very cool
<abu[7]> But consider `*Dbg in some sources
<abu[7]> This is a trick :)
<geri> is backquote behaviour also written in pico?
<abu[7]> When 'loading' a file, reading NIL is considered as EOF
<abu[7]> so the file is not further loaded
<abu[7]> The backquote behaviour is in the base system
<abu[7]> in the reader
<abu[7]> (vi 'llvm~read0)
<abu[7]> ((== C (char "`"))
<abu[7]> this line and following
<geri> vi command doesnt work for that one, probably related to nix being itself
<abu[7]> So not written in PicoLisp but in PilSrc
<geri> do you remember where it is in the git tree?
<abu[7]> Ii is in @src/io.l
<abu[7]> Line 1561
<abu[7]> (currert version)
<geri> ah okay
<geri> i thought base would be in like C so the src folder made no sense for me
<geri> cause i know nothing about llvm
<abu[7]> PilSrc looks like Pil, but isn't
<abu[7]> It compiles to llvm
<abu[7]> Well, in fact it *is* Pil, but many functions redefined
<geri> and where is pilsrc defined? :D
<abu[7]> In @src/lib/llvm.l
<geri> its defined in itself? ~w~
<abu[7]> It creates functions in the 'llvm' namespace
<abu[7]> yes
<abu[7]> e.g. 'de' starts writing llvm code to the output file
<geri> snakes eating their tails, yum
<abu[7]> yes :)
<geri> is it like you wrote it once in C, now its migrated to llvm and you can't recover without another version of pico or is there some magical bootstrapping process?
<geri> (not necessarily in C)
<abu[7]> Right, first was C
<abu[7]> Whe pre-compiled src/base.ll is in the distro
<abu[7]> so LLVM can build the interpreter
<abu[7]> After that it re-builds stand-alone
<geri> ah, so base.ll is the kernel fromwhich you can do everything else
<geri> base.lispyLisp
<abu[7]> It is the whole interpreter
<abu[7]> The biggest file in the distro
<geri> it looks kinda scary in this form
<abu[7]> Indeed! Ugly.
<geri> 110896 lines
<geri> im glad nobody has to rewrite that from scratch
<abu[7]> T
<geri> self hosted interpreters/compilers are honestly scary if you're the only developer
<abu[7]> But both pil and llvm are simple enough to do it relatively easily
<abu[7]> A full C compiler is a *lot* more stuff
<geri> write the initial interpreter to interpret your interpreter interpreting code?
<geri> :D
<abu[7]> Kind of, yes :)
<geri> i wrote a very basic lisp parser like 2 days ago, honestly it was kinda hard
<geri> and i did it abusing cl's stream functionality, so no peek or next
<geri> ...need to be written*
<abu[7]> ok
<geri> i cant image how people managed to write lisps in asm
<abu[7]> Takes time, but may be fun :)
<geri> yeah
<geri> i wrote a really bad scheme interpreter in cl too, was super fun
<abu[7]> :)
<geri> i use dynamic variables to implement lexical ones
<geri> xd
<geri> cause i couldnt figure out how else to make `define' actually work
<abu[7]> Not sure about Scheme, but there are many ways it seems
<geri> yeah, way too many to count
<abu[7]> moment, brb
abu[7] has left #picolisp [#picolisp]
abu[7] has joined #picolisp
<geri> wb
<geri> i actually gotta go myself
<geri> enjoy your (dat$) # misused!
<abu[7]> Have a good time!
geri has quit [Quit: ERC 5.5.0.29.1 (IRC client for GNU Emacs 29.3)]
pablo_escoberg has joined #picolisp
<pablo_escoberg> Hey, has anybody played with this:  https://github.com/vygr/ChrysaLisp ?  Seems like a hell of a project and I just heard about it on HN.
<abu[7]> Never saw it
<pablo_escoberg> me too.  But it's quite developed.  Seems like what pilOS could be, almost...
<pablo_escoberg> which actually reminds me of a question I've had for a while:  would it be possible to build some kind of shim that would allow pilOS to use Linux drivers?
<beneroth> looks interesting
<beneroth> the guy behind it was also behind TAO https://en.wikipedia.org/wiki/Tao_Group
<beneroth> I don't know about the pilOS Linux driver question - but I suspect that would require a very large shim. I guess Linux drivers are based on the Linux Kernel ABI. Also somewhat the point of pilOS was to leave all that bloat away.
<abu[7]> Right
abu[7] has left #picolisp [#picolisp]
abu[7] has joined #picolisp
bjork1intosh has joined #picolisp
bjorkint0sh has quit [Ping timeout: 260 seconds]