Brand new RowScript · Issue #195 · rowscript/rowscript · GitHub
Skip to content

Brand new RowScript #195

Description

@anqur

I feel an urge to rewrite RowScript. If you stumble upon this issue, it should crack you up: Yes, there's still a great amount of flaws in current design (up to version v1.0.0-alpha.5). But now I'm feeling like a guru on making languages, let me refine it, please be patient.

Motivation: Scripting over Native

Software industries are now only workable upon dynamic/scripting languages, e.g., JavaScript, Python, Lua, Ruby, Julia, Matlab... In terms of systems languages, like C/C++, Java, Rust, Go and Zig, they mostly serve as the engines or components of some bigger realms.

  1. Dynamic/scripting languages are usually the first option for early problems.

For domains like UI, graphics, AI, microservices, games and scientific computing, we keep seeing people use them for fast-prototyping and flexible developer experience.

Nonetheless, further problems like performance tuning and hardware adoption would convince people to use systems languages. But we should notice that it's hard and even unnecessary to replace the existing components written in dynamic/scripting languages. Every language serves their own scopes, but sometimes multi-language project management can be hard.

(NB: Problems like writing language VMs, compilers and IDEs are not taken into account here, since designing such language is a different topic.)

  1. Native support for dynamic/scripting languages should be a first-class citizen.

It should not just be an AOT compiler for the program bytecodes. It should emit machine code directly. Run as an executable.

To sum up, RowScript emits JavaScript for scripting by default, and should be able to emit machine code for native support.

Native Support

I would try Cranelift for backend and MMTk for making a GC. I have no further comments on this topic for now, it just requires a whole bunch of groundwork.

You should be asking about concurrent programming. Yes, it can be just using libuv, it can be stackless coroutines, it can be something else. I would talk about it some day.

Split the number Type

For native support, number type is far from usable anymore. We split it into:

  • Integers: u8, u16, u32, u64, u128, i8, i16, i32, i64, i128.
  • Floating-point numbers: f16, f32, f64.

Consistent Syntax over Reusing Keywords

When I implemented the capabilities (#156) feature, I reused the throws, try and catch keywords for so-called familiarity, but apparently I failed to deliver the intention of the syntax. Users came up to me for complaints.

This time, forget about the "familiarity", we should use consistent and similar syntax.

Dependent Types

  1. Impose dependent types in the surface syntax by default.

Unleash the full power of dependent types! Because scripting is so natural with it. We banned it in the current version for that "people might not understand what they're doing". But this time I feel confident about this feature.

  1. comptime function.

Function marked with comptime can be run everywhere in compile-time.

  1. No internal dependent-type encodings.

I used so many encodings (e.g., Sigma types for function arguments) in the current codebase, it screwed up everything, from concrete syntax to even code generation. We should never use it again.

Arbitrary Control-flow Constructs

  1. Feel free to use any control flow.

Everyone just can't live without it.

  1. Use statements in AST.

In the current design, I used CPS-style AST for convenience, this was proven to be disappointing (e.g. I banned control-flow constructs in closures, that's stupid).

  1. comptime function could also have control-flow constructs.

Since we need native support, we have to translate the control-flow code into graph-based IRs for typechecking and code generation, so it's easy to write an abstract interpreter/partial evaluator to run any functions in compile-time.

Nominal over Structural Typing

  1. struct type.

We will still have our record-concatenation row polymorphism in the feature set, but it only comes up to solve subtyping problems for existing JavaScript constructs. struct is recommended in new application code.

A similar situation can be found in Python where @dataclass and TypedDict are both supported but the former is more widely used.

  1. Find the boundaries.

The first problem that comes to my mind is whether Option<T> should be nominal or structural. We need to find the boundaries, and even the balance. Let's make such decisions in the future.

And More...

  1. enum type and flexible pattern matching.

Pattern unification, I have to challenge this feature for the ultimate user experience.

  1. Tuple type.

It's proven to be highly useful, just don't miss this.

"Isn't It Just Another Dart?"

RowScript WILL NOT HAVE:

  • Bytecode
  • JIT bytecode-to-machine compilation
  • AOT bytecode-to-machine compilation

That says:

  1. No isolates are needed for concurrency.
    • We might have something like this to solve other problems, for instance we could write many Cgo-based libraries and linked them into one single C executable to have many Go runtimes simultaneously. Some weird problems might arise, but we shouldn't isolate the runtime for concurrency if we only have one.
  2. No subtyping-style dynamic typechecking.
    • We should have other approaches to object systems. But classic OOP/subtyping sounds quite overcomplicated for me.
    • We might also have inheritance, but it can be simple has-a inheritance for convenience. No complex subtyping cluttering.

It should just look like a compiled and managed language. No more magic inside.

New Slogan

A better JavaScript that types and compiles.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No fields configured for Task.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions