Medium Blog: Creating a new programming language model with AI.

This is the additional content of a Medium blog post, use this link to read the main content.

Charactristics of different language models

1. Python

  • Easy to Read and Write: Python’s syntax is clean, readable, and intuitive, making it beginner-friendly.
  • Huge Standard Library and Ecosystem: Rich library support for web development (Django, Flask), data science (NumPy, Pandas, SciPy), machine learning (TensorFlow, PyTorch), and more.
  • Cross-Platform: Runs on various operating systems without significant modification.
  • Rapid Prototyping: Great for quickly building proofs of concept and small- to large-scale projects.

2. JavaScript

  • Ubiquitous on the Web: The de facto language for client-side web development; supported by all modern browsers.
  • Event-Driven and Asynchronous: Suited for interactive user interfaces and real-time applications.
  • Rich Ecosystem of Frameworks: Libraries such as React, Vue, Angular for front-end development; Node.js for back-end development.
  • Vast Package Repository (npm): Thousands of open-source packages for nearly any use case.

3. Java

  • Object-Oriented: Supports concepts like inheritance, encapsulation, and polymorphism, making it suitable for large-scale applications.
  • Platform Independence: The “write once, run anywhere” philosophy via the Java Virtual Machine (JVM).
  • Mature Ecosystem: Extensive libraries (Spring, Hibernate) and enterprise tooling.
  • Strong Community and Corporate Support: Widely used in Android development and large enterprise systems.

4. C

  • Low-Level Control: Offers direct manipulation of memory, making it powerful for system-level programming.
  • Speed and Efficiency: Ideal for performance-critical applications (operating systems, embedded systems).
  • Portability: C compilers exist for almost every hardware platform.
  • Small Language Core: Though it can be challenging for beginners, it forms the basis of many higher-level languages.

5. C++

  • Object-Oriented, but Also Procedural: C++ builds on C by adding object-oriented features.
  • High Performance: Used in industries like gaming, finance, and high-frequency trading where speed is crucial.
  • Large Standard Library (STL): Offers data structures and algorithms that are highly optimized.
  • Low-Level Control: Similar to C, allows intricate handling of memory and hardware resources.

6. C#

  • Microsoft Ecosystem: Integrates seamlessly with .NET platform, making it popular for Windows, server-side, and enterprise solutions.
  • Modern Language Features: Garbage collection, LINQ, async/await, and more to ease development.
  • Unity Game Engine: A top choice for game development.
  • Strong Type System: Balances performance and ease of development.

7. PHP

  • Web-Focused: Built for server-side scripting and powers a significant portion of modern websites (e.g., WordPress).
  • Easy Deployment: Widely supported by shared hosting providers and straightforward to set up.
  • Large Community: Many resources, frameworks (Laravel, Symfony), and CMS platforms (WordPress, Drupal).
  • Continual Evolution: Newer versions significantly improve performance and modern language features.

8. Ruby

  • Focus on Developer Happiness: Human-friendly syntax that’s designed to be expressive and enjoyable to write.
  • Rails Framework: Ruby on Rails popularized rapid web application development with convention-over-configuration principles.
  • Dynamic and Flexible: Metaprogramming capabilities allow easy extensions and library usage.
  • Vibrant Community: Strong open-source adoption and a plethora of gems (libraries).

9. Swift

  • Apple Ecosystem: Primarily used for iOS, macOS, watchOS, and tvOS development.
  • Modern Syntax: Combines safety (optionals, strong typing) with performance comparable to C-based languages.
  • Interoperability: Can work alongside existing Objective-C codebases.
  • Open Source: Although driven by Apple, it’s open source, allowing use on Linux as well.

10. Kotlin

  • JVM-Based: Interoperable with Java, making migration or integration easy.
  • Modern, Concise Syntax: Reduced boilerplate compared to Java.
  • Official Language for Android Development: Backed by Google, used in modern Android apps.
  • Null Safety: Minimizes common programming errors like NullPointerExceptions.

11. Go (Golang)

  • Concurrency Built-In: Goroutines and channels make concurrent programming simpler.
  • Simplicity and Speed: Compiles quickly; produces efficient, statically linked binaries.
  • Garbage Collected: Simplifies memory management.
  • Backed by Google: Reliable for large-scale infrastructure (Docker, Kubernetes use Go).

12. Rust

  • Memory Safety Guarantees: Borrow checker prevents common bugs like null pointer dereferences and data races.
  • High Performance: Comparable to C/C++, suitable for system-level projects.
  • Growing Ecosystem: Popular for building safe and fast applications (e.g., web servers, CLI tools).
  • Modern Syntax and Tools: Strong tooling (Cargo package manager) and developer-friendly compiler messages.

