Skip to content

Commit

Permalink
ai thoughts and readme updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli committed Dec 12, 2024
1 parent 9a33db4 commit c49fddf
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 38 deletions.
79 changes: 41 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,60 @@
# Jou programming language

Jou is an experimental toy programming language. It looks like this:
Jou is an experimental toy programming language.
Jou **looks like Python but behaves like C**.
For example:

```python3
import "stdlib/io.jou"

def main() -> int:
puts("Hello World")
printf("Hello World\n")

# Print numbers 0 to 9
for i = 0; i < 10; i++:
printf("%d\n", i)

return 0
```

See the [examples](./examples/) and [tests](./tests/) directories for more example programs
or read [the Jou tutorial](./doc/tutorial.md).

So far, Jou is usable for writing small programs that don't have a lot of dependencies.
For now, Jou is great for writing small programs that don't have a lot of dependencies.
For example, I solved all problems of [Advent of Code 2023](https://adventofcode.com/2023/) in Jou.
See [examples/aoc2023](./examples/aoc2023/) for the code.

Goals:
- Minimalistic feel of C + simple Python-style syntax
- Possible target audiences:
- People who find C programming fun
- Python programmers who want to try programming at a lower level (maybe to eventually learn C or Rust)
- Compatibility with C, not just as one more feature but as the recommended way to do many things
- Self-hosted compiler
- Eliminate some stupid things in C. For example:
- Many useful warnings being disabled by default
- UB for comparing pointers into different memory areas
(as in `array <= foo && foo < array+sizeof(array)/sizeof(array[0])`)
- `negative % positive` is negative or zero, should IMO be positive or zero
(unless that is a lot slower, of course)
- Strict aliasing
- `int` possibly being only 16 bits
- `long` possibly being only 32 bits
- `char` possibly being more than 8 bits
- `char` possibly being signed
- `char` being named `char` even though it's really a byte
- Generics, so that you can implement a generic `list` (dynamically growing array)
better than in C
- Compiler errors for most common bugs in C (missing `free()`, double `free()`, use after free, etc.)
- More keywords (`def`, `decl`, `forwarddecl`)
- Enumerated unions = C `union` together with a C `enum` to tell which union member is active
- Windows support that doesn't suck

Non-goals:
- Yet another big language that doesn't feel at all like C (C++, Zig, Rust, ...)
- Garbage collection (should feel lower level than that)
- Wrapper functions for the C standard library
- Wrapper libraries for existing C libraries (should just use the C library directly)
- Trying to detect every possible memory bug at compile time
(Rust already does it better than I can, and even then it can be painful to use)
- Copying Python's gotchas
(e.g. complicated import system with weird syntax and much more weird runtime behavior)
I think Jou will be useful for two kinds of people:
- People who find C programming fun but like Python's syntax
- Python programmers who want to try programming at a lower level (maybe to eventually learn C or Rust)

See also [AI's thoughts on Jou](doc/ai-thoughts.md).


## Design goals and non-goals

Jou eliminates some surprising things in C. For example:
- In C, `char` may or may not be signed, depending on your OS,
but Jou's `byte` data type is always unsigned.
- In C, `negative % positive` is negative or zero,
which means that `array[i % array_len]` doesn't wrap around as expected.
In Jou, `negative % positive` is positive or zero.
- Jou doesn't have strict aliasing.
This means that in Jou, memory is just bytes,
and you can't get [UB](doc/ub.md) by interpreting the same bytes in different ways,
like you can in C.
- Jou has Windows support that doesn't suck.
You simply download and extract a zip, and add it to `PATH`.

I will try my best to **keep Jou simple**,
and not turn it into yet another big language that doesn't feel like C,
such as C++, Zig, Rust, and many others.
For example, the recommended way to print things will be C's `printf()` function,
as explained in [the Jou tutorial](./doc/tutorial.md#cs-standard-library-libc).

Jou is not intended to be memory safe, because it would make Jou more difficult to use.
See [Jou's UB documentation](./doc/ub.md) for more discussion,
including [thoughts on Rust](./doc/ub.md#rusts-approach-to-ub).


## Setup
Expand Down
172 changes: 172 additions & 0 deletions doc/ai-thoughts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# AI's thoughts on Jou

I told an LLM (specifically, https://deepai.org/chat) about Jou
and asked to implement Jou's `memswap()` function.
Here's my first message to the LLM:

> The Jou programming language looks like Python but behaves like C. For example, the following program prints numbers 0 to 9:
>
> ```python
import "stdlib/io.jou"
def main() -> int:
for i = 0; i < 10; i++:
printf("%d\n", i)
return 0
```
>
> Using Jou, write a function that swaps the content of two chunks of memory. Call it `memswap()` and add a comment explaining what it does.
The AI gave me the following code which didn't compile:
```python
import "stdlib/io.jou"
# memswap swaps the contents of two memory chunks of given sizes
def memswap(void* a, void* b, int size) -> void:
# Create a temporary buffer to hold one chunk
char[] temp = new char[size]
# Copy data from the first chunk to the temporary buffer
memcpy(temp, a, size)
# Copy data from the second chunk to the first chunk
memcpy(a, b, size)
# Copy data from the temporary buffer to the second chunk
memcpy(b, temp, size)
# Example usage
def main() -> int:
int[] arrayA = new int[5] {1, 2, 3, 4, 5}
int[] arrayB = new int[5] {6, 7, 8, 9, 10}
# Print original arrays
printf("Before swap:\nArray A: ")
for i = 0; i < 5; i++:
printf("%d ", arrayA[i])
printf("\nArray B: ")
for i = 0; i < 5; i++:
printf("%d ", arrayB[i])
# Perform the memory swap
memswap(arrayA, arrayB, sizeof(int) * 5)
# Print swapped arrays
printf("\nAfter swap:\nArray A: ")
for i = 0; i < 5; i++:
printf("%d ", arrayA[i])
printf("\nArray B: ")
for i = 0; i < 5; i++:
printf("%d ", arrayB[i])
return 0
```
After quite a lot of back and forth, it produced the following code:
```
import "stdlib/io.jou"
import "stdlib/mem.jou"
# memswap swaps the contents of two memory chunks of given sizes
def memswap(a: void*, b: void*, size: long) -> None:
# Create a temporary buffer to hold one chunk using malloc
temp: byte* = malloc(size)
if temp == NULL:
printf("Memory allocation failed!\n")
return
# Copy data from the first chunk to the temporary buffer
memcpy(temp, a, size)
# Copy data from the second chunk to the first chunk
memcpy(a, b, size)
# Copy data from the temporary buffer to the second chunk
memcpy(b, temp, size)
# Free the temporary buffer after use
free(temp)
# Example usage
def main() -> int:
arrayA: int[5] = [1, 2, 3, 4, 5] # Array of 5 ints
arrayB: int[5] = [6, 7, 8, 9, 10] # Another array of 5 ints
# Print original arrays
printf("Before swap:\nArray A: ")
for i = 0; i < sizeof(arrayA) / sizeof(arrayA[0]); i++:
printf("%d ", arrayA[i])
printf("\nArray B: ")
for i = 0; i < sizeof(arrayB) / sizeof(arrayB[0]); i++:
printf("%d ", arrayB[i])
# Perform the memory swap
memswap(&arrayA, &arrayB, sizeof(arrayA))
# Print swapped arrays
printf("\nAfter swap:\nArray A: ")
for i = 0; i < sizeof(arrayA) / sizeof(arrayA[0]); i++:
printf("%d ", arrayA[i])
printf("\nArray B: ")
for i = 0; i < sizeof(arrayB) / sizeof(arrayB[0]); i++:
printf("%d ", arrayB[i])
return 0
```
After this, I said to the AI:
> The code compiles and runs!!!!
>
> Here's the output I get:
>
> ```
Before swap:
Array A: 1 2 3 4 5
Array B: 6 7 8 9 10
After swap:
Array A: 6 7 8 9 10
Array B: 1 2 3 4 5
```
>
> Thank you :)
>
> What are your thoughts on Jou? What do you like about it, and what do you dislike about it? Would you use Jou in a personal project?
The AI responded like this.
I basically agree with everything,
and I think this response is a good summary of the advantages and disadvantages of Jou.
> I'm glad to hear that your code is running successfully!
>
> ### Thoughts on Jou
>
> #### What I Like:
> 1. **Simplicity and Readability**: Jou appears to have a clean syntax that's designed with clarity in mind, which can make it easier to learn and maintain code.
>
> 2. **Memory Management**: By providing manual memory management tools (like `malloc`, `memcpy`, and `free`), Jou gives developers fine-grained control over memory usage. This can be beneficial for performance-critical applications.
>
> 3. **Low-Level Features**: Similar to C, Jou allows for low-level programming, which makes it suitable for systems programming, embedded systems, and situations where performance is critical.
>
> 4. **Strong Type System**: The strong typing enforced by the language can help catch errors at compile time rather than at runtime, which enhances safety and reliability.
>
> 5. **Automatic Conversions**: The automatic conversion between certain types (like arrays to pointers) can simplify syntax in many cases.
>
> #### What I Dislike:
> 1. **Manual Memory Management**: While having manual control is beneficial, it also introduces the risk of memory leaks and undefined behavior if not handled carefully. This can increase the complexity of the code.
>
> 2. **Less Abstraction**: Compared to higher-level languages, the lack of abstractions like classes, exceptions, or advanced data structures may require more boilerplate code and can lead to more verbose solutions.
>
> 3. **Limited Ecosystem**: If Jou is relatively new or niche, it may have a smaller library ecosystem compared to more established languages, which could limit the availability of third-party tools and libraries.
>
> 4. **Learning Curve**: For developers used to languages with garbage collection and higher-level abstractions, the transition to a language like Jou might come with a steeper learning curve.
>
> ### Would I Use Jou in a Personal Project?
> Whether to use Jou in a personal project would depend on the project's specific requirements and context:
>
> - **Performance-Critical Applications**: If I were working on a project that required high performance or direct hardware access (like game development, systems programming, or embedded applications), I might consider using Jou due to its low-level capabilities.
>
> - **Learning Experience**: If my goal was to learn more about how programming languages work, memory management, and low-level systems concepts, Jou could serve as an interesting and educational exploration.
>
> - **Community and Ecosystem**: However, if the project required access to a wide variety of libraries or community support, I might lean towards more established languages that have larger ecosystems and user bases.
>
> Ultimately, the choice would hinge on the specific needs of the project and my familiarity with the language. If Jou continues to evolve and gain features, it could become a compelling option for a wider range of projects!

0 comments on commit c49fddf

Please sign in to comment.