#how do you all get around not being able to switch on strings?

1 messages · Page 1 of 1 (latest)

gaunt sigil
#

Zig compiler is informing me that I'm not allowed to.

warm rampart
#

For simple stuff where performance is not critical, e.g. checking the values of command line flags at program start:

if (std.mem.eql(u8, arg, "--verbose")) ...

Otherwise you can use a std.HashMap when the set of keys is dynamically determined, or a std.ComptimeStringMap when the set of keys is fixed and known at comptime.

shy rock
#

Try Out InK's Patented Solution™️:

const str: []const u8 = ....;
const Case = enum {
    fizz,
    buzz,
    @"fizz buzz",
};
const case = std.meta.stringToEnum(Case, str) orelse {
    // handle non-matching case
};
switch (case) {
    .fizz => {},
    .buzz => {},
    .@"fizz buzz" => {},
}
#

for enums with less than 100 members or something, it uses std.ComptimeStringMap under the hood

warm rampart
#

I would like to purchase a license to your solution, I'll have my people call your people

shy rock
#

We'll get back to you in 1.25 business days

gaunt sigil
#

lol thanks yall

#

@shy rock how are you getting syntax highlighting? I thought there was no zig support

shy rock
#

there isn't. I just arbitrarily add a language tag that looks good for the particular code lol

#

that one's typescript (ts)

gaunt sigil
#

lol

#

also is there a name for @"" syntax? I want to read up on it a bit

warm rampart
#

Or "escaped identifiers"

gaunt sigil
#

how do you read about how they work?

warm rampart
#

There's a section there ^

shy rock
#

can also use unicode codepoint literals in them, e.g. @"\u{77}"

#

certainly makes for some funky stuff

#

also allows you to use keywords as identifiers

#

@"return"

#

which, generally is the main use case for them

dapper meadow
#

@shy rock you got a version of that enum solution for std.mem.startsWith?

shy rock
#

nay, not quite. That would be quite a bit more complex I imagine

warm rampart
dapper meadow
#

Yeah 😭

gaunt sigil
#

you also can't do a for loop over const character data?

#
fn parser(input: [*:0]const u8) TOKEN {
  std.debug.print("THE INPUT{s}", .{input});
  var tokens: []Token = undefined;
  comptime var cur_tok_start = 0;
  comptime var token_depth = 0;
  for (input) |char| {
    _ = char;
    const case = std.meta.stringToEnum(Case, input[cur_tok_start..(cur_tok_start + 1)]);
    // token = token ++ char;
    switch (case) {
      .function => {
        tokens = tokens ++ Token {
          .kind = TOKEN.FUNCTION,
          .value = "function"
        };
        cur_tok_start += token_depth;
        token_depth = 0;
      },
      else => {
        token_depth += 1;
      }
    }
  }
  return tokens;
}```
shy rock
#

not if it doesn't have a length

#

[*:0]const u8 is a plain pointer, which has no length encoded into the type, nor does it carry attached any runtime length information like a slice would

#

it just happens to be annotated as having a 0 sentinel

gaunt sigil
#

we could get it's length

#

we're comptime

#
pub fn main() !void {
  comptime {

    const javascript = @embedFile("./test.js");
    const tokens = parser(javascript);
    std.debug.print("THE TOKENS {}", .{tokens});
  }
}```
shy rock
#

if you want, you could transform this into a slice using a function like std.mem.sliceTo or std.mem.span.
Also, no, this isn't being done at comptime, not in the function

#

there is a distinction between a function which can be called at comptime, and a function which is comptime-only

#

if you wanted that to be comptime, the parameter would have to be comptime input: [*:0]const u8

gaunt sigil
#

I'd prefer for this function to be comptime only

shy rock
#

why?

gaunt sigil
#

I'm looking at targeting zig from js

shy rock
#

if you make it comptime-only, input can never be from any external data

gaunt sigil
#

right

#

there's an input js file

#

and i want to generate zig that does the same thing as the js

#

so we have everything

shy rock
#

I would still recommend against making it comptime-only unless you actually need to

#

at any rate, to get back to the main question

#

just make your parameter be input: []const u8, or input: [:0]const u8

#

Oh, I do notice now that it can only be comptime only

#

few other fixes:

#

surround the whole function body in a comptime block instead of having comptime vars, and declare tokens as:

