Skip to content

Releases: jinko-core/jinko

v0.3.0-jinx7

26 Aug 13:25
75c6f9e
Compare
Choose a tag to compare
v0.3.0-jinx7 Pre-release
Pre-release

What's Changed

Full Changelog: v0.3.0-jinx6...v0.3.0-jinx7

v0.3.0-jinx6

26 Aug 12:46
3a0e4e0
Compare
Choose a tag to compare
v0.3.0-jinx6 Pre-release
Pre-release

What's Changed

Full Changelog: v0.3.0-jinx5...v0.3.0-jinx6

v0.3.0-jinx5

26 Aug 10:26
c67f3ed
Compare
Choose a tag to compare
v0.3.0-jinx5 Pre-release
Pre-release

What's Changed

Full Changelog: v0.3.0-jinx4...v0.3.0-jinx5

This release concerns the following target(s):

x86_64-unknown-linux

v0.3.0-jinx4

16 Jan 22:54
d15db19
Compare
Choose a tag to compare
v0.3.0-jinx4 Pre-release
Pre-release

Developer changelog

This is quite a small release as the code inclusion bug was really nasty... and prevented any possible development using jinko. A bunch of other bugs regarding generics have been fixed.

Multiple instructions such as VarAssign and FieldAssign did not expand generics properly. This has been fixed in the PR aiming for generic method calls to resolve correctly.

Previously, non-generic types were getting generically-mapped during the expansion pass. This meant that code like this:

type Something;
func takes_generic_and_some[T](one: T, two: Something) {}

would error out for not mapping the generic type Something properly.

Typechecking had broken test functions by forbidding the user to declare a test with the same name as an existing function. This is now fixed. Test functions are also now typechecked properly, which wasn't the case before.

You are no longer allowed to perform generic function calls if the function does not contain generics.

func no_gen(a: int, b: string) -> float {
    15.4
}

no_gen[int, string, bool](15, true); // Error

fmt_int has been reimplemented completely in jinko! There is a small performance hit, and the implementation is extremely ugly due to a weird recursion argument mapping bug and the lack of switch cases/pattern matching.

The implementation was benchmarked against a similarly ugly python implementation, and a call to the previous version of fmt_int(), which is simply a wrapper around rust's Display<i64> implementation.

~/G/j/jinko (int-to-string|✚2…) $ hyperfine --warmup 10 'python python_impl.py' 'target/release/jinko jinko_impl.jk' 'target/release/jinko native_rust_fmt.jk'
Benchmark #1: python python_impl.py
  Time (mean ± σ):      20.5 ms ±   1.4 ms    [User: 16.9 ms, System: 3.9 ms]
  Range (min … max):    15.7 ms …  23.8 ms    113 runs

Benchmark #2: target/release/jinko jinko_impl.jk
  Time (mean ± σ):       6.1 ms ±   0.9 ms    [User: 4.7 ms, System: 2.0 ms]
  Range (min … max):     2.5 ms …   8.7 ms    258 runs

  Warning: Command took less than 5 ms to complete. Results might be inaccurate.

Benchmark #3: target/release/jinko native_rust_fmt.jk
  Time (mean ± σ):       2.4 ms ±   1.0 ms    [User: 2.7 ms, System: 1.1 ms]
  Range (min … max):     0.0 ms …   6.0 ms    543 runs

  Warning: Command took less than 5 ms to complete. Results might be inaccurate.

Summary
  'target/release/jinko native_rust_fmt.jk' ran
    2.51 ± 1.05 times faster than 'target/release/jinko jinko_impl.jk'
    8.40 ± 3.32 times faster than 'python python_impl.py'

A side-effect of these fixes is that we also accidentally gained the power to do generic type inference... But this behavior needs to be standardized and tested on its own:

ext func debug[T](instance: T); // builtin function

debug(15);
debug("s");

type Complex(real: int, imaginary: int);

debug(Complex(real: 15, imaginary: 12));

No need to call debug[int](15) anymore!

Language changelog

  • #474: You can now call generic methods properly
  • #472: Code Inclusion was fixed!

Full Changelog: v0.3.0-jinx3...v0.3.0-jinx4