13. TypeScript

  • Superset of JavaScript: Adds static typing while still being compatible with existing JavaScript code.
  • Type Safety: Helps catch errors early, improves maintainability in large projects.
  • Adopted by Big Frameworks: Angular is built with TypeScript, and it’s commonly used with React, Vue, Node.js.
  • Tooling and IDE Support: Better autocompletion, refactoring, and documentation in modern editors.
Programmer challenges to use each model

1. Python

  • Slower for CPU-Intensive Tasks: Python is slower compared to lower-level languages like C or C++.
  • The Global Interpreter Lock (GIL): Limits true parallelism in multi-threaded, CPU-bound tasks.
  • Dynamic Typing Pitfalls: Type mismatch errors only appear at runtime, making debugging harder.

2. JavaScript

  • Fragmented Ecosystem and Tooling: Rapidly changing libraries and frameworks can lead to “JavaScript fatigue.”
  • Browser Inconsistencies: Different browsers have historically implemented JavaScript features differently.
  • Asynchronous Complexity: Handling callbacks, promises, and async/await properly can be tricky.

3. Java

  • Verbose Syntax: Boilerplate code (getters, setters, etc.) and class-based structure can feel heavy compared to more concise languages.
  • Long Startup Times and Memory Usage: The JVM can have higher memory overhead, and startup can be slower than compiled languages like C++ or Rust.
  • Backward Compatibility and Legacy Code: Maintaining older codebases can mean dealing with large amounts of legacy infrastructure and libraries.

4. C

  • Manual Memory Management: Managing memory (malloc, free) and dealing with pointers can be error-prone, leading to memory leaks or segmentation faults.
  • Lack of Modern Abstractions: No built-in object orientation, generics, or advanced language features found in newer languages.
  • Debugging Complexity: Diagnosing pointer and buffer overflow errors can be challenging, especially in large codebases.

5. C++

  • Complex Language Features: Templates, multiple inheritance, operator overloading, and other advanced features add complexity.
  • Long Compile Times: Big C++ projects can have significant build times due to templates and header inclusion.
  • Manual Resource Management: Although smart pointers help, memory management issues can still occur.

6. C#

  • Platform/Framework Lock-In (Historically): Originally tied heavily to the Windows ecosystem; although .NET is now open source and cross-platform, many older projects are still Windows-centric.
  • Large Frameworks and Versions: The .NET environment has various versions and frameworks (Framework vs .NET Core vs .NET 5/6+), which can lead to confusion or compatibility issues.
  • Resource Requirements: Like Java, C# applications running on .NET can have higher memory footprints compared to native languages like C or C++.

7. PHP

  • Inconsistent Language Design: Historically, function naming and parameter orders can feel inconsistent (e.g., array_filter, array_map, etc.).
  • Performance and Security Concerns: Older versions of PHP were less efficient. Security best practices often weren’t followed in legacy code (e.g., outdated tutorials).
  • Reliance on Shared Hosting: A positive (easy deployment) can also be a negative when dealing with older or restricted hosting environments.

8. Ruby

  • Performance Constraints: Generally slower compared to compiled languages or even some other interpreted languages (like newer versions of Python with JITs).
  • Concurrency Model: Ruby’s “green threads” in MRI (CRuby) can limit true parallelism. Alternative implementations (JRuby) exist but are less common.
  • Evolving Versions and Smaller Ecosystem (Outside of Rails): Ruby is heavily associated with Rails; outside that framework, it’s less prevalent.

9. Swift

  • Evolving Language: Swift has had frequent and sometimes breaking changes, especially in its early years, leading to version compatibility issues.
  • Apple Ecosystem Lock-In: Primarily used for iOS and macOS; although it’s open source and can run on Linux, it’s still largely driven by Apple’s platform development.
  • Limited Cross-Platform Support: Outside of Apple platforms, Swift adoption is still comparatively small.

10. Kotlin

  • Ecosystem Not as Mature as Java (Yet): While Kotlin is fully interoperable with Java, some libraries and tools are still Java-centric, or have incomplete Kotlin DSLs.
  • Slower Compilation Times (Compared to Java): Kotlin’s more advanced features (like inline functions, lambdas) sometimes introduce extra compile-time overhead.
  • Learning Curve from Java: Though Kotlin is simpler in many respects, developers used to Java’s verbosity need time to adapt.