var tokens: []const Token = &.{};
gaunt sigil
#
src/main.zig:44:13: error: switch on type '?main.Case'
    switch (case) {
            ^~~~
shy rock
#

like I demonstrated in my original example, that function returns ?Case, you have to unwrap it first

warm rampart
gaunt sigil
#

gotcha

#

looks like there are still some comptime issues

#
src/main.zig:46:18: error: unable to resolve comptime value
        tokens = tokens ++ Token {
                 ^~~~~~
#

nvm

#

well...

#
switch (case) {
      .function => {
        comptime var newTok = [_]Token{Token {
          .kind = TOKEN.FUNCTION,
          .val = "function"
        }};
        tokens = tokens ++ newTok;
        cur_tok_start += token_depth;
        token_depth = 0;
      },
      else => {
        token_depth += 1;
      }
    }
  }
#

seems hard to not make my Token a const pointer if I want to define it literally

#
src/main.zig:51:25: error: expected type '[]main.Token', found '*const [1]main.Token'
        tokens = tokens ++ newTok;
                 ~~~~~~~^~~~~~~~~
gaunt sigil
#

tried this which doesn't work

#
comptime var newTok: [*]Token = undefined;
        newTok[0] = Token {
          .kind = TOKEN.FUNCTION,
          .val = "function"
        };
#
src/main.zig:51:15: error: use of undefined value here causes undefined behavior
        newTok[0] = Token {
        ~~~~~~^~~
warm rampart
#

Problem there is that var newTok: [*]Token = undefined creates an uninitialized pointer, not a pointer to an uninitialized array

shy rock
#

like I said earlier

#

wrap all of your code in a comptime block

#

and also fix your uninitialised pointer

#

undefined is not the same as empty

#

if you want an empty slice or w/e, you need to at least assign &.{}

#

I would shorten your line to

tokens = tokens ++ &[_]Token{.{
    .kind = TOKEN.FUNCTION,
    .val = "function",
}};
heavy barn
gaunt sigil
#

seems to still be upset even with the comptime block and fixed initialization

#
fn parser(comptime input: [:0]const u8) []Token {
  comptime {

    var tokens: []Token = &.{};
    var cur_tok_start = 0;
    var token_depth = 0;
    for (input) |char| {
      _ = char;
      var case = std.meta.stringToEnum(Case, input[cur_tok_start..(cur_tok_start + token_depth)]) orelse Case.ident;
      // std.debug.print("THE CASE {}", .{case});
      // @compileLog(cur_tok_start, cur_tok_s)
      // @compileLog("THE CASE {}", input[cur_tok_start..(cur_tok_start + 1)]);
      switch (case) {
        .function => {
          tokens = tokens ++ &[_]Token{ .{
            .kind = TOKEN.FUNCTION,
            .val = "function"
          }};
          cur_tok_start += token_depth;
          token_depth = 0;
        },
        else => {
          token_depth += 1;
        }
      }
    }
    return tokens;
    }
}```
#
src/main.zig:49:25: error: expected type '[]main.Token', found '*const [1]main.Token'
        tokens = tokens ++ &[_]Token{ .{
                 ~~~~~~~^~
shy rock
#

there's not really a good and safe way to return mutable comptime memory

gaunt sigil
#

hence your recommendation against doing as much in comptime as I was indicating I'd like I guess...

shy rock
#

though, later if you want to be able to modify the list of tokens for whatever reason, you can just do something like:

var tokens = parser(input)[0..].*;

to make it an array

gaunt sigil
#

well I'm eventually going to be turning thsi into a while loop

#

and continually adding to tokens

shy rock
#

wdym

#

as in, during runtime?

gaunt sigil
#

ah no sorry the for loop is achieving it... i lapsed for a sec

#

right now the compiler is still upset even with the const

shy rock
#

what's the error

gaunt sigil
#
 /Users/interpretations/projects/zigscript$ zig build-exe src/main.zig -freference-trace
src/main.zig:50:33: error: pointer modifier 'const' not allowed on array child type
          tokens = tokens ++ [_]const Token{ .{
                                ^~~~~
shy rock
#

that's only for the slice

#

arrays are value types, and can't have attributes related to memory

#

that should remain as &[_]Token{.{ ... }}

gaunt sigil
#

ah I see I think

#

well now I'm going through my loop too many times... so I'm going to work on fixing that, and hopefully we'll see that this works once I get past that error

#

seems to have a lot of details about the things that tend to trip me up

shy rock
#

haven't actually seen that

lapis wedge
#

yea, nice video

#

Helped me a lot

gaunt sigil
#

it appears that for some reason...

#
@compileLog("\n", input[cur_tok_start..(cur_tok_start + token_depth)], "\n");
#

is just giving me the entire input

#

even if I know that those values that are used to get a slice of the input are say 1, and 0

shy rock
#

I'll ask that you open a new post for that

gaunt sigil
#

1 and 8

#

sure