v0.3.0-jinx3

29 Dec 14:20
2f6cea7
Compare
Choose a tag to compare
v0.3.0-jinx3 Pre-release
Pre-release

Developer changelog

Thanks to @tanguysegarra, we now have multiple different tags over on dockerhub. If you go over to the tags tab, you'll now find the latest tag which corresponds to the latest release (or pre-release like this one) and bleeding which is updated with the most recent version of the interpreter on the default branch.

@SanderJSA worked to improve the string formatting situation and create the needed instructions during the parsing phase instead of the execution phase. Before, each string would get parsed and expanded at runtime: This is no longer the case.

Thanks to this change, we also get all other phases of the context "for free": The nodes to expand are now typechecked like any other, can use generics, andw ill get optimized once that is in.

We can also update formatting delimiters ('{' and '}') if we desire to use them by themselves: For example,

> name = "jinko"
> println("hey {jinko}")
"hey jinko"
> println("hey \{jinko\}")
"hey {jinko}"

We also now have escaped characters such as \t or \n! Meaning that we can properly print newlines from the stdlib without necessarily relying on the println builtin function.

Thanks to his work, the string interpolation feature is now complete enough that I felt confident merging it. This will make tiny scripts easier to write, without relying on multiple calls to concat(). Thanks!

@n1tram1 started working on an online REPL for the language in order to showcase it. In order to do so, @Skallwar started work on getting the jinko crate to compile with a WASM target, as well as adding an eval() function to develop easy REPLs. This meant splitting the code using rust features, to avoid platform dependent interactions such as dynamic library loading or uses of stdin and stdout. The eval() function is also now available for very easy integration of the jinko language to rust code, as showcased in the simple-repl example.

Work on generics has started in the interpreter. The changes are massive and extremely complex. I decided to focus on generic functions instead of generic types, as they are more complex but easier to test. The implementation still feels extremely fragile, and should not be relied on. The pipeline is as follows:

 ___________________
|                   |
|  TypeChecking 1   |
|___________________|
         |
         v
 ___________________
|                   |
| Generic expansion |
|___________________|
         |
         v
 ___________________
|                   |
| Generic resolving |
|___________________|
         |
         v
 ___________________
|                   |
|   TypeChecking 2  |
|___________________|

Splitting the typechecking pass in two allows for two things:

1/ Resolving generic calls and declarations after the arguments have been typechecked,
in order to generate proper versions of each declarations
2/ Declaring functions after they are being called. This is a feature of many modern
languages, and is still not present in jinko.

The type is now also cached in every instruction, to not reevaluate unecessary types during the second phase of the typechecking. This adds a lot of mutability, which I am quite sad about, but was necessary.

The generic typechecking works as follows:

If a function declaration contain generic types, it is not typehchecked during the first phase. A typical generic function looks something like this:

func call_method_on_generic[T](animal: T) -> string {
    animal.get_name()
}

type Dog;

func get_name(d: Dog) -> string {
    "doug"
}

rex = Dog;

call_method_on_generic(rex);

Since the type T does not exist, there is no point in checking that a get_name() method exists on it.

However, it makes sense for the interpreter to realize that we'd like to use the call_method_on_generic function with the Dog type, and to generate the following function declaration:

// The name comes from mangling the function name and the resolved generics. The user
// cannot directly call these mangled functions, or generate them either as they are not
// valid identifiers. But we are waaaaay paste the parsing phase when generating these, so
// the rules do not apply anymore :)
func call_method_on_generic+Dog(animal: Dog) -> string {
    animal.get_name()
}

This function can then get typechecked, and we can make sure that a get_name() method exists for the type Dog: This is just a regular function declaration!

The next step is to replace the call to call_method_on_generic(rex) with its newly generated counterpart: call_method_on_generic+Dog(rex)

The generics pass is a simple "visitor" comprised of two functions. Each instruction runs them on itself, before calling it on its subinstructions (i.e an if_else block needs to do generic expansion on its condition, its if block and its else block).

There are still a lot of issues with generic function calls and declarations, namely:

