Stories
Slash Boxes
Comments

SoylentNews is people

Log In

Log In

Create Account  |  Retrieve Password


istartedi (123)

istartedi
(email not shown publicly)

Journal of istartedi (123)

The Fine Print: The following are owned by whoever posted them. We are not responsible for them in any way.
Saturday October 24, 20
07:34 AM
Code

I just got through watching this long but interesting video from just over six years ago, in which Johnathan Blow puts forth his ideas for the (then un-named) Jai programming language which is currently under development but not released to the public. There is a brief overview of the language available.

As someone interested in language design, I can't believe this has been out here this long and I haven't heard of it. He works in the domain of video games, but what he discusses has broad applications and many of the things he says should resonate with people who work in other areas.

Display Options Threshold/Breakthrough Reply to Article Mark All as Read Mark All as Unread
The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
(1)
  • (Score: 2) by Rich on Saturday October 24 2020, @12:12PM (5 children)

    by Rich (945) on Saturday October 24 2020, @12:12PM (#1068216) Journal

    I recently was debugging some Objective C code that had pointer ownership issues. I had to look at the binary representation and found an article explaining how auto-reference-counting works at low level. It uses not one, but two counters for an object, where the "weak" references are counted separately and can keep an object in undead state, while reading as nil if the "strong" references are gone. This is quite some runtime ov3rh3ad, but still less than the supposedly "zero ov3rh3ad" C++, which keeps a whole extra object just for counting shared_ptr. (leetspeek needed against douche filter. wtf?)

    I got carried away a bit and came across an article where the writer argued that references should be "weak" by default. This was a bit of an epiphany to me, because it could also mean that there might be just a single "strong" owner. Thought further, one might even do away with any runtime overhead at reading by just failing when trying to overwrite the owner with weak references left. This solves all issues with undefined memory states, and much more simple than in Rust (with its complex static checking and lifetime annotations), at the cost of the "weak" counter. Extra effort over C is that that no dangling pointers are allowed anymore (but that's bad practice anyway), and it's an imperfection that the logic has no cycle checking. This could be rationalized by pointing out that the halting problem on the code-flow side can't be solved either, it would eventually "just" cause a out-of-memory failure, rather than undefined states, and extra debugging tools might even check for cycles. Weak "counting" could also be done in different way, by various combinations of marking/sweeping, or even not at all in an unsafe model for eliminating all overhead).

    I note that Jai has exactly this concept of a simple single strong ownership, Although it doesn't mention anything on safeguarding the weak references. And I'd design in some runtime bindings for true shared objects (like anonymous text style runs), or catching non-memory resources on deallocations.

    • (Score: 2) by RamiK on Sunday October 25 2020, @10:37PM (4 children)

      by RamiK (1813) on Sunday October 25 2020, @10:37PM (#1068687)

      one might even do away with any runtime overhead at reading by just failing when trying to overwrite the owner

      1. Cache misses cost more cycles than checking two counters.

      2. Transferring ownership of an object is a hard IPC problem involving context switching, locking and cache misses.

      --
      compiling...
      • (Score: 2) by istartedi on Tuesday October 27 2020, @02:04AM (3 children)

        by istartedi (123) on Tuesday October 27 2020, @02:04AM (#1069154) Journal

        Now this, this is an interesting thread. It's carrying me in to areas I haven't even considered in my own language design, because at this stage I'm just happy that my reference counter works!

        --
        Appended to the end of comments you post. Max: 120 chars.
        • (Score: 2) by Rich on Tuesday October 27 2020, @10:04AM (2 children)

          by Rich (945) on Tuesday October 27 2020, @10:04AM (#1069230) Journal

          I haven't thought really in depth about it, but the considerations I see so far are:

          - Storing a new object into an existing owning pointer needs the no-weak-check and can be done thread-safe with atomic CAS (*)
          - Deleting, moving, or scope-ending owned objects are a variant of the above
          - Introspection is needed in a (recursive) "destructor" at least for the owning pointers.
          - Expression terms probably should auto-delete owned pointers returned from functions (for your string handling) after executing the term operation (vs. letting the functions gobble them up, so the functions work with weak pointers and references)

          - Assigning weak pointers need atomic counting, just outside of their lifecycle. This guarantees thread safety.
          - How weak pointers go out of scope might be debatable. There might be an auto-mechanism, with them being deleted first, or a "hard" stance on "NEVER let a weak pointer go out of scope" for visible control over them. Might be a bit too inconvenient.

          - References would be preferred for passing into functions. These are like weak pointers with an initial counting, no counting needed when they are passed on, at the cost that they cannot be assigned to anything outside the stack.

          - The compiler might eliminate a bit of the checking if it sees that it is safe in scope (primarily for initial assignments).
          - One could experiment with (most of?) the above logic in a bit of advanced C++ to get the practical "feel".

          (*) The atomic CAS might either do lifecycling on a second-write-overwrites basis (with extra checking), or trigger an abort (because it would be "sort-of-undefined"). There's a hazard of having a register loaded pointer being deleted by another thread, so for multi-thread safety it would probably be needed to crank out a reference (i.e. using the weak counter) while working with owned pointers.

          • (Score: 2) by Rich on Tuesday October 27 2020, @10:23AM (1 child)

            by Rich (945) on Tuesday October 27 2020, @10:23AM (#1069235) Journal

            D'oh. Just to point out how little I have thought about it - it just occurred to me: With the system, you CAN'T have cycles. For a cyclic data structure, you'd need to either use weak pointers, which would cause an abort if you'd try to leak it, or, with owning pointers, an iterator that holds the head and is used to close the cycle on the nil "next" pointer of the last object. Bidirectional linking is no problem, you'll just have to nil the next backlink before cutting the chain.

            • (Score: 2) by istartedi on Wednesday October 28 2020, @08:53PM

              by istartedi (123) on Wednesday October 28 2020, @08:53PM (#1070091) Journal

              Bread is made of dough. Software is made of D'oh!

              --
              Appended to the end of comments you post. Max: 120 chars.
  • (Score: 2) by Mojibake Tengu on Saturday October 24 2020, @07:37PM (2 children)

    by Mojibake Tengu (8598) on Saturday October 24 2020, @07:37PM (#1068306) Journal

    I consider "Arbitrary compile-time code execution" very dangerous.

    This clearly represent a topological hole in program logic (in categorial paradigm, a program is a proof of something (Curry-Howard) in some constructed logic, and the hole is observable as truly a hole in geometric representation of said logic), which could lead to host platform injection exploits very quickly even for originally safe projects.

    Historically, TeX author did similar design error with infamous write18 construct to shell escape.

    On the other side, I consider anonymous codeblocks and anonymous functions good.
    However, so-called polymorphic procedures are just macros/templates reinvented, badly. This contradicts author's intent not to have macros/templates.

    Defer (like that one i Go) is dangerous too, for it is an explicit side effect which may introduce nondeterminism, especially together with some kind of failure encountered.

    I appreciate language author's will to experiment though, this is how a craftsman should acquire his own experience, for fun and glory.

    --
    The edge of 太玄 cannot be defined, for it is beyond every aspect of design
    • (Score: 1) by istartedi on Saturday October 24 2020, @08:29PM

      by istartedi (123) on Saturday October 24 2020, @08:29PM (#1068325) Journal

      I consider "Arbitrary compile-time code execution" very dangerous.

      I think his compile-time execution is sand-boxed, ie, in a virtual machine not JIT or otherwise compiled. Even if it were though, how is it any more dangerous than having the source to the compiler on the machine? If my account is compromised, a good attacker is going to look for the source to the compiler and inject malware right there.

      Of course things can get out of hand. Just as a simple example, a compiler with arbitrary compile-time exe could go into an infinite loop, whereas the C pre-processor is most likely proven to terminate. You could always restrict function calls from the compiler, but when the language is capable of being scripted or compiled, it seems very inelegant to use anything *other* than the language itself for macros, conditional compilation, etc. This is what Lisps do, and they're not considered a security threat.

      If you download, compile, and run random code from the Internet you get what you deserve. I don't see restricting compile-time execution preventing this.

      --
      Appended to the end of comments you post. Max: 120 chars.
    • (Score: 0) by Anonymous Coward on Sunday October 25 2020, @09:44PM

      by Anonymous Coward on Sunday October 25 2020, @09:44PM (#1068670)

      I consider "Arbitrary compile-time code execution" very dangerous.

      Ignorance is well known to cause such opinions in people.
      A configure script, and a makefile, exist for the very reason of doing precisely that thing. Their code being in a different language is not any protection to anyone. One can inject something totally elephantine into the usual megabyte-sized autoconf excreta with no one the wiser, for who ever looks inside the ugly things at all?
      Alongside that, compile-time execution capabilities in a language, like Perl's BEGIN blocks, or Forth's natural behavior, are totally unimportant.

  • (Score: 0) by Anonymous Coward on Monday October 26 2020, @07:14PM (1 child)

    by Anonymous Coward on Monday October 26 2020, @07:14PM (#1069019)

    I thought a lot of what he said is thought-provoking. I also think some of the criticisms of Rust unrelated to Jonathan Blow's developer friction and learning curve criticisms are thought-provoking. If you haven't seen them already, it's worth a look at blog posts by by people like Drew Devault.

    That said, it feels like a lot of the simplicity and readability advantages of Jai would be lost with compile-time code execution. You could recreate macros and operator overloading and object-oriented-programming in Jai. You put your new syntax in Jai files, and then in another file you put code that runs at compile time and translates the new syntax in the other files into standard Jai syntax and compiles those. It's a terrible idea, but the point is that his compile-time code execution feature enables it. So if he ever releases Jai, eventually these kinds of macro-workaround and operator overloading and OOP will exist for Jai. If people start adopting them we'll reach territory where Jai is as complicated as Rust or C++.

    For other languages that try to improve upon C without becoming more complicated (no OOP, no macros, no garbage collection), there's also Zig and Vlang. Zig seems really close to Jai in a lot of ways. I haven't looked as closely at Vlang.

    • (Score: 1) by istartedi on Tuesday October 27 2020, @02:02AM

      by istartedi (123) on Tuesday October 27 2020, @02:02AM (#1069152) Journal

      I get what you're saying about how compile-time execution enables terrible ideas; but that falls in line with what he said in his talk about "letting good programmers do good things" (paraphrasing) and not letting what bad programmers might do constrain the language design.

      I hate to go here, but the best analogy I can come up with is that we don't blame the German language for Mein Kampf and a bunch of speeches. We blame the guy who wrote them.

      --
      Appended to the end of comments you post. Max: 120 chars.
(1)