Make null optional unwraps return error

This commit is contained in:
jaina heartles 2022-12-13 01:52:16 -08:00
parent bf0d2f6642
commit 44dfcd6bd0
2 changed files with 19 additions and 15 deletions

View file

@ -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);
},
},

View file

@ -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>