Kayne Ruse 002651f95d WIP, adjusting architecture, read more
The 'source' directory compiles, but the repl and tests are almost
untouched so far. There's no guarantee that the code in 'source' is
correct, so I'm branching this for a short time, until I'm confident the
whole project passes the CI again.

I'm adjusting the concepts of routines and bytecode to make them more
consistent, and tweaking the VM so it loads from an instance of
'Toy_Module'.

* 'Toy_ModuleBuilder' (formally 'Toy_Routine')

This is where the AST is compiled, producing a chunk of memory that can
be read by the VM. This will eventually operate on individual
user-defined functions as well.

* 'Toy_ModuleBundle' (formally 'Toy_Bytecode')

This collects one or more otherwise unrelated modules into one chunk of
memory, stored in sequence. It is also preprended with the version data for
Toy's reference implementation:

For each byte in the bytecode:

    0th: TOY_VERSION_MAJOR
    1st: TOY_VERSION_MINOR
    2nd: TOY_VERSION_PATCH
    3rd: (the number of modules in the bundle)
    4th and onwards: TOY_VERSION_BUILD

TOY_VERSION_BUILD has always been a null terminated C-string, but from
here on, it begins at the word-alignment, and continues until the first
word-alignment after the null terminator.

As for the 3rd byte listed, since having more than 256 modules in one
bundle seems unlikely, I'm storing the count here, as it was otherwise
unused. This is a bit janky, but it works for now.

* 'Toy_Module'

This new structure represents a single complete unit of operation, such
as a single source file, or a user-defined function. It is divided into
three main sections, with various sub-sections.

    HEADER (all members are unsigned ints):
        total module size in bytes
        jumps count
        param count
        data count
        subs count
        code addr
        jumps addr (if jumps count > 0)
        param addr (if param count > 0)
        data addr (if data count > 0)
        subs addr (if subs count > 0)
    BODY:
        <raw opcodes, etc.>
    DATA:
        jumps table
            uint array, pointing to addresses in 'data' or 'subs'
        param table
            uint array, pointing to addresses in 'data'
        data
            heterogeneous data, including strings
        subs
            an array of modules, using recursive logic

The reference implementation as a whole uses a lot of recursion, so this
makes sense.

The goal of this rework is so 'Toy_Module' can be added as a member of
'Toy_Value', as a simple and logical way to handle functions. I'll
probably use the union pattern, similarly to Toy_String, so functions
can be written in C and Toy, and used without needing to worry which is
which.
2025-01-29 10:21:33 +11:00
2025-01-14 12:45:11 +11:00
2024-10-19 15:58:17 +11:00
2024-12-07 07:43:28 +11:00
2025-01-29 10:16:55 +11:00
2024-05-19 03:50:57 +10:00

Toy v2.x

The Toy Programming Language is an imperative, bytecode-interpreted, embeddable scripting language. Rather than functioning independently, it serves as part of another program, the "host". This design allows for straightforward customization by both the host's developers and end users, achieved by exposing program logic through text files.

This repository holds the reference implementation for Toy version 2.x, written in C.

Nifty Features

  • Simple C-like/JS-like syntax
  • Intermediate AST representation
  • Strong, but optional type system
  • First-class functions and closures
  • Extensible with importable native code
  • Can re-direct output, error and assert failure messages
  • Open-Source under the Zlib license

Syntax

The following examples aren't fully functional yet, see Timetable.

//fizzbuzz example
for (var counter: int = 1; counter <= 100; i++) {
	var result: string = "";

	if (counter % 3 == 0) {
		result = result .. "fizz";
	}

	if (counter % 5 == 0) {
		result = result .. "buzz";
	}

	if (result != "") {
		print result;
	}
	else {
		print counter;
	}
}
//find the nth fibonacci number
fn fib(n: int) {
	if (n < 2) return n;
	return fib(n-1) + fib(n-2);
}

for (var i = 1; i <= 10; i++) {
	print i.toString() .. ":" .. fib(i).toString();
}
//closures!
fn makeCounter() {
	var count = 0;

	fn next() {
		return ++count;
	}

	return next;
}

var tally = makeCounter();

print tally(); //1
print tally(); //2
print tally(); //3

Timetable

Here's a rough goal for the upcoming milestones, at which time I'll review and revise my projections.

Feature Time Span Review Date
Arrays & Tables - 1st Jan
Control Flow 2 weeks 15th Jan
Functions 2 weeks 29th Jan
Functions 2 weeks 12th Feb
Dot Operator & Slices 2 weeks 26th Feb
Standard Libraries 2 weeks 12th Mar
Native Libraries 2 weeks 26th Mar
Documentation - -

Building

Supported platforms are: linux-latest, windows-latest, macos-latest, using GitHub's standard runners.

To build the shared library, run make source.
To build the shared library and repl, run make repl.
To build and run the test suites, run make tests (make tests-gdb and make tests-valgrind options are also available).

Tools

Coming Soon - I want the features mostly working first.

Documentation

The WIP documentation can be found here: https://v2.toylang.com/

License

This source code is covered by the Zlib license (see LICENSE.md).

Contributors and Special Thanks

For a guide on how you can contribute, see CONTRIBUTING.md.

@Gipson62 - v1 docs spell checking @8051Enthusiast - fixAlignment() trick
@hiperiondev - v1 Disassembler, v1 porting support and feedback
@add00 - v1 Library support
@gruelingpine185 - Unofficial v1 MacOS support
@solar-mist - v1 Minor bugfixes
Various Anons - Feedback
@munificent - For writing the book that sparked my interest in langdev

Patreon Supporters

  • Seth A. Robinson
Languages
C 97.7%
Makefile 2.2%