buzz-language / buzz

👨‍🚀 buzz, A small/lightweight statically typed scripting language
https://buzz-lang.dev
MIT License
1.15k stars 31 forks source link

Add support to `_` in number literals #185

Closed mcbattirola closed 9 months ago

mcbattirola commented 9 months ago

This PR adds support for _ in number literals (int and float) (https://github.com/buzz-language/buzz/issues/163).

The underscore must be between the digits, not at the beginning or end, like in Zig and Go.

Since Zig already has this feature, we don't have to ignore the _ character and can leverage Zig's std.fmt.parseInt/std.fmt.parseFloat.

On hex and binary literals, it works like this, _ after the b or x is not valid, mimicking Zig's behavior, so 0b_000 and 0x_fff are not valid:

test.buzz:28:16: [E78] Syntax error: '_' must be between digits
    26 ╭─   assert(0x0_0_F == 0x00F, message: "hex ok");
    27 │
    28 │    int testx1 = 0b_000;
       ┆                 ╭─
       ┆                 ╰─ '_' must be between digits
    29 │    int testx2 = 0x_fff;
    30 ╰─   |int testx2 = 0x0F_;

I've added some simple test case in tests/001-basic-types.buzz. Please let me know if I should add more extensive tests.

This file is also compiling and running as expected:

import "std";

fun main([str] args) > void {
  int a = 9_9_9;
  int b = 1;
  int c = 1;

  int d = 0;

  float f = 1.0_0;
  float g = 1_0.0_0;

  assert(a + b == 1_000, message: "Sum OK");

  assert(1200.0_01 == 1_200.001, message: "Float sum OK");

  assert(1_0 == 10, message: "1_0 == 10 OK");

  assert(1_0.9 == 10.9, message: "1_0.9 == 10.9 OK");

  assert(0b0_0_1 == 0b001, message: "binary OK");

  assert(0x0_0_F == 0x00F, message: "hex ok");
}

I've also tried a modified version of the example on the website:

import "std";

| 👨‍🚀 buzz is a simple unambiguous scripting language
object Person {
    str name,
    int age = 1_8,

    fun growUp() > int {
        this.age = this.age + 1;

        return this.age;
    }
}

fun main([str] args) > void {
    Person me = Person{
        name = "Giann",
        age = 3_6,
    };

    print("Hello I'm {me.name} and I'm {me.age}.");
    me.growUp();
    print("Hello I'm {me.name} and now I'm {me.age}.");
}

It prints the expected:

Hello I'm Giann and I'm 36.
Hello I'm Giann and now I'm 37.

Please let me know if I'm missing something or should do something differently. I'd be happy to update this PR if requested.

Closes https://github.com/buzz-language/buzz/issues/163

mcbattirola commented 9 months ago

Thanks @giann, I've fixed the trailing _ and squashed the commits.

I've also implemented _ in binary and hex literals, as it felt wrong to allow _ in base 10 literals and not on hex/bin. Please let me know if you'd prefer those to be in a separate PR.

giann commented 9 months ago

Thanks!