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 {
|
||||
switch (stmt) {
|
||||
.expression => |expr| {
|
||||
const val = evaluateExpression(expr, args, captures, context);
|
||||
const val = try evaluateExpression(expr, args, captures, context);
|
||||
try print(writer, val);
|
||||
},
|
||||
.@"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;
|
||||
//std.log.debug("{any}", .{subtemplate});
|
||||
for (iterable) |v| {
|
||||
|
@ -92,7 +92,7 @@ fn executeStatement(
|
|||
}
|
||||
},
|
||||
.@"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;
|
||||
var was_true: bool = false;
|
||||
if (if_stmt.header.capture) |capture| {
|
||||
|
@ -128,7 +128,7 @@ fn executeStatement(
|
|||
}
|
||||
},
|
||||
.@"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;
|
||||
|
||||
|
@ -176,7 +176,7 @@ fn executeStatement(
|
|||
writer,
|
||||
templates,
|
||||
new_template,
|
||||
evaluateExpression(call.args, args, captures, context),
|
||||
try evaluateExpression(call.args, args, captures, context),
|
||||
context,
|
||||
);
|
||||
},
|
||||
|
@ -184,7 +184,7 @@ fn executeStatement(
|
|||
try std.fmt.format(
|
||||
writer,
|
||||
"{" ++ fmt.format ++ "}",
|
||||
.{evaluateExpression(fmt.value, args, captures, context)},
|
||||
.{try evaluateExpression(fmt.value, args, captures, context)},
|
||||
);
|
||||
},
|
||||
//else => @compileError("TODO"),
|
||||
|
@ -209,6 +209,7 @@ fn print(writer: anytype, arg: anytype) !void {
|
|||
try std.fmt.format(writer, "{}", .{arg});
|
||||
}
|
||||
|
||||
const DerefError = error{NullOptional};
|
||||
fn Deref(comptime T: type, comptime names: []const DerefDecl) type {
|
||||
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..]);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
switch (names[0]) {
|
||||
.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(
|
||||
comptime expression: Expression,
|
||||
comptime Args: type,
|
||||
|
@ -257,14 +260,14 @@ fn evaluateExpression(
|
|||
args: anytype,
|
||||
captures: anytype,
|
||||
context: anytype,
|
||||
) EvaluateExpression(expression, @TypeOf(args), @TypeOf(captures), @TypeOf(context)) {
|
||||
) ExpressionError!EvaluateExpression(expression, @TypeOf(args), @TypeOf(captures), @TypeOf(context)) {
|
||||
return switch (expression) {
|
||||
.arg_deref => |names| deref(args, names),
|
||||
.capture_deref => |names| deref(captures, names),
|
||||
.context_deref => |names| deref(context, names),
|
||||
.arg_deref => |names| try deref(args, names),
|
||||
.capture_deref => |names| try deref(captures, names),
|
||||
.context_deref => |names| try deref(context, names),
|
||||
.equals => |eql| {
|
||||
const lhs = evaluateExpression(eql.lhs, args, captures, context);
|
||||
const rhs = evaluateExpression(eql.rhs, args, captures, context);
|
||||
const lhs = try evaluateExpression(eql.lhs, args, captures, context);
|
||||
const rhs = try evaluateExpression(eql.rhs, args, captures, context);
|
||||
const T = @TypeOf(lhs, rhs);
|
||||
if (comptime std.meta.trait.isZigString(T)) {
|
||||
return std.mem.eql(u8, lhs, rhs);
|
||||
|
@ -274,7 +277,7 @@ fn evaluateExpression(
|
|||
},
|
||||
.builtin => |call| switch (call.*) {
|
||||
.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);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
{#if .maybe_bar |$v|}{$v}{#else}null{/if}
|
||||
{#if .maybe_foo |$_|}abcd{#else}null{/if}
|
||||
{.maybe_foo.?}
|
||||
This causes an error: {{.maybe_bar.?}}
|
||||
|
||||
<template>{#template test_tmpl .bar}</template>
|
||||
<template>{#template test_tmpl .}</template>
|
||||
|
|
Loading…
Reference in a new issue