diff --git a/src/compiler.zig b/src/compiler.zig index 2aaff70..81fe6be 100644 --- a/src/compiler.zig +++ b/src/compiler.zig @@ -230,9 +230,10 @@ pub const Compiler = struct { } fn string(self: *Compiler) !void { + const lexeme_len = self.parser.previous.lexeme.len; try self.emitConstant(values.ObjVal(try objects.copyString( self.allocator, - self.parser.previous.lexeme, + self.parser.previous.lexeme[1 .. lexeme_len - 1], ))); } diff --git a/src/object.zig b/src/object.zig index 0971fe3..c47cf65 100644 --- a/src/object.zig +++ b/src/object.zig @@ -15,15 +15,23 @@ pub const Object = struct { value: ObjValue, }; +fn createString(allocator: *Allocator, data: []u8) !*Object { + var obj = try allocator.create(Object); + obj.otype = ObjType.String; + obj.value = ObjValue{ .String = data }; + return obj; +} + pub fn copyString(allocator: *Allocator, data: []const u8) !*Object { var str = try allocator.alloc(u8, data.len); std.mem.copy(u8, str, data); - var obj = try allocator.create(Object); - obj.otype = ObjType.String; - obj.value = ObjValue{ .String = str }; + return try createString(allocator, str); +} - return obj; +/// Assumes it can take ownership of the given data. +pub fn takeString(allocator: *Allocator, data: []u8) !*Object { + return try createString(allocator, data); } pub fn printObject(stdout: var, obj: Object) !void { diff --git a/src/vm.zig b/src/vm.zig index 302f371..40c1ac6 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -3,6 +3,7 @@ const chunk = @import("chunk.zig"); const value = @import("value.zig"); const values = value; const compiler = @import("compiler.zig"); +const objects = @import("object.zig"); const Chunk = chunk.Chunk; const Value = value.Value; @@ -124,7 +125,27 @@ pub const VM = struct { } } + fn concatenateStrings(self: *VM) !void { + var b = self.pop().as.Object.value.String; + var a = self.pop().as.Object.value.String; + + var res_str = try std.mem.join( + self.allocator, + "", + [][]u8{ a, b }, + ); + + var val = values.ObjVal(try objects.takeString(self.allocator, res_str)); + try self.push(val); + } + fn doAdd(self: *VM) !void { + if (values.isObjType(self.peek(0), .String) and + values.isObjType(self.peek(1), .String)) + { + return try self.concatenateStrings(); + } + var b = try self.popNum(); var a = try self.popNum(); try self.push(values.NumberVal(a + b));