11. Go (Golang)

  • Minimalism Can Be Restrictive: Lack of generics (pre-Go 1.18) meant more repetitive code. Even with generics now, the design is intentionally simplified, which may feel limiting for some.
  • Error Handling Verbosity: Go relies heavily on explicit error checks (e.g., if err != nil) which can feel cumbersome.
  • Concurrency Pitfalls: Goroutines are easy to start but can be overlooked in terms of resource usage, leading to potential memory leaks if not managed properly.

12. Rust

  • Steep Learning Curve: The borrow checker and strict type system can be difficult for beginners or developers coming from garbage-collected languages.
  • Long Compilation Times: Rust’s compiler does extensive checks, which results in safer code but slower build times, especially for large projects.
  • Relatively Young Ecosystem: While growing quickly, Rust does not have the decades of libraries that languages like C/C++ or Java do, so certain domains may still have limited library support.

13. TypeScript

  • Configuration Complexity: Requires a build/compile step (tsconfig.json), which can be daunting for newcomers.
  • Definition Files for Third-Party JS Libraries: Even though DefinitelyTyped helps with type definitions, mismatched or incomplete typings can cause friction.
  • Advanced Type Features Are Complex: Generics, mapped types, and advanced type utilities can become very complicated, making type errors difficult to debug.
The roadmap to create a new programming language

1. Define Your Core Philosophy and Goals

Identify the Problems You Want to Solve

  • What shortcomings in current languages do you want to address?
  • Common challenges might include:
    • Memory safety without too much complexity (Rust vs. C++).
    • Clear, minimal syntax (Go’s simplicity vs. complex, highly flexible languages).
    • Ease of concurrency (Go’s goroutines, Erlang/Elixir’s actor model).
    • Better tooling and package management from the start.

Decide on Your Main Use Cases

  • Will this language be for systems programming, web development, scripting, data science, or general-purpose use?
  • Defining a domain helps keep your design focused.

2. Shape the Language Design

Syntax Choices

  • Will it be curly-brace style (like C, Java, Go)?
  • Indentation-based (like Python)?
  • Expression-oriented vs. statement-oriented?
  • Balancing readability, familiarity, and innovation is key.

Type System

  • Static vs. Dynamic Typing: Static typing can catch errors at compile time (like TypeScript, Rust), while dynamic typing allows rapid prototyping (like Python, Ruby).
  • Type Inference: Many modern languages (e.g., Kotlin, Rust) use type inference to reduce boilerplate.
  • Null Safety: Minimizing or eliminating null references with language-level features (like Kotlin’s `?` or Rust’s `Option`).

