diff --git a/src/renderer.zig b/src/renderer.zig index ec1cc0a..c6455d1 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -291,4 +291,118 @@ pub const Renderer = struct { .null => false, }; } + + fn evaluateCondition(self: *const Renderer, allocator: Allocator, expr: []const u8) RenderError!bool { + const trimmed = std.mem.trim(u8, expr, " \t\r\n"); + if (trimmed.len == 0) return false; + + var parts = std.mem.splitScalar(u8, trimmed, ' '); + + // Coleta tokens não vazios + var tokens = std.ArrayList([]const u8){}; + defer tokens.deinit(allocator); + + while (parts.next()) |part| { + const t = std.mem.trim(u8, part, " \t\r\n"); + if (t.len > 0) try tokens.append(allocator, t); + } + + // Caso simples: só nome de variável + if (tokens.items.len == 1) { + const value = self.context.get(tokens.items[0]) orelse Value.null; + return isTruthy(value); + } + + // Caso especial: "not variavel" + if (tokens.items.len == 2 and std.mem.eql(u8, tokens.items[0], "not")) { + const value = self.context.get(tokens.items[1]) orelse Value.null; + return !isTruthy(value); + } + + // Caso com operadores de comparação: var op valor + if (tokens.items.len == 3) { + const left = tokens.items[0]; + const op = tokens.items[1]; + const right_str = tokens.items[2]; + + const left_value = self.context.get(left) orelse Value.null; + const right_value = parseLiteral(right_str); + + if (std.mem.eql(u8, op, ">")) return compare(left_value, right_value, .gt); + if (std.mem.eql(u8, op, "<")) return compare(left_value, right_value, .lt); + if (std.mem.eql(u8, op, ">=")) return compare(left_value, right_value, .ge); + if (std.mem.eql(u8, op, "<=")) return compare(left_value, right_value, .le); + if (std.mem.eql(u8, op, "==")) return compare(left_value, right_value, .eq); + if (std.mem.eql(u8, op, "!=")) return compare(left_value, right_value, .ne); + + return error.InvalidSyntax; + } + + // Caso mais complexo (and/or/not composto) - por enquanto erro + return error.UnsupportedExpression; + } + + // Função auxiliar: converte string literal pra Value + fn parseLiteral(str: []const u8) Value { + const trimmed = std.mem.trim(u8, str, " \t\r\n\"'"); + if (std.mem.eql(u8, trimmed, "true")) return Value{ .bool = true }; + if (std.mem.eql(u8, trimmed, "false")) return Value{ .bool = false }; + if (std.mem.eql(u8, trimmed, "null")) return Value.null; + + if (std.fmt.parseInt(i64, trimmed, 10)) |n| return Value{ .int = n } else |_| {} + if (std.fmt.parseFloat(f64, trimmed)) |f| return Value{ .float = f } else |_| {} + + return Value{ .string = trimmed }; + } + + // Função auxiliar: truthy check + fn isTruthy(v: Value) bool { + return switch (v) { + .null => false, + .bool => |b| b, + .int => |i| i != 0, + .float => |f| f != 0.0, + .string => |s| s.len > 0, + .list => |l| l.len > 0, + .dict => |d| d.count() > 0, + }; + } + + // Função auxiliar: comparação + fn compare(left: Value, right: Value, op: enum { gt, lt, ge, le, eq, ne, not }) bool { + // Implementação básica (expanda conforme necessário) + switch (left) { + .int => |l| switch (right) { + .int => |r| return switch (op) { + .gt => l > r, + .lt => l < r, + .ge => l >= r, + .le => l <= r, + .eq => l == r, + .ne, .not => l != r, + }, + else => return false, + }, + .float => |l| switch (right) { + .float => |r| return switch (op) { + .gt => l > r, + .lt => l < r, + .ge => l >= r, + .le => l <= r, + .eq => l == r, + .ne, .not => l != r, + }, + else => return false, + }, + .string => |l| switch (right) { + .string => |r| return switch (op) { + .eq => std.mem.eql(u8, l, r), + .ne, .not => !std.mem.eql(u8, l, r), + else => false, + }, + else => return false, + }, + else => return false, + } + } };