diff --git a/schema/test b/schema/test index ca397b2..4aece6c 100644 --- a/schema/test +++ b/schema/test @@ -9,3 +9,13 @@ User ( best_friend: User, friends: []User, ) + +ArrayTest ( + array_int: []int, + array_float: []float, + array_str: []str, + array_bool: []bool, + array_date: []date, + array_time: []time, + array_datetime: []datetime, +) diff --git a/src/cli/core.zig b/src/cli/core.zig index 1c39ea2..843e1ea 100644 --- a/src/cli/core.zig +++ b/src/cli/core.zig @@ -27,6 +27,7 @@ schema_engine: SchemaEngine = undefined, thread_engine: ThreadEngine = undefined, pub fn init(allocator: Allocator, potential_main_path: ?[]const u8, potential_schema_path: ?[]const u8) Self { + log.debug("DatabaseEngine Initializing.", .{}); var self = Self{ .allocator = allocator }; self.thread_engine = ThreadEngine.init(self.allocator) catch { @@ -34,12 +35,13 @@ pub fn init(allocator: Allocator, potential_main_path: ?[]const u8, potential_sc self.state = .MissingThreadEngine; return self; }; + log.debug("ThreadEngine initialized.", .{}); const potential_main_path_or_environment_variable = potential_main_path orelse getEnvVariable(self.allocator, "ZIPPONDB_PATH"); if (potential_main_path_or_environment_variable) |main_path| { setLogPath(main_path); - log.info("Found ZIPPONDB_PATH: {s}.", .{main_path}); + log.debug("Found ZIPPONDB_PATH: {s}.", .{main_path}); self.file_engine = FileEngine.init(self.allocator, main_path, self.thread_engine.thread_pool) catch { log.err("Error when init FileEngine", .{}); self.state = .MissingFileEngine; @@ -53,10 +55,11 @@ pub fn init(allocator: Allocator, potential_main_path: ?[]const u8, potential_sc self.state = .MissingSchemaEngine; } else { - log.info("No ZIPPONDB_PATH found.", .{}); + log.debug("No ZIPPONDB_PATH found.", .{}); self.state = .MissingFileEngine; return self; } + log.debug("FileEngine initialized.", .{}); if (self.file_engine.isSchemaFileInDir() and potential_schema_path == null) { const schema_path = std.fmt.bufPrint(&path_buffer, "{s}/schema", .{self.file_engine.path_to_ZipponDB_dir}) catch { @@ -64,7 +67,7 @@ pub fn init(allocator: Allocator, potential_main_path: ?[]const u8, potential_sc return self; }; - log.info("Schema founded in the database directory.", .{}); + log.debug("Schema founded in the database directory.", .{}); self.schema_engine = SchemaEngine.init(self.allocator, schema_path, &self.file_engine) catch |err| { log.err("Error when init SchemaEngine: {any}", .{err}); self.state = .MissingSchemaEngine; @@ -80,13 +83,14 @@ pub fn init(allocator: Allocator, potential_main_path: ?[]const u8, potential_sc self.file_engine.schema_engine = self.schema_engine; self.state = .Ok; + log.debug("SchemaEngine initialized.", .{}); return self; } - log.info("Database don't have any schema yet, trying to add one.", .{}); + if (potential_schema_path == null) log.info("Database don't have any schema yet, trying to add one.", .{}); const potential_schema_path_or_environment_variable = potential_schema_path orelse getEnvVariable(self.allocator, "ZIPPONDB_SCHEMA"); if (potential_schema_path_or_environment_variable) |schema_path| { - log.info("Found schema path {s}.", .{schema_path}); + log.debug("Found schema path {s}.", .{schema_path}); self.schema_engine = SchemaEngine.init(self.allocator, schema_path, &self.file_engine) catch |err| { log.err("Error when init SchemaEngine: {any}", .{err}); self.state = .MissingSchemaEngine; @@ -105,8 +109,9 @@ pub fn init(allocator: Allocator, potential_main_path: ?[]const u8, potential_sc }; self.state = .Ok; + log.debug("SchemaEngine initialized.", .{}); } else { - log.info(config.HELP_MESSAGE.no_schema, .{self.file_engine.path_to_ZipponDB_dir}); + log.debug(config.HELP_MESSAGE.no_schema, .{self.file_engine.path_to_ZipponDB_dir}); } return self; diff --git a/src/dataStructure/filter.zig b/src/dataStructure/filter.zig index fd19a6d..66648b6 100644 --- a/src/dataStructure/filter.zig +++ b/src/dataStructure/filter.zig @@ -312,7 +312,8 @@ pub const Filter = struct { else => unreachable, }, - // TODO: Add stuff to compare array, now condition with value as int, operator as in and to compare as []int should exist + // TODO: Also be able to it for array to array. Like names in ['something'] + // And it is true if at least one value are shared between array. .in => switch (condition.data_type) { .link => condition.value.link.contains(UUID{ .bytes = row_value.UUID }), .int => in(i32, row_value.Int, condition.value.int_array), diff --git a/src/file/core.zig b/src/file/core.zig index e56ec47..9ffc038 100644 --- a/src/file/core.zig +++ b/src/file/core.zig @@ -26,6 +26,7 @@ thread_pool: *Pool, // same pool as the ThreadEngine schema_engine: SchemaEngine = undefined, // This is init after the FileEngine and I attach after. Do I need to init after tho ? pub fn init(allocator: std.mem.Allocator, path: []const u8, thread_pool: *Pool) ZipponError!Self { + log.debug("FileEngine Initializing with path {s}", .{path}); return Self{ .allocator = allocator, .path_to_ZipponDB_dir = std.fmt.bufPrint(&path_to_ZipponDB_dir_buffer, "{s}", .{path}) catch return ZipponError.MemoryError, diff --git a/src/file/write.zig b/src/file/write.zig index 53adbb0..273f8e4 100644 --- a/src/file/write.zig +++ b/src/file/write.zig @@ -148,7 +148,6 @@ fn updateEntitiesOneFile( dir: std.fs.Dir, sync_context: *ThreadSyncContext, ) void { - log.debug("{any}\n", .{@TypeOf(writer)}); var data_buffer: [config.BUFFER_SIZE]u8 = undefined; var fa = std.heap.FixedBufferAllocator.init(&data_buffer); defer fa.reset(); diff --git a/src/schema/core.zig b/src/schema/core.zig index 03b334e..d3bc870 100644 --- a/src/schema/core.zig +++ b/src/schema/core.zig @@ -7,7 +7,7 @@ const Tokenizer = @import("tokenizer.zig").Tokenizer; const Parser = @import("parser.zig").Parser; const ZipponError = @import("error").ZipponError; -const log = std.log.scoped(.schemaEngine); +const log = std.log.scoped(.schema); /// Manage everything that is relate to the schema /// This include keeping in memory the schema and schema file, and some functions to get like all members of a specific struct. @@ -23,13 +23,13 @@ struct_array: []SchemaStruct, null_terminated: [:0]u8, pub fn init(parent_allocator: Allocator, path: []const u8, file_engine: *FileEngine) ZipponError!Self { + log.debug("SchemaEngine Initializing with path {s}", .{path}); const arena = parent_allocator.create(std.heap.ArenaAllocator) catch return ZipponError.MemoryError; + errdefer arena.deinit(); arena.* = std.heap.ArenaAllocator.init(parent_allocator); const allocator = arena.allocator(); var buffer: [config.BUFFER_SIZE]u8 = undefined; - - log.debug("Trying to init a SchemaEngine with path {s}", .{path}); const len: usize = try FileEngine.readSchemaFile(path, &buffer); const null_terminated = std.fmt.bufPrintZ(&schema_buffer, "{s}", .{buffer[0..len]}) catch return ZipponError.MemoryError; @@ -57,6 +57,7 @@ pub fn init(parent_allocator: Allocator, path: []const u8, file_engine: *FileEng } pub fn deinit(self: *Self) void { + log.debug("Deinit SchemaEngine.", .{}); const parent_allocator = self.arena.child_allocator; self.arena.deinit(); parent_allocator.destroy(self.arena); diff --git a/src/test.zig b/src/test.zig index eb69c34..0696ff5 100644 --- a/src/test.zig +++ b/src/test.zig @@ -27,23 +27,26 @@ test "Clear" { try testParsing(db, "DELETE User {}"); } +// Basic +// =============================================================== + test "ADD" { const db = DB{ .path = "test1", .schema = "schema/test" }; try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=55, scores=[ 1 ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45)"); - try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=55, scores=[ 666 123 331 ], best_friend=none, friends=none, bday=2000/11/01, a_time=12:04:54, last_order=2000/01/01-12:45)"); + try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=55, scores=[ 666, 123, 331 ], best_friend=none, friends=none, bday=2000/11/01, a_time=12:04:54, last_order=2000/01/01-12:45)"); try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=-55, scores=[ 33 ], best_friend=none, friends=none, bday=2000/01/04, a_time=12:04:54.8741, last_order=2000/01/01-12:45)"); try testParsing(db, "ADD User (name = 'Boba', email='boba@email.com', age=20, scores=[ ], best_friend=none, friends=none, bday=2000/06/06, a_time=04:04:54.8741, last_order=2000/01/01-12:45)"); - try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=-55, scores=[ 1 ], best_friend={name='Bob'}, friends=none, bday=2000/01/01, a_time=12:04:54.8741, last_order=2000/01/01-12:45)"); - try testParsing(db, "ADD User (name = 'Bou', email='bob@email.com', age=66, scores=[ 1 ], best_friend={name = 'Boba'}, friends={name = 'Bob'}, bday=2000/01/01, a_time=02:04:54.8741, last_order=2000/01/01-12:45)"); - try testParsing(db, "ADD User (name = 'Bobibou', email='bob@email.com', age=66, scores=[ 1 ], best_friend={name = 'Boba'}, friends=[1]{name = 'Bob'}, bday=2000/01/01, a_time=02:04:54.8741, last_order=2000/01/01-12:45)"); + try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=-55, scores=[ 1, ], best_friend={name='Bob'}, friends=none, bday=2000/01/01, a_time=12:04:54.8741, last_order=2000/01/01-12:45)"); + try testParsing(db, "ADD User (name = 'Bou', email='bob@email.com', age=66, scores=[ 1, ], best_friend={name = 'Boba'}, friends={name = 'Bob'}, bday=2000/01/01, a_time=02:04:54.8741, last_order=2000/01/01-12:45)"); + try testParsing(db, "ADD User (name = 'Bobibou', email='bob@email.com', age=66, scores=[ 1, ], best_friend={name = 'Boba'}, friends=[1]{name = 'Bob'}, bday=2000/01/01, a_time=02:04:54.8741, last_order=2000/01/01-12:45)"); try testParsing(db, "GRAB User {}"); } test "ADD batch" { const db = DB{ .path = "test1", .schema = "schema/test" }; - try testParsing(db, "ADD User (name = 'ewq', email='ewq@email.com', age=22, scores=[ ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45) (name = 'Roger', email='roger@email.com', age=10, scores=[ 1 11 111 123 562345 123451234 34623465234 12341234 ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45)"); + try testParsing(db, "ADD User (name = 'ewq', email='ewq@email.com', age=22, scores=[ ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45) (name = 'Roger', email='roger@email.com', age=10, scores=[ 1, 11, 111, 123, 562345, 123451234, 34623465234, 12341234 ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45)"); try testParsing(db, "ADD User (name = 'qwe', email='qwe@email.com', age=57, scores=[ ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45) ('Rodrigo', 'bob@email.com', 55, [ 1 ], {name = 'qwe'}, none, 2000/01/01, 12:04, 2000/01/01-12:45)"); try testParsing(db, "GRAB User [name, best_friend] {name = 'Rodrigo'}"); @@ -93,6 +96,17 @@ test "Specific query" { try testParsing(db, "GRAB User [1]"); } +// Array manipulation +// =============================================================== + +test "GRAB name IN" { + const db = DB{ .path = "test1", .schema = "schema/test" }; + try testParsing(db, "GRAB User {name IN ['Bob', 'Bobinou']}"); +} + +// Single Struct Relationship +// =============================================================== + test "UPDATE relationship" { const db = DB{ .path = "test1", .schema = "schema/test" }; try testParsing(db, "UPDATE User [1] {name='Bob'} TO (best_friend = {name='Boba'} )"); @@ -124,11 +138,6 @@ test "GRAB Relationship AdditionalData Filtered" { try testParsing(db, "GRAB User [2; name, best_friend] {best_friend !IN {}}"); } -test "GRAB name IN" { - const db = DB{ .path = "test1", .schema = "schema/test" }; - try testParsing(db, "GRAB User {name IN ['Bob' 'Bobinou']}"); -} - test "GRAB Relationship dot" { // DO I add this ? I'm not sure about this feature const db = DB{ .path = "test1", .schema = "schema/test" }; @@ -139,11 +148,17 @@ test "GRAB Relationship dot" { try testParsing(db, "GRAB User [1] {}"); } +// Cleaning +// =============================================================== + test "DELETE" { const db = DB{ .path = "test1", .schema = "schema/test" }; try testParsing(db, "DELETE User {}"); } +// 3 Struct Relationship +// =============================================================== + test "3 struct base" { const db = DB{ .path = "test2", .schema = "schema/test-3struct" }; try testParsing(db, "DELETE User {}"); @@ -172,7 +187,10 @@ test "3 struct both side" { fn testParsing(db: DB, source: [:0]const u8) !void { const allocator = std.testing.allocator; var db_engine = DBEngine.init(allocator, db.path, db.schema); - defer db_engine.deinit(); + defer { + db_engine.deinit(); + std.debug.print("\n\n-------------------------------\n\n", .{}); + } var parser = Parser.init( &db_engine.file_engine, @@ -181,13 +199,15 @@ fn testParsing(db: DB, source: [:0]const u8) !void { std.debug.print("Running: {s}\n", .{source}); try parser.parse(allocator, source); - std.debug.print("\n\n-------------------------------\n\n", .{}); } fn expectParsingError(db: DB, source: [:0]const u8, err: ZipponError) !void { const allocator = std.testing.allocator; var db_engine = DBEngine.init(allocator, db.path, db.schema); - defer db_engine.deinit(); + defer { + db_engine.deinit(); + std.debug.print("\n\n-------------------------------\n\n", .{}); + } var parser = Parser.init( &db_engine.file_engine, @@ -196,5 +216,4 @@ fn expectParsingError(db: DB, source: [:0]const u8, err: ZipponError) !void { std.debug.print("Running: {s}\n", .{source}); try std.testing.expectError(err, parser.parse(allocator, source)); - std.debug.print("\n\n-------------------------------\n\n", .{}); } diff --git a/src/test_runner.zig b/src/test_runner.zig index c107860..3c4e1f3 100644 --- a/src/test_runner.zig +++ b/src/test_runner.zig @@ -16,9 +16,8 @@ pub fn myLog( comptime format: []const u8, args: anytype, ) void { - _ = message_level; _ = scope; - if (true) { + if (message_level == .debug) { std.debug.print(format, args); std.debug.print("\n", .{}); } diff --git a/src/thread/engine.zig b/src/thread/engine.zig index a5195de..5156dc8 100644 --- a/src/thread/engine.zig +++ b/src/thread/engine.zig @@ -8,18 +8,20 @@ const log = std.log.scoped(.thread); pub const ThreadEngine = @This(); +allocator: std.mem.Allocator, thread_arena: *std.heap.ThreadSafeAllocator, thread_pool: *Pool, pub fn init(allocator: std.mem.Allocator) !ThreadEngine { + log.debug("ThreadEngine Initializing.", .{}); const thread_arena = try allocator.create(std.heap.ThreadSafeAllocator); thread_arena.* = std.heap.ThreadSafeAllocator{ .child_allocator = allocator, }; const cpu_core = if (CPU_CORE == 0) std.Thread.getCpuCount() catch 1 else CPU_CORE; - log.info("Using {d} cpu core", .{cpu_core}); - log.info("Using {d}Mb stack size", .{std.Thread.SpawnConfig.default_stack_size / 1024 / 1024}); + log.debug(" Using {d} cpu core.", .{cpu_core}); + log.debug(" Using {d}Mb stack size.", .{std.Thread.SpawnConfig.default_stack_size / 1024 / 1024}); const thread_pool = try allocator.create(std.Thread.Pool); try thread_pool.init(std.Thread.Pool.Options{ @@ -28,23 +30,25 @@ pub fn init(allocator: std.mem.Allocator) !ThreadEngine { }); return ThreadEngine{ + .allocator = allocator, .thread_pool = thread_pool, .thread_arena = thread_arena, }; } pub fn deinit(self: *ThreadEngine) void { - const parent_allocator = self.thread_arena.allocator(); + log.debug("Deinit ThreadEngine.", .{}); self.thread_pool.deinit(); - parent_allocator.destroy(self.thread_arena); - parent_allocator.destroy(self.thread_pool); + self.allocator.destroy(self.thread_arena); + self.allocator.destroy(self.thread_pool); } // Not tested, for later when config is runtime pub fn setCpuCore(self: *ThreadEngine, cpu_core: usize) void { + log.debug("Set CPU count to {d}.", .{cpu_core}); self.thread_pool.deinit(); self.thread_pool.init(std.Thread.Pool.Options{ - .allocator = self.thread_arena.allocator(), + .allocator = self.allocator, .n_jobs = cpu_core, }); } diff --git a/src/ziql/parts/condition.zig b/src/ziql/parts/condition.zig index d9b6f1f..fb4efcc 100644 --- a/src/ziql/parts/condition.zig +++ b/src/ziql/parts/condition.zig @@ -71,7 +71,12 @@ pub fn parseCondition( .expect_operation => { condition.operation = try self.parseComparisonOperator(token); - if (condition.operation == .in) condition.data_type = switch (condition.data_type) { + state = .expect_value; + }, + + .expect_value => { + var data_type = condition.data_type; + if (condition.operation == .in) data_type = switch (condition.data_type) { .int => .int_array, .float => .float_array, .str => .str_array, @@ -79,14 +84,11 @@ pub fn parseCondition( .date => .date_array, .time => .time_array, .datetime => .datetime_array, - else => condition.data_type, + .link, .link_array => data_type, + else => unreachable, }; - log.debug("Condition operation {any}\n", .{condition.operation}); - state = .expect_value; - }, - .expect_value => { - condition.value = try self.parseConditionValue(allocator, struct_name, member_name, condition.data_type, &token); + condition.value = try self.parseConditionValue(allocator, struct_name, member_name, data_type, &token); state = .end; }, @@ -171,12 +173,12 @@ pub fn checkConditionValidity( }, .in => switch (condition.data_type) { - .link, .int_array, .float_array, .str_array, .bool_array, .time_array, .date_array, .datetime_array => {}, + .link, .int, .float, .str, .bool, .time, .date, .datetime => {}, else => unreachable, }, .not_in => switch (condition.data_type) { - .link, .int_array, .float_array, .str_array, .bool_array, .time_array, .date_array, .datetime_array => {}, + .link, .int, .float, .str, .bool, .time, .date, .datetime => {}, else => unreachable, }, } diff --git a/src/ziql/parts/value.zig b/src/ziql/parts/value.zig index f6ae922..65b6b28 100644 --- a/src/ziql/parts/value.zig +++ b/src/ziql/parts/value.zig @@ -35,7 +35,7 @@ pub fn parseConditionValue( ) ZipponError!ConditionValue { const start_index = token.loc.start; - if (data_type.is_array()) switch (token.tag) { + if (data_type.is_array() and data_type != .link_array) switch (token.tag) { .l_bracket => token.* = self.toker.next(), else => return printError( "Error: expecting [ to start array.", @@ -150,14 +150,16 @@ pub fn parseConditionValue( token.* = self.toker.next(); } else first = false; - if (token.tag != .int_literal) return printError( + if (token.tag == .int_literal) array.append(s2t.parseInt(self.toker.getTokenSlice(token.*))) catch return ZipponError.MemoryError; + if (token.tag == .int_literal or token.tag == .comma) continue; + if (token.tag == .r_bracket) break; + return printError( "Error: Wrong type. Expected int.", ZipponError.SynthaxError, self.toker.buffer, token.loc.start, token.loc.end, ); - array.append(s2t.parseInt(self.toker.getTokenSlice(token.*))) catch return ZipponError.MemoryError; } return try ConditionValue.initArrayInt(array.toOwnedSlice() catch return ZipponError.MemoryError); @@ -180,14 +182,16 @@ pub fn parseConditionValue( token.* = self.toker.next(); } else first = false; - if (token.tag != .float_literal) return printError( + if (token.tag == .float_literal) array.append(s2t.parseFloat(self.toker.getTokenSlice(token.*))) catch return ZipponError.MemoryError; + if (token.tag == .float_literal or token.tag == .comma) continue; + if (token.tag == .r_bracket) break; + return printError( "Error: Wrong type. Expected float.", ZipponError.SynthaxError, self.toker.buffer, token.loc.start, token.loc.end, ); - array.append(s2t.parseFloat(self.toker.getTokenSlice(token.*))) catch return ZipponError.MemoryError; } return try ConditionValue.initArrayFloat(array.toOwnedSlice() catch return ZipponError.MemoryError); @@ -210,14 +214,16 @@ pub fn parseConditionValue( token.* = self.toker.next(); } else first = false; - if (token.tag != .bool_literal_false and token.tag != .bool_literal_true) return printError( + if (token.tag == .bool_literal_false or token.tag == .bool_literal_false) array.append(s2t.parseBool(self.toker.getTokenSlice(token.*))) catch return ZipponError.MemoryError; + if (token.tag == .bool_literal_false or token.tag == .bool_literal_false or token.tag == .comma) continue; + if (token.tag == .r_bracket) break; + return printError( "Error: Wrong type. Expected bool.", ZipponError.SynthaxError, self.toker.buffer, token.loc.start, token.loc.end, ); - array.append(s2t.parseBool(self.toker.getTokenSlice(token.*))) catch return ZipponError.MemoryError; } return try ConditionValue.initArrayBool(array.toOwnedSlice() catch return ZipponError.MemoryError); @@ -240,14 +246,16 @@ pub fn parseConditionValue( token.* = self.toker.next(); } else first = false; - if (token.tag != .string_literal) return printError( + if (token.tag == .string_literal) array.append(self.toker.getTokenSlice(token.*)) catch return ZipponError.MemoryError; + if (token.tag == .string_literal or token.tag == .comma) continue; + if (token.tag == .r_bracket) break; + return printError( "Error: Wrong type. Expected str.", ZipponError.SynthaxError, self.toker.buffer, token.loc.start, token.loc.end, ); - array.append(self.toker.getTokenSlice(token.*)) catch return ZipponError.MemoryError; } return try ConditionValue.initArrayStr(array.toOwnedSlice() catch return ZipponError.MemoryError); @@ -270,14 +278,16 @@ pub fn parseConditionValue( token.* = self.toker.next(); } else first = false; - if (token.tag != .date_literal and token.tag != .keyword_now) return printError( + if (token.tag == .date_literal or token.tag == .keyword_now) array.append(s2t.parseDate(self.toker.getTokenSlice(token.*)).toUnix()) catch return ZipponError.MemoryError; + if (token.tag == .date_literal or token.tag == .keyword_now or token.tag == .comma) continue; + if (token.tag == .r_bracket) break; + return printError( "Error: Wrong type. Expected date.", ZipponError.SynthaxError, self.toker.buffer, token.loc.start, token.loc.end, ); - array.append(s2t.parseDate(self.toker.getTokenSlice(token.*)).toUnix()) catch return ZipponError.MemoryError; } return try ConditionValue.initArrayUnix(array.toOwnedSlice() catch return ZipponError.MemoryError); @@ -300,14 +310,16 @@ pub fn parseConditionValue( token.* = self.toker.next(); } else first = false; - if (token.tag != .time_literal and token.tag != .keyword_now) return printError( + if (token.tag == .time_literal or token.tag == .keyword_now) array.append(s2t.parseTime(self.toker.getTokenSlice(token.*)).toUnix()) catch return ZipponError.MemoryError; + if (token.tag == .time_literal or token.tag == .keyword_now or token.tag == .comma) continue; + if (token.tag == .r_bracket) break; + return printError( "Error: Wrong type. Expected time.", ZipponError.SynthaxError, self.toker.buffer, token.loc.start, token.loc.end, ); - array.append(s2t.parseTime(self.toker.getTokenSlice(token.*)).toUnix()) catch return ZipponError.MemoryError; } return try ConditionValue.initArrayUnix(array.toOwnedSlice() catch return ZipponError.MemoryError); @@ -330,14 +342,16 @@ pub fn parseConditionValue( token.* = self.toker.next(); } else first = false; - if (token.tag != .datetime_literal and token.tag != .date_literal and token.tag != .keyword_now) return printError( + if (token.tag == .datetime_literal or token.tag == .date_literal or token.tag == .keyword_now) array.append(s2t.parseDatetime(self.toker.getTokenSlice(token.*)).toUnix()) catch return ZipponError.MemoryError; + if (token.tag == .datetime_literal or token.tag == .date_literal or token.tag == .keyword_now or token.tag == .comma) continue; + if (token.tag == .r_bracket) break; + return printError( "Error: Wrong type. Expected datetime.", ZipponError.SynthaxError, self.toker.buffer, token.loc.start, token.loc.end, ); - array.append(s2t.parseDatetime(self.toker.getTokenSlice(token.*)).toUnix()) catch return ZipponError.MemoryError; } return try ConditionValue.initArrayUnix(array.toOwnedSlice() catch return ZipponError.MemoryError);