I think the big question is languages supported. It would be nice, with all the compile to JavaScript/CSS programs, to support code maps. If you invented a generic code map for all languages, that would be way better than anything else I can imagine.
Maybe have the three main backends at least? LLVM, JVM bytecode, and JavaScript?
I do wish programming languages were more about user interface and less about the underlying implementation. What if every Ruby performance improvement were also felt by LLVM and JavaScript? What if eliminating the GIL in Python helped JavaScript?
I am going to support any language, what I need to implement what you saw in the video is just to identify a Code Block with its name (what would be a function or method in most cases). To do that I’ll rely a lot on the fact we give one or more blank lines between function definitions and we ident its content.
I’ll create the different modules of Looset as independent scripts, so it would have a general simple analyzer written in Clojure, but someone else could implement some more advanced analyzer in another language.
I don’t understand your last paragraph there. How would eliminating the GIL (Global Interpreter Lock) in Python help JavaScript? They’re not only different languages, but different implementations, with different goals.
Lua does not have a GIL. Python does. Lua runs faster than Python, but because Lua lacks a GIL, you can’t share a Lua state between OS-level threads, whereas you can share a Python instance among threads. It’s a trade-off in the language design.
And how would focusing on user interfaces instead of implementation help a programming language?
I was just cherry-picking a few things that people had complaints about in languages. I do agree that they are trade-offs. I don’t think making a Lua syntax frontend for Python would be mistaken as Lua. I just think there is much more in common with languages than is different. Could there be a flag for a GIL in Lua to make it easier to write thread safe code? I’m trying to think about what is an actual feature of a language and what is an implementation detail. Can we work less on implementation details (like with languages that are front ends to other VMs, like JVM, LLVM, and BEAM)?
The bottom level of langauges, assembly [1], there is effectively, no runtime (or the runtime is the operating system if you are lucky). As you go up in languages, you start to have more and more of a runtime. Even C (generally speaking, one step up from assembly) has a runtime, if a minimal one. Lua has more of a runtime than C, because it supports garbage collection, closures and coroutines. Can Lua be compiled? Yes (LuaJIT). Does compiled Lua still require a runtime? Yes, because of the garbage collection, closures and coroutines. Can you do those in C? Yes, but … (and it’s a big but) it won’t be recognizable as C, or be so painful to use that no one will use it, or so full of caveats that it’s difficult to use correctly.
Can you use the LLVM backend for Lua? Yes, only because Lua is written in C, and C is one of the frontends to LLVM. Can you use the JVM backend? I guess if there’s a C frontend for the JVM, but then you end up with two garbage collectors—the one in Lua and the one in the JVM. It probably won’t hurt, but it’s a waste of space to have two. I suppose you could remove the Lua specific GC if the backend is the JVM, but the Lua GC is generational (5.4, previous were more mark-n-sweep I think), I don’t know what type the JVM implements but different GCs have different performance and issues (reference has problems with circular references; mark-n-sweep don’t but impose some latency).
There are also implementation details that leak through. Lua supports tail-call-optimizations [2] and Python does not. This “implementation detail” can make or break certain approaches to problems. For one thing, it can make a recursive function (or mutually recursive functions) consume no stack space if supported. Python, or rather Guido van Rossum, absolutely refused to implement tail-call optimizations because it “will break stack traces”. But using tail-call optimizations with mutually recursive functions make implementing state machines trivial and very easy to follow.
From your comments here, I get the feeling you are a tool maven (whereas I am a language maven).
Oh, and Lua kind of has a flag for a GIL—the main implementation has two C macos, lua_lock() and lua_unlock() that you can provide an implementation for and get a GIL (you’ll need to recompile Lua). On the downside, it makes Lua run as slow as Python.
[1] The only platform I know of where you can go one lower, is the PERQ, where you have access to the underlying microcode, and can even modify it.
[2] If the last thing a function does is return the result of a function call:
return call_this_function(foo)
that is a tail-call, and it can be optimized into a goto, not a call.
So I set up a nightly cron job to pull the code and generate the html docs with the fancy graphs etc.
Several years later someone asked me why the html doxygen page was broken…
…I looked at the logs and realised they had been broken for the last two years.
Nobody was looking at them, nobody cared.
Secondly I hate warm fuzzy architectural cloud diagrams. They’re useless. The happy little arrows don’t tell you if all things (whatever thing the arrows means) follow the arrows, or whether there are some going where the arrows aren’t pointing. (Hint: In every warm fuzzy architectural cloud diagram I have had a close look at has been basically plain wrong compared to the code on many points).
If I generate a diagram it’s exactly what the preprocessor / compiler /linker is seeing, if it’s architectural it’s because I have wired the build system to enforce the picture.
Of course in real systems pictures become so complex as to be useless.
One way of thinning it out is to allow the user to request a small finite list of modules of interest and the graph generator includes all and only edges from or two the modules of interest.
Thirdly, you’re looking at javascript. I’d love to be using a automagically parsable / rewritable language, but sadly I’m employed to wrangle c/c++.
Which has a preprocessor.
And we build many different deliverable flavours and variations from the same source.
Sigh. Preprocessors are evil.
Bottom line.
The class / function signatures, code, precondition asserts, and tests are the most concise, precise and up to date and accurate representation of the code. Anything else is fluff.
Build systems can be used to enforce architectural structure. ie. It’s less useful to have a warm fluffy cloud diagram that says dependencies go from here to there and much more useful to encode and enforce such architectural decisions in your build system.
I truly believe one day we will have machine readable and rewritable languages that machines can reason about. Once we have that your editor and compiler and documentation tool and refactoring tool will essentially be the same thing.
The ability of showing code blocks from multiple files in the same screen is something I wish my editor would be able to do. Have you ever thought about writing a plugin for existing editors such as VS code?
I like the idea of using different tools together, for example: I used to use Visual Studio and Vim at the same time to edit C# code. I don’t see Looset as an editor, but it could have functionalities to help finding a specific Code Block in any editor. Like an easy way to copy the file path and line number.
A protocol to tell editors to open/focus on a specific file+line sounds like a simple enough idea. Maybe piggybacking on LSP as a “service bus” for code tooling or something.
Looks neat and I’m excited to see how it progresses. The tagging system looks similar to that of code crumbs, and overall in a similar vein as source trail.
I think the big question is languages supported. It would be nice, with all the compile to JavaScript/CSS programs, to support code maps. If you invented a generic code map for all languages, that would be way better than anything else I can imagine.
Maybe have the three main backends at least? LLVM, JVM bytecode, and JavaScript?
I do wish programming languages were more about user interface and less about the underlying implementation. What if every Ruby performance improvement were also felt by LLVM and JavaScript? What if eliminating the GIL in Python helped JavaScript?
I am going to support any language, what I need to implement what you saw in the video is just to identify a Code Block with its name (what would be a function or method in most cases). To do that I’ll rely a lot on the fact we give one or more blank lines between function definitions and we ident its content.
I’ll create the different modules of Looset as independent scripts, so it would have a general simple analyzer written in Clojure, but someone else could implement some more advanced analyzer in another language.
I don’t understand your last paragraph there. How would eliminating the GIL (Global Interpreter Lock) in Python help JavaScript? They’re not only different languages, but different implementations, with different goals.
Lua does not have a GIL. Python does. Lua runs faster than Python, but because Lua lacks a GIL, you can’t share a Lua state between OS-level threads, whereas you can share a Python instance among threads. It’s a trade-off in the language design.
And how would focusing on user interfaces instead of implementation help a programming language?
I was just cherry-picking a few things that people had complaints about in languages. I do agree that they are trade-offs. I don’t think making a Lua syntax frontend for Python would be mistaken as Lua. I just think there is much more in common with languages than is different. Could there be a flag for a GIL in Lua to make it easier to write thread safe code? I’m trying to think about what is an actual feature of a language and what is an implementation detail. Can we work less on implementation details (like with languages that are front ends to other VMs, like JVM, LLVM, and BEAM)?
The bottom level of langauges, assembly [1], there is effectively, no runtime (or the runtime is the operating system if you are lucky). As you go up in languages, you start to have more and more of a runtime. Even C (generally speaking, one step up from assembly) has a runtime, if a minimal one. Lua has more of a runtime than C, because it supports garbage collection, closures and coroutines. Can Lua be compiled? Yes (LuaJIT). Does compiled Lua still require a runtime? Yes, because of the garbage collection, closures and coroutines. Can you do those in C? Yes, but … (and it’s a big but) it won’t be recognizable as C, or be so painful to use that no one will use it, or so full of caveats that it’s difficult to use correctly.
Can you use the LLVM backend for Lua? Yes, only because Lua is written in C, and C is one of the frontends to LLVM. Can you use the JVM backend? I guess if there’s a C frontend for the JVM, but then you end up with two garbage collectors—the one in Lua and the one in the JVM. It probably won’t hurt, but it’s a waste of space to have two. I suppose you could remove the Lua specific GC if the backend is the JVM, but the Lua GC is generational (5.4, previous were more mark-n-sweep I think), I don’t know what type the JVM implements but different GCs have different performance and issues (reference has problems with circular references; mark-n-sweep don’t but impose some latency).
There are also implementation details that leak through. Lua supports tail-call-optimizations [2] and Python does not. This “implementation detail” can make or break certain approaches to problems. For one thing, it can make a recursive function (or mutually recursive functions) consume no stack space if supported. Python, or rather Guido van Rossum, absolutely refused to implement tail-call optimizations because it “will break stack traces”. But using tail-call optimizations with mutually recursive functions make implementing state machines trivial and very easy to follow.
From your comments here, I get the feeling you are a tool maven (whereas I am a language maven).
Oh, and Lua kind of has a flag for a GIL—the main implementation has two C macos,
lua_lock()
andlua_unlock()
that you can provide an implementation for and get a GIL (you’ll need to recompile Lua). On the downside, it makes Lua run as slow as Python.[1] The only platform I know of where you can go one lower, is the PERQ, where you have access to the underlying microcode, and can even modify it.
[2] If the last thing a function does is return the result of a function call:
that is a tail-call, and it can be optimized into a goto, not a call.
(It applies to this post because it would, to me, allow more tools like this to exist and be easier to implement.)
Sorry I didn’t comment earlier… been under a bit of pressure.
First off… a war story.
The project had a coding standard and comment templates and used doxygen…. https://www.doxygen.nl/index.html
So I set up a nightly cron job to pull the code and generate the html docs with the fancy graphs etc.
Several years later someone asked me why the html doxygen page was broken…
…I looked at the logs and realised they had been broken for the last two years.
Nobody was looking at them, nobody cared.
Secondly I hate warm fuzzy architectural cloud diagrams. They’re useless. The happy little arrows don’t tell you if all things (whatever thing the arrows means) follow the arrows, or whether there are some going where the arrows aren’t pointing. (Hint: In every warm fuzzy architectural cloud diagram I have had a close look at has been basically plain wrong compared to the code on many points).
If I generate a diagram it’s exactly what the preprocessor / compiler /linker is seeing, if it’s architectural it’s because I have wired the build system to enforce the picture.
Of course in real systems pictures become so complex as to be useless.
One way of thinning it out is to allow the user to request a small finite list of modules of interest and the graph generator includes all and only edges from or two the modules of interest.
Thirdly, you’re looking at javascript. I’d love to be using a automagically parsable / rewritable language, but sadly I’m employed to wrangle c/c++.
Which has a preprocessor.
And we build many different deliverable flavours and variations from the same source.
Sigh. Preprocessors are evil.
Bottom line.
I really like the idea of Looset code.
The ability of showing code blocks from multiple files in the same screen is something I wish my editor would be able to do. Have you ever thought about writing a plugin for existing editors such as VS code?
I like the idea of using different tools together, for example: I used to use Visual Studio and Vim at the same time to edit C# code. I don’t see Looset as an editor, but it could have functionalities to help finding a specific Code Block in any editor. Like an easy way to copy the file path and line number.
A protocol to tell editors to open/focus on a specific file+line sounds like a simple enough idea. Maybe piggybacking on LSP as a “service bus” for code tooling or something.
I thought that wouldn’t be that simple, but as pyj mentioned, source trail does that and seems pretty useful.
Looks neat and I’m excited to see how it progresses. The tagging system looks similar to that of code crumbs, and overall in a similar vein as source trail.
They are the closest projects I’ve seen so far from what I have thought. Have you used them? Do you have some pros and cons?
It looks wicked fast, which is an incredibly important trait in a tool, and one that most tools fail miserably on.
Now you can find more information about the project in https://jponline.github.io/looset-landing/