Make null optional unwraps return error
This commit is contained in:
parent
bf0d2f6642
commit
44dfcd6bd0
2 changed files with 19 additions and 15 deletions
|
@ -73,11 +73,11 @@ fn executeStatement(
|
||||||
) !void {
|
) !void {
|
||||||
switch (stmt) {
|
switch (stmt) {
|
||||||
.expression => |expr| {
|
.expression => |expr| {
|
||||||
const val = evaluateExpression(expr, args, captures, context);
|
const val = try evaluateExpression(expr, args, captures, context);
|
||||||
try print(writer, val);
|
try print(writer, val);
|
||||||
},
|
},
|
||||||
.@"for" => |loop| {
|
.@"for" => |loop| {
|
||||||
const iterable = evaluateExpression(loop.header.iterable, args, captures, context);
|
const iterable = try evaluateExpression(loop.header.iterable, args, captures, context);
|
||||||
const subtemplate = loop.subtemplate;
|
const subtemplate = loop.subtemplate;
|
||||||
//std.log.debug("{any}", .{subtemplate});
|
//std.log.debug("{any}", .{subtemplate});
|
||||||
for (iterable) |v| {
|
for (iterable) |v| {
|
||||||
|
@ -92,7 +92,7 @@ fn executeStatement(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.@"if" => |if_stmt| {
|
.@"if" => |if_stmt| {
|
||||||
const condition = evaluateExpression(if_stmt.header.condition, args, captures, context);
|
const condition = try evaluateExpression(if_stmt.header.condition, args, captures, context);
|
||||||
const subtemplate = if_stmt.subtemplate;
|
const subtemplate = if_stmt.subtemplate;
|
||||||
var was_true: bool = false;
|
var was_true: bool = false;
|
||||||
if (if_stmt.header.capture) |capture| {
|
if (if_stmt.header.capture) |capture| {
|
||||||
|
@ -128,7 +128,7 @@ fn executeStatement(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.@"switch" => |switch_stmt| {
|
.@"switch" => |switch_stmt| {
|
||||||
const expr = evaluateExpression(switch_stmt.expression, args, captures, context);
|
const expr = try evaluateExpression(switch_stmt.expression, args, captures, context);
|
||||||
|
|
||||||
const exhaustive = switch_stmt.cases.len == std.meta.fields(@TypeOf(expr)).len;
|
const exhaustive = switch_stmt.cases.len == std.meta.fields(@TypeOf(expr)).len;
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ fn executeStatement(
|
||||||
writer,
|
writer,
|
||||||
templates,
|
templates,
|
||||||
new_template,
|
new_template,
|
||||||
evaluateExpression(call.args, args, captures, context),
|
try evaluateExpression(call.args, args, captures, context),
|
||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -184,7 +184,7 @@ fn executeStatement(
|
||||||
try std.fmt.format(
|
try std.fmt.format(
|
||||||
writer,
|
writer,
|
||||||
"{" ++ fmt.format ++ "}",
|
"{" ++ fmt.format ++ "}",
|
||||||
.{evaluateExpression(fmt.value, args, captures, context)},
|
.{try evaluateExpression(fmt.value, args, captures, context)},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
//else => @compileError("TODO"),
|
//else => @compileError("TODO"),
|
||||||
|
@ -209,6 +209,7 @@ fn print(writer: anytype, arg: anytype) !void {
|
||||||
try std.fmt.format(writer, "{}", .{arg});
|
try std.fmt.format(writer, "{}", .{arg});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DerefError = error{NullOptional};
|
||||||
fn Deref(comptime T: type, comptime names: []const DerefDecl) type {
|
fn Deref(comptime T: type, comptime names: []const DerefDecl) type {
|
||||||
if (names.len == 0) return T;
|
if (names.len == 0) return T;
|
||||||
|
|
||||||
|
@ -226,15 +227,17 @@ fn Deref(comptime T: type, comptime names: []const DerefDecl) type {
|
||||||
return Deref(F, names[1..]);
|
return Deref(F, names[1..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deref(arg: anytype, comptime names: []const DerefDecl) Deref(@TypeOf(arg), names) {
|
fn deref(arg: anytype, comptime names: []const DerefDecl) DerefError!Deref(@TypeOf(arg), names) {
|
||||||
if (names.len == 0) return arg;
|
if (names.len == 0) return arg;
|
||||||
|
|
||||||
switch (names[0]) {
|
switch (names[0]) {
|
||||||
.field => |name| return deref(@field(arg, name), names[1..]),
|
.field => |name| return deref(@field(arg, name), names[1..]),
|
||||||
.optional_unwrap => return arg.?,
|
.optional_unwrap => return arg orelse error.NullOptional,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ExpressionError = DerefError;
|
||||||
|
|
||||||
fn EvaluateExpression(
|
fn EvaluateExpression(
|
||||||
comptime expression: Expression,
|
comptime expression: Expression,
|
||||||
comptime Args: type,
|
comptime Args: type,
|
||||||
|
@ -257,14 +260,14 @@ fn evaluateExpression(
|
||||||
args: anytype,
|
args: anytype,
|
||||||
captures: anytype,
|
captures: anytype,
|
||||||
context: anytype,
|
context: anytype,
|
||||||
) EvaluateExpression(expression, @TypeOf(args), @TypeOf(captures), @TypeOf(context)) {
|
) ExpressionError!EvaluateExpression(expression, @TypeOf(args), @TypeOf(captures), @TypeOf(context)) {
|
||||||
return switch (expression) {
|
return switch (expression) {
|
||||||
.arg_deref => |names| deref(args, names),
|
.arg_deref => |names| try deref(args, names),
|
||||||
.capture_deref => |names| deref(captures, names),
|
.capture_deref => |names| try deref(captures, names),
|
||||||
.context_deref => |names| deref(context, names),
|
.context_deref => |names| try deref(context, names),
|
||||||
.equals => |eql| {
|
.equals => |eql| {
|
||||||
const lhs = evaluateExpression(eql.lhs, args, captures, context);
|
const lhs = try evaluateExpression(eql.lhs, args, captures, context);
|
||||||
const rhs = evaluateExpression(eql.rhs, args, captures, context);
|
const rhs = try evaluateExpression(eql.rhs, args, captures, context);
|
||||||
const T = @TypeOf(lhs, rhs);
|
const T = @TypeOf(lhs, rhs);
|
||||||
if (comptime std.meta.trait.isZigString(T)) {
|
if (comptime std.meta.trait.isZigString(T)) {
|
||||||
return std.mem.eql(u8, lhs, rhs);
|
return std.mem.eql(u8, lhs, rhs);
|
||||||
|
@ -274,7 +277,7 @@ fn evaluateExpression(
|
||||||
},
|
},
|
||||||
.builtin => |call| switch (call.*) {
|
.builtin => |call| switch (call.*) {
|
||||||
.isTag => |hdr| {
|
.isTag => |hdr| {
|
||||||
const val = evaluateExpression(hdr.expression, args, captures, context);
|
const val = try evaluateExpression(hdr.expression, args, captures, context);
|
||||||
return std.meta.isTag(val, hdr.tag);
|
return std.meta.isTag(val, hdr.tag);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
{#if .maybe_bar |$v|}{$v}{#else}null{/if}
|
{#if .maybe_bar |$v|}{$v}{#else}null{/if}
|
||||||
{#if .maybe_foo |$_|}abcd{#else}null{/if}
|
{#if .maybe_foo |$_|}abcd{#else}null{/if}
|
||||||
{.maybe_foo.?}
|
{.maybe_foo.?}
|
||||||
|
This causes an error: {{.maybe_bar.?}}
|
||||||
|
|
||||||
<template>{#template test_tmpl .bar}</template>
|
<template>{#template test_tmpl .bar}</template>
|
||||||
<template>{#template test_tmpl .}</template>
|
<template>{#template test_tmpl .}</template>
|
||||||
|
|
Loading…
Reference in a new issue