1/ No type inference. The above example would not work, as we cannot yet infer the correct call from the argument's type. This should not be hard to do, but is still unimplemented. You need to specify the generic types at all times for now, i.e: call_method_on_generic[Dog](rex)
2/ Parsing errors: We cannot call generic methods yet: rex.call_method_on_generic[Dog]() fails, while it shouldn't.

The issues haves the generic label and should not be too hard to solve. Focus should also be shifted to generic types, as they are the final step required to have a proper generic standard library and interesting types such as Maybe[T], Result[T, E] and so on.

Language changelog

  • String formatting for expressions between curly brackets
  • Character escaping
  • Generic function declarations and calls

Full Changelog: v0.3.0-jinx2...v0.3.0-jinx3

v0.3.0-jinx2

07 Dec 15:28
50b1cdd
Compare
Choose a tag to compare
v0.3.0-jinx2 Pre-release
Pre-release

What's Changed

These PRs add the parsing of generic types in function calls, type
instantiations, function declarations and type declarations. The syntax is the
following:

type SomeType[T](member: T);
type OtherType[T, U, V](member: T, member2: U, member3: V);
func takes_generic[T](arg: T) -> T { ... }

instance = SomeType[T](member: some_argument);
takes_generic[T](some_argument);

Thanks to @Skallwar, we now have LTO release builds which are much smaller than
previously. Thanks to you and @tanguysegarra 's efforts, this means we have a
1.9MB large docker image for jinko!

This enables the concept of empty-types or value-types: Types that can be instantiated,
but do not contain any fields. They provide a lot of type safety and can be optimized
and removed completely very easily. The syntax is the following:

type Empty; // declaration

e = Empty; // instantiation

They allow the Maybe type to be implemented in the following fashion:

type Nothing;
type Maybe[T](inner: T | Nothing);

They also allow the representation of enums once we have multi-types:

type Horse;
type Cat;
type Dog;

type Animal(Horse | Cat | Dog);

Thanks to @Skallwar, it is now much cleaner to execute expressions and cast
them as booleans for if-else conditions. Since we now have a typechecker, we
can completely avoid checking the type of variables also at execution. This should speed
up the interpreter and improve safety overall.

We now have a fantastic Dockerfile and docker image on hub.docker.com thanks to
@tanguysegarra. It is build automatically on each push to master and available as
jinko/jinko:latest.

We can now run tests declared in a file with the test keyword! Once we have a few more
abstractions, we will be able to write testsuites entirely in jinko. What is currently
missing is an assertion library, as well as a few abstractions.

Full Changelog: v0.3.0-jinx1...v0.3.0-jinx2

v0.3.0-jinx1

29 Nov 21:49
0b28031
Compare
Choose a tag to compare
v0.3.0-jinx1 Pre-release
Pre-release

What's Changed

New Contributors

Full Changelog: v0.2.0...v0.3.0-jinx1

v0.2.1

31 Oct 22:42
Compare
Choose a tag to compare
  • Fixed variable mutation bug #187

This release concerns the following target(s):

x86_64-unknown-linux

v0.2.0

26 Oct 08:16
1babd52
Compare
Choose a tag to compare

Major changes:

  • Add static typechecker
  • Add < and > operators in #321
  • Implement correct for loop behavior in #316
  • Add FFI
  • Add builtin functions

Minor changes:

  • Add args handling library in #314
  • stdlib/exit: Add exit() function in #318
  • Add Iter and Range in #280
  • Add install script to package standard library in #309
  • Load libraries from path in #310
  • ffi: Allow loading libraries without full path in #295
  • Add shell library abstraction in #294
  • Add link_with() builtin and start of FFI module

This release concerns the following target(s):

x86_64-unknown-linux

v0.2.0-jinx5

25 Oct 11:54
a8f488c
Compare
Choose a tag to compare
v0.2.0-jinx5 Pre-release
Pre-release

What's Changed

  • Add args handling library in #314
  • stdlib/exit: Add exit() function in #318
  • Add < and > operators in #321
  • Implement correct for loop behavior in #316
  • cargo: Bump version to 0.2.0-jinx5 in #324

Full Changelog: v0.2.1-jinx4...v0.2.0-jinx5