authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-06-15 18:54:07 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-06-15 18:54:07 -07:00
log82747c72ddaa89c023e454dd4a4cecd4773d5433
treedbe0380f180473831c0e203404e11caddf0989da
parent08ae93da6fde7392d66bac2c34c4a4f530fe7696

allow passing plain strings as args to blocks and functions


2 files changed, 39 insertions(+), 17 deletions(-)

src/astgen.zig+20-12
...@@ -35,7 +35,7 @@ pub const Replacement = struct {...@@ -35,7 +35,7 @@ pub const Replacement = struct {
35pub const Block = struct {35pub const Block = struct {
36 name: Type,36 name: Type,
37 func: ?string,37 func: ?string,
38 args: []const []const string,38 args: []const Arg,
39 body: Body,39 body: Body,
40 bttm: Body,40 bttm: Body,
4141
...@@ -53,7 +53,12 @@ pub const Body = []const Value;...@@ -53,7 +53,12 @@ pub const Body = []const Value;
53pub const Fn = struct {53pub const Fn = struct {
54 name: string,54 name: string,
55 raw: bool,55 raw: bool,
56 args: []const []const string,56 args: []const Arg,
57};
58
59pub const Arg = union(enum) {
60 lookup: []const string,
61 plain: string,
57};62};
5863
59//64//
...@@ -93,6 +98,7 @@ const Parser = struct {...@@ -93,6 +98,7 @@ const Parser = struct {
93 }98 }
9499
95 fn tryEatSymbol(comptime self: *Parser, comptime needle: string) bool {100 fn tryEatSymbol(comptime self: *Parser, comptime needle: string) bool {
101 if (self.index >= self.tokens.len) return false;
96 switch (self.tokens[self.index].data) {102 switch (self.tokens[self.index].data) {
97 .symbol => |sym| {103 .symbol => |sym| {
98 if (std.mem.eql(u8, sym, needle)) {104 if (std.mem.eql(u8, sym, needle)) {
...@@ -194,23 +200,25 @@ const Parser = struct {...@@ -194,23 +200,25 @@ const Parser = struct {
194 return Value{ .element = self.doElement() };200 return Value{ .element = self.doElement() };
195 }201 }
196202
197 pub fn doArgs(comptime self: *Parser) []const []const string {203 pub fn doArgs(comptime self: *Parser) []const Arg {
198 var ret: []const []const string = &.{};204 var ret: []const Arg = &.{};
199 var temp: []const string = &.{self.eat(.word)};205 var temp: []const string = &.{};
200 while (!self.tryEatSymbol("}")) {206 while (!self.tryEatSymbol("}")) {
207 if (self.nextIs(.string)) {
208 ret = ret ++ &[_]Arg{.{ .plain = self.eat(.string) }};
209 continue;
210 }
211 if (temp.len == 0 and self.nextIs(.word)) {
212 temp = temp ++ &[_]string{self.eat(.word)};
213 }
201 if (self.tryEatSymbol(".")) {214 if (self.tryEatSymbol(".")) {
202 temp = temp ++ &[_]string{self.eat(.word)};215 temp = temp ++ &[_]string{self.eat(.word)};
203 } else {216 } else {
204 ret = ret ++ &[_][]const string{temp};217 ret = ret ++ &[_]Arg{.{ .lookup = temp }};
205 temp = &.{};218 temp = &.{};
206 if (comptime self.nextIs(.string)) {
207 ret = ret ++ &[_][]const string{&.{self.eat(.string)}};
208 } else {
209 temp = &.{self.eat(.word)};
210 }
211 }219 }
212 }220 }
213 if (temp.len > 0) ret = ret ++ &[_][]const string{temp};221 if (temp.len > 0) ret = ret ++ &[_]Arg{.{ .lookup = temp }};
214 return ret;222 return ret;
215 }223 }
216224
src/lib.zig+19-5
...@@ -127,7 +127,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V...@@ -127,7 +127,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V
127 .block => |v| {127 .block => |v| {
128 const body = astgen.Value{ .body = v.body };128 const body = astgen.Value{ .body = v.body };
129 const bottom = astgen.Value{ .body = v.bttm };129 const bottom = astgen.Value{ .body = v.bttm };
130 const x = if (comptime std.mem.eql(u8, v.args[0][0], "this")) search(v.args[0][1..], data) else search(v.args[0], ctx);130 const x = resolveArg(v.args[0], data, ctx);
131 const T = @TypeOf(x);131 const T = @TypeOf(x);
132 const TI = @typeInfo(T);132 const TI = @typeInfo(T);
133 switch (v.name) {133 switch (v.name) {
...@@ -167,7 +167,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V...@@ -167,7 +167,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V
167 },167 },
168 .ifequal => {168 .ifequal => {
169 comptime assertEqual(v.args.len, 2);169 comptime assertEqual(v.args.len, 2);
170 const y = if (comptime std.mem.eql(u8, v.args[1][0], "this")) search(v.args[1][1..], data) else search(v.args[1], ctx);170 const y = resolveArg(v.args[1], data, ctx);
171 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {171 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {
172 return try doif(alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));172 return try doif(alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));
173 }173 }
...@@ -175,7 +175,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V...@@ -175,7 +175,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V
175 },175 },
176 .ifnotequal => {176 .ifnotequal => {
177 comptime assertEqual(v.args.len, 2);177 comptime assertEqual(v.args.len, 2);
178 const y = if (comptime std.mem.eql(u8, v.args[1][0], "this")) search(v.args[1][1..], data) else search(v.args[1], ctx);178 const y = resolveArg(v.args[1], data, ctx);
179 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {179 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {
180 return try doif(alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));180 return try doif(alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));
181 }181 }
...@@ -201,7 +201,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V...@@ -201,7 +201,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V
201 args.@"1" = list.writer();201 args.@"1" = list.writer();
202 inline for (v.args, 0..) |arg, i| {202 inline for (v.args, 0..) |arg, i| {
203 const field_name = comptime std.fmt.comptimePrint("{d}", .{i + 2});203 const field_name = comptime std.fmt.comptimePrint("{d}", .{i + 2});
204 @field(args, field_name) = if (comptime std.mem.eql(u8, arg[0], "this")) search(arg[1..], data) else search(arg, ctx);204 @field(args, field_name) = resolveArg(arg, data, ctx);
205 }205 }
206 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };206 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };
207 try @call(.auto, func, args);207 try @call(.auto, func, args);
...@@ -223,7 +223,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V...@@ -223,7 +223,7 @@ inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.V
223 };223 };
224 inline for (v.args, 0..) |arg, i| {224 inline for (v.args, 0..) |arg, i| {
225 const field_name = comptime std.fmt.comptimePrint("{d}", .{i});225 const field_name = comptime std.fmt.comptimePrint("{d}", .{i});
226 @field(args[3], field_name) = if (comptime std.mem.eql(u8, arg[0], "this")) search(arg[1..], data) else search(arg, ctx);226 @field(args[3], field_name) = resolveArg(arg, data, ctx);
227 }227 }
228 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };228 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };
229 try @call(.auto, func, args);229 try @call(.auto, func, args);
...@@ -248,6 +248,20 @@ pub const DoOptions = struct {...@@ -248,6 +248,20 @@ pub const DoOptions = struct {
248 flag1: bool,248 flag1: bool,
249};249};
250250
251fn resolveArg(comptime arg: astgen.Arg, data: anytype, ctx: anytype) ResolveArg(arg, @TypeOf(data), @TypeOf(ctx)) {
252 return switch (arg) {
253 .plain => |av| av[1 .. av.len - 1],
254 .lookup => |av| if (comptime std.mem.eql(u8, av[0], "this")) search(av[1..], data) else search(av, ctx),
255 };
256}
257
258fn ResolveArg(comptime arg: astgen.Arg, comptime This: type, comptime Ctx: type) type {
259 return switch (arg) {
260 .plain => string,
261 .lookup => |av| if (comptime std.mem.eql(u8, av[0], "this")) FieldSearch(This, av[1..]) else FieldSearch(Ctx, av),
262 };
263}
264
251fn search(comptime args: []const string, ctx: anytype) FieldSearch(@TypeOf(ctx), args) {265fn search(comptime args: []const string, ctx: anytype) FieldSearch(@TypeOf(ctx), args) {
252 if (args.len == 0) return ctx;266 if (args.len == 0) return ctx;
253 if (args[0][0] == '"') return std.mem.trim(u8, args[0], "\"");267 if (args[0][0] == '"') return std.mem.trim(u8, args[0], "\"");