authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-04-10 12:10:57 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-04-10 12:10:57 -07:00
logf734eef7d8fc77e3c2b4c3447a8d73b5aedaa283
tree422cb0ef9fa4017ea5ede04ea450214fe5afc7d3
parent115c652942aa7a063335e202613716aee22737a6

allow parentheses values as arguments to custom functions


2 files changed, 33 insertions(+), 15 deletions(-)

src/astgen.zig+6
...@@ -61,6 +61,7 @@ pub const Arg = union(enum) {...@@ -61,6 +61,7 @@ pub const Arg = union(enum) {
61 lookup: []const string,61 lookup: []const string,
62 plain: string,62 plain: string,
63 int: u64,63 int: u64,
64 value: []const Value,
64};65};
6566
66//67//
...@@ -214,6 +215,11 @@ const Parser = struct {...@@ -214,6 +215,11 @@ const Parser = struct {
214 ret = ret ++ &[_]Arg{.{ .plain = self.eat(.string) }};215 ret = ret ++ &[_]Arg{.{ .plain = self.eat(.string) }};
215 continue;216 continue;
216 }217 }
218 if (self.tryEatSymbol("(")) {
219 self.index -= 1;
220 ret = ret ++ &[_]Arg{.{ .value = self.doChildren() }};
221 continue;
222 }
217 if (temp.len == 0 and self.nextIs(.word)) {223 if (temp.len == 0 and self.nextIs(.word)) {
218 const next_word = self.eat(.word);224 const next_word = self.eat(.word);
219 if (extras.matchesAll(u8, next_word, std.ascii.isDigit)) {225 if (extras.matchesAll(u8, next_word, std.ascii.isDigit)) {
src/lib.zig+27-15
...@@ -94,7 +94,8 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -94,7 +94,8 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
94 }94 }
95 },95 },
96 .string => |v| {96 .string => |v| {
97 try writeEscaped(v[1 .. v.len - 1], writer);97 if (opts.escaped) try writeEscaped(v[1 .. v.len - 1], writer);
98 if (!opts.escaped) try writer.writeAll(v[1 .. v.len - 1]);
98 },99 },
99 .replacement => |repl| {100 .replacement => |repl| {
100 const v = repl.arms;101 const v = repl.arms;
...@@ -108,7 +109,8 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -108,7 +109,8 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
108 return;109 return;
109 }110 }
110 const s = std.mem.trim(u8, x, "\n");111 const s = std.mem.trim(u8, x, "\n");
111 try writeEscaped(s, writer);112 if (opts.escaped) try writeEscaped(s, writer);
113 if (!opts.escaped) try writer.writeAll(s);
112 return;114 return;
113 }115 }
114 if (TI == .Int or TI == .Float or TI == .ComptimeInt or TI == .ComptimeFloat) {116 if (TI == .Int or TI == .Float or TI == .ComptimeInt or TI == .ComptimeFloat) {
...@@ -128,7 +130,8 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -128,7 +130,8 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
128 return;130 return;
129 }131 }
130 const s = std.mem.trim(u8, &x, "\n");132 const s = std.mem.trim(u8, &x, "\n");
131 try writeEscaped(s, writer);133 if (opts.escaped) try writeEscaped(s, writer);
134 if (!opts.escaped) try writer.writeAll(s);
132 return;135 return;
133 }136 }
134 @compileError(std.fmt.comptimePrint("pek: print {s}: unsupported type: {s}", .{ v, @typeName(TO) }));137 @compileError(std.fmt.comptimePrint("pek: print {s}: unsupported type: {s}", .{ v, @typeName(TO) }));
...@@ -136,7 +139,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -136,7 +139,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
136 .block => |v| {139 .block => |v| {
137 const body = astgen.Value{ .body = v.body };140 const body = astgen.Value{ .body = v.body };
138 const bottom = astgen.Value{ .body = v.bttm };141 const bottom = astgen.Value{ .body = v.bttm };
139 const x = resolveArg(v.args[0], data, ctx);142 const x = try resolveArg(v.args[0], alloc, data, ctx, opts);
140 const T = @TypeOf(x);143 const T = @TypeOf(x);
141 const TI = @typeInfo(T);144 const TI = @typeInfo(T);
142 switch (v.name) {145 switch (v.name) {
...@@ -150,12 +153,12 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -150,12 +153,12 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
150 const x2 = try switch (@typeInfo(@TypeOf(f)).Fn.params.len) {153 const x2 = try switch (@typeInfo(@TypeOf(f)).Fn.params.len) {
151 2 => f(alloc, x),154 2 => f(alloc, x),
152 3 => blk: {155 3 => blk: {
153 const y = resolveArg(v.args[1], data, ctx);156 const y = try resolveArg(v.args[1], alloc, data, ctx, opts);
154 break :blk f(alloc, x, y);157 break :blk f(alloc, x, y);
155 },158 },
156 4 => blk: {159 4 => blk: {
157 const y = resolveArg(v.args[1], data, ctx);160 const y = try resolveArg(v.args[1], alloc, data, ctx, opts);
158 const z = resolveArg(v.args[2], data, ctx);161 const z = try resolveArg(v.args[2], alloc, data, ctx, opts);
159 break :blk f(alloc, x, y, z);162 break :blk f(alloc, x, y, z);
160 },163 },
161 else => unreachable, // TODO164 else => unreachable, // TODO
...@@ -180,12 +183,12 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -180,12 +183,12 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
180 const x2 = try switch (@typeInfo(@TypeOf(f)).Fn.params.len) {183 const x2 = try switch (@typeInfo(@TypeOf(f)).Fn.params.len) {
181 2 => f(alloc, x),184 2 => f(alloc, x),
182 3 => blk: {185 3 => blk: {
183 const y = resolveArg(v.args[1], data, ctx);186 const y = try resolveArg(v.args[1], alloc, data, ctx, opts);
184 break :blk f(alloc, x, y);187 break :blk f(alloc, x, y);
185 },188 },
186 4 => blk: {189 4 => blk: {
187 const y = resolveArg(v.args[1], data, ctx);190 const y = try resolveArg(v.args[1], alloc, data, ctx, opts);
188 const z = resolveArg(v.args[2], data, ctx);191 const z = try resolveArg(v.args[2], alloc, data, ctx, opts);
189 break :blk f(alloc, x, y, z);192 break :blk f(alloc, x, y, z);
190 },193 },
191 else => unreachable, // TODO194 else => unreachable, // TODO
...@@ -206,7 +209,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -206,7 +209,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
206 },209 },
207 .ifequal => {210 .ifequal => {
208 comptime assertEqual(v.args.len, 2);211 comptime assertEqual(v.args.len, 2);
209 const y = resolveArg(v.args[1], data, ctx);212 const y = try resolveArg(v.args[1], alloc, data, ctx, opts);
210 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {213 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {
211 return try doif(alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));214 return try doif(alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));
212 }215 }
...@@ -217,7 +220,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -217,7 +220,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
217 },220 },
218 .ifnotequal => {221 .ifnotequal => {
219 comptime assertEqual(v.args.len, 2);222 comptime assertEqual(v.args.len, 2);
220 const y = resolveArg(v.args[1], data, ctx);223 const y = try resolveArg(v.args[1], alloc, data, ctx, opts);
221 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {224 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {
222 return try doif(alloc, writer, body, bottom, data, ctx, opts, !std.mem.eql(u8, @tagName(x), y));225 return try doif(alloc, writer, body, bottom, data, ctx, opts, !std.mem.eql(u8, @tagName(x), y));
223 }226 }
...@@ -247,7 +250,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -247,7 +250,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
247 args.@"1" = list.writer();250 args.@"1" = list.writer();
248 inline for (v.args, 0..) |arg, i| {251 inline for (v.args, 0..) |arg, i| {
249 const field_name = comptime std.fmt.comptimePrint("{d}", .{i + 2});252 const field_name = comptime std.fmt.comptimePrint("{d}", .{i + 2});
250 @field(args, field_name) = resolveArg(arg, data, ctx);253 @field(args, field_name) = try resolveArg(arg, alloc, data, ctx, opts);
251 }254 }
252 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };255 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };
253 try @call(.auto, func, args);256 try @call(.auto, func, args);
...@@ -270,7 +273,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d...@@ -270,7 +273,7 @@ fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, d
270 };273 };
271 inline for (v.args, 0..) |arg, i| {274 inline for (v.args, 0..) |arg, i| {
272 const field_name = comptime std.fmt.comptimePrint("{d}", .{i});275 const field_name = comptime std.fmt.comptimePrint("{d}", .{i});
273 @field(args[3], field_name) = resolveArg(arg, data, ctx);276 @field(args[3], field_name) = try resolveArg(arg, alloc, data, ctx, opts);
274 }277 }
275 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };278 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };
276 try @call(.auto, func, args);279 try @call(.auto, func, args);
...@@ -293,13 +296,21 @@ pub const DoOptions = struct {...@@ -293,13 +296,21 @@ pub const DoOptions = struct {
293 Ctx: type,296 Ctx: type,
294 indent: usize,297 indent: usize,
295 flag1: bool,298 flag1: bool,
299 escaped: bool = true,
296};300};
297301
298fn resolveArg(comptime arg: astgen.Arg, data: anytype, ctx: anytype) ResolveArg(arg, @TypeOf(data), @TypeOf(ctx)) {302fn resolveArg(comptime arg: astgen.Arg, alloc: std.mem.Allocator, data: anytype, ctx: anytype, comptime opts: DoOptions) !ResolveArg(arg, @TypeOf(data), @TypeOf(ctx)) {
299 return switch (arg) {303 return switch (arg) {
300 .plain => |av| av[1 .. av.len - 1],304 .plain => |av| av[1 .. av.len - 1],
301 .lookup => |av| if (comptime std.mem.eql(u8, av[0], "this")) search(av[1..], data) else search(av, ctx),305 .lookup => |av| if (comptime std.mem.eql(u8, av[0], "this")) search(av[1..], data) else search(av, ctx),
302 .int => |av| av,306 .int => |av| av,
307 .value => |av| {
308 var list = std.ArrayList(u8).init(alloc);
309 comptime var newopts = opts;
310 newopts.escaped = false;
311 try do(alloc, list.writer(), astgen.Value{ .body = av }, data, ctx, newopts);
312 return list.items;
313 },
303 };314 };
304}315}
305316
...@@ -308,6 +319,7 @@ fn ResolveArg(comptime arg: astgen.Arg, comptime This: type, comptime Ctx: type)...@@ -308,6 +319,7 @@ fn ResolveArg(comptime arg: astgen.Arg, comptime This: type, comptime Ctx: type)
308 .plain => string,319 .plain => string,
309 .lookup => |av| if (comptime std.mem.eql(u8, av[0], "this")) FieldSearch(This, av[1..]) else FieldSearch(Ctx, av),320 .lookup => |av| if (comptime std.mem.eql(u8, av[0], "this")) FieldSearch(This, av[1..]) else FieldSearch(Ctx, av),
310 .int => u64,321 .int => u64,
322 .value => string,
311 };323 };
312}324}
313325