Memory Management

  • Manual (like C/C++), Garbage Collection (like Java/C#), Reference Counting (like Swift/Objective-C), or a Hybrid approach?
  • If you want high performance and safety, consider borrowing ideas from Rust’s ownership model.

Concurrency Model

  • Threads and Locks (traditional), Channels/Goroutines (Go), Actors (Erlang/Elixir), or Async/Await (JavaScript, .NET).
  • Choose a model that fits your core domain.

Error Handling

  • Exceptions (like Java, Python).
  • Result Types (like Rust’s Result, Go’s error returns).
  • Or a hybrid approach.

Standard Library Scope

  • Decide how “batteries-included” the language should be.
  • Python includes a huge standard library, while Go is minimalist but includes robust concurrency features.
  • A large standard library can bootstrap adoption, but also requires significant maintenance.

3. Build an Initial Prototype and Compiler/Interpreter

Implement a Minimal Subset

  • Start with the core syntax, a basic type system, and minimal standard libraries.
  • Prove your language concept works before adding more features.

Choose a Strategy: Compiler or Interpreter

  • A compiler can generate machine code or target a known VM (e.g., LLVM IR, JVM, .NET CLR).
  • An interpreter can be easier to get off the ground but may need a just-in-time (JIT) compiler or optimizations later for performance.

Leverage Existing Toolchains

  • Using LLVM, for example, can greatly simplify the backend development.
  • Tapping into existing ecosystems (like the JVM, .NET) can give your language immediate cross-platform support and libraries.

4. Create First-Class Tooling and Package Management

Package Manager and Build Tool

  • Look at Cargo (Rust), npm (JavaScript), pip (Python) for inspiration.
  • Automatic dependency resolution, versioning, and reproducible builds are crucial for developer adoption.

Formatting and Linting

  • Emulate Go’s go fmt, Rust’s rustfmt, or Prettier for JavaScript to enforce consistent code style.
  • Provide official or community-driven linters to encourage best practices.

IDE/Editor Integration

  • Language Server Protocol (LSP) integration ensures features like autocompletion, code navigation, and refactoring in popular editors (VSCode, IntelliJ, etc.).

Testing Framework

  • Offer a built-in testing framework or make it easy to develop and use third-party libraries.
  • Emphasize simplicity (like Go’s builtin testing package) or flexibility (like Python’s unittest/pytest ecosystem).

5. Gather Feedback Early (Community Building)

Open Source Your Language

  • Open collaboration encourages contributions and fosters a user community.
  • Transparency helps developers trust the direction of your project.

Early Adopters and Beta Testers

  • Identify teams or individuals willing to try your language in real-world scenarios.
  • Gather feedback on what’s working, what’s confusing, and what’s missing.

Documentation and Tutorials

  • Thorough, friendly documentation lowers the barrier to entry.
  • Clear examples, quick-start guides, and “getting started” tutorials help build adoption.

6. Iterate, Polish, and Stabilize

Refine the Language Specification

  • Lock down the core syntax and semantics to prevent instability.
  • Use a clear versioning strategy (e.g., semver or language epochs like Rust) to handle breaking changes.

Establish a Roadmap

  • Identify which features will be experimental, which are stable, and what is on the horizon.
  • Communicate clearly with the community about priorities and timelines.

Focus on Developer Experience (DX)

  • Errors and warnings from the compiler/interpreter should be clear and actionable (Rust’s compiler messages are often praised for this).
  • Invest in a robust standard library or strong guidelines for third-party library authors.

Performance and Benchmarking

  • Continuously optimize common patterns.
  • Compare your language’s performance and memory usage to other solutions in your target domain.
  • Provide official benchmarks to highlight improvements over time.

7. Grow the Ecosystem

Community-Driven Packages

  • Encourage third-party package development for popular use cases.
  • Offer incentives (like official recognition or easy discoverability) for quality libraries.

Real-World Adoption Stories

  • Showcase companies or open-source projects using your language in production.
  • Success stories inspire others to adopt and trust the language.

Conferences and Meetups

  • Host or sponsor events, talks, and workshops to build user engagement.
  • Share best practices, case studies, and future goals with the community.
The suggested language and the path forward

1. Is It Even Possible?

Short answer: Yes, it’s possible in principle, but there are trade-offs:

  • Natural Language Parsing Is Hard: Human language is ambiguous. For example:
    Sort the list and print each item
    Does the user want ascending or descending order? Should duplicates be removed?
  • Context and Intent Understanding: The compiler or interpreter would need a robust way to handle incomplete or ambiguous commands. Traditional compilers expect precise syntax. A “prompt-like” language might rely on advanced parsing (potentially AI-based or rule-based) to disambiguate intent.
  • Simplicity vs. Power: A super-simple syntax might limit how complex a program can get. Once you need more advanced logic (e.g., concurrency, database connections, or error handling), you risk drifting away from “natural” statements and into “programming constructs.”

However, we already see partial successes of this concept with domain-specific languages (DSLs) and “low-code” or “no-code” tools. These frameworks let users configure business logic with minimal syntax. So, in a sense, it’s not only possible but already happening in certain niches—just not usually labeled as a general-purpose “programming language.”

2. Key Considerations for a “Prompt-Like” Language

Syntax vs. Natural Language

  • Minimal, English-like Syntax: You might define statements such as:
    read file "data.csv" into dataset
    				sort dataset by column "Name"
    				print dataset
  • Grammar and Parsing: You’d need a carefully designed grammar to interpret these lines. This grammar might be more flexible than typical languages, but still needs structure:
    • Verb → Noun → Optional parameters.
    • For instance: read [resource] ["identifier"] [into variable].
  • Disambiguation Mechanisms: When ambiguous, the parser may:
    • Prompt the user for clarification, or
    • Use a “best guess” approach (e.g., default to ascending order on sort).

Error Handling and Feedback

  • Compiler Warnings in Plain English: If the compiler can’t parse a statement or sees a logical error, it might respond with something like:
    I see you tried to print a dataset called ‘datset’. Did you mean ‘dataset’?
  • Interactive Shell vs. Static Compiler: An interactive REPL or shell might better serve a prompt-like language because it can ask clarifying questions in real-time.

Performance and Resource Usage

  • Simplicity in Implementation: A language that uses a straightforward AST (Abstract Syntax Tree) parsing approach can be efficient. You don’t necessarily need a huge runtime or advanced JIT compiler.
  • Limit the Scope of the Language: Avoid implementing complex features like concurrency, heavy libraries, or sophisticated reflection if you aim to minimize resource usage. A smaller runtime footprint means less overhead.

Potential Use of AI

  • Optional AI-Driven Parsing: A large language model (LLM) or rule-based NLP engine could interpret ambiguous statements. But this might introduce heavier resource usage and dependence on an external service (unless you use a very optimized on-device model).
  • Offline, Lean Implementation: Alternatively, a deterministic, rule-based parser can remain lightweight, but you lose some of the “magical” intelligence AI can provide.

3. Conceptual Example

Let’s imagine you define a file named hello.world that contains:

say "Hello, World!"
				ask "What is your name?" and store answer in username
				say "Nice to meet you, {username}!"

How does the language handle this?

  • Lexical Analysis: It identifies tokens like say, ask, store, and strings.
  • Parsing: It matches statements to grammar rules. For example:
    • say "<message>"
    • ask "<prompt>" and store answer in <variable>
  • Execution:
    • say prints the string to stdout.
    • ask displays a prompt, reads input, assigns it to username.
    • The second say uses interpolation to print the user’s name.

This might look like a “prompt-based” DSL. It’s very close to natural language but still restricted to a set of known patterns.

4. How to Keep It Simple but Powerful

Limit the Language Scope

  • Focus on a narrow domain (e.g., file I/O, text manipulation, basic logic and conditionals). This ensures you don’t blow up complexity with thousands of features.

Provide Good Defaults

  • Whenever the user doesn’t specify details (like sort order), default to something reasonable (e.g., ascending, or lexicographical). This reduces the amount of syntax a user must learn.

Gradual Complexity

  • Let advanced users opt into more “programming-like” constructs (loops, functions, conditionals). Keep them in plain-English style but well-defined:
    for each item in item_list
    				   say "Item: {item}"
    				end

Interactive Documentation

  • Provide “built-in help” or a REPL that explains commands, like a mini-tutorial.
  • Example: Typing help say prints usage examples.

5. Potential Challenges

  • Ambiguity: Natural language often has multiple interpretations. You’ll need to systematically handle or reduce ambiguity (e.g., “sort the list by name ascending” vs. “sort the list by name, ascending or descending?”).
  • Scalability: As projects grow bigger, you may need modules, packages, or some method to structure code. Maintaining a “prompt-like” style could become unwieldy.
  • Performance Trade-Offs: If you rely on AI-based parsing, you might introduce large model dependencies or external APIs. A purely rule-based approach is simpler but might feel “less intelligent.”
  • Community Adoption: Any new language faces the challenge of building an ecosystem of libraries, documentation, and tooling. Without these, it’s hard to gain traction.

6. Path Forward: A Feasible Strategy

  • Draft a Small Grammar: Start with a few key verbs: read, write, ask, say, calculate, sort, etc. Let them combine with natural-sounding phrases: read file "data.csv" into dataset.
  • Implement a Lightweight Interpreter: A simple parser that translates each statement into internal actions. Keep it in memory with minimal data structures, ensuring it’s not resource-heavy.
  • Offer an Interactive REPL: Let users type commands one by one. Provide immediate feedback or error messages in plain English.
  • Gather User Feedback: See where users stumble or want more capabilities. Gradually refine or expand the grammar.
  • Expand as Needed, Keep the Core Simple: Possibly add modules for specialized tasks (e.g., HTTP requests, database queries), each with their own small set of natural commands.
ParleyScript is born

Meaning & Inspiration:

  • Parley means “to speak” or “to negotiate,” originating from French parler (“to talk”). It evokes the concept of a straightforward dialogue between the user and the computer.
  • This aligns well with the goal of letting users “just type their intentions” in a natural, prompt-like fashion.

Why It Fits Your Language:

  • Conversation-Style Coding: Emphasizes how the language feels more like having a conversation with the machine rather than coding in verbose syntax.
  • Simplicity: A short, memorable name that reflects the minimal, resource-light approach you want.
  • Approachable for Non-Programmers: Suggests an inviting atmosphere, where even those with limited programming experience can “talk” to the system to get things done.

Alternative Name Ideas:

  • Whisper: Subtle, lightweight connotation, implying minimal overhead and a gentle “whisper” of commands to the machine.
  • ChatScript: Emphasizes the chat-like interaction; straightforward and descriptive.
  • Promptly: Plays on the idea of writing prompts; suggests speed and directness.
  • Parlay: A variant spelling of Parley, still carries the idea of a conversation or negotiation, plus it can hint at “expanding” a simple action into something more powerful.

Bottom Line:

A name like Parley (or a variant) works well because it succinctly reflects the idea of talking to the computer in plain, near-natural language—precisely the kind of experience you’re aiming to build.

↑ Back to Top