Compiler/AST interpreter: Difference between revisions
Content added Content deleted
Recombinant (talk | contribs) m (→{{header|Zig}}: update to Zig 0.11.0 - casting builtins renaming, fix errors from std library changes) |
|||
Line 7,075: | Line 7,075: | ||
</pre> |
</pre> |
||
{{works with|Zig|0.11.0}} |
|||
To simplify memory allocation management <tt>std.heap.ArenaAllocator</tt> is used in the code below. This allows all an arena's allocations to be freed together with a single call to arena.deinit() |
|||
=={{header|Zig}}== |
=={{header|Zig}}== |
||
<syntaxhighlight lang="zig"> |
<syntaxhighlight lang="zig"> |
||
Line 7,142: | Line 7,144: | ||
.prts => _ = try self.out("{s}", .{(try self.interp(t.left)).?.string}), |
.prts => _ = try self.out("{s}", .{(try self.interp(t.left)).?.string}), |
||
.prti => _ = try self.out("{d}", .{(try self.interp(t.left)).?.integer}), |
.prti => _ = try self.out("{d}", .{(try self.interp(t.left)).?.integer}), |
||
.prtc => _ = try self.out("{c}", .{@ |
.prtc => _ = try self.out("{c}", .{@as(u8, @intCast((try self.interp(t.left)).?.integer))}), |
||
.string => return t.value, |
.string => return t.value, |
||
.integer => return t.value, |
.integer => return t.value, |
||
Line 7,161: | Line 7,163: | ||
fn binOp( |
fn binOp( |
||
self: *Self, |
self: *Self, |
||
func: fn (a: i32, b: i32) i32, |
comptime func: fn (a: i32, b: i32) i32, |
||
a: ?*Tree, |
a: ?*Tree, |
||
b: ?*Tree, |
b: ?*Tree, |
||
Line 7,172: | Line 7,174: | ||
fn less(a: i32, b: i32) i32 { |
fn less(a: i32, b: i32) i32 { |
||
return @ |
return @intFromBool(a < b); |
||
} |
} |
||
fn less_equal(a: i32, b: i32) i32 { |
fn less_equal(a: i32, b: i32) i32 { |
||
return @ |
return @intFromBool(a <= b); |
||
} |
} |
||
fn greater(a: i32, b: i32) i32 { |
fn greater(a: i32, b: i32) i32 { |
||
return @ |
return @intFromBool(a > b); |
||
} |
} |
||
fn greater_equal(a: i32, b: i32) i32 { |
fn greater_equal(a: i32, b: i32) i32 { |
||
return @ |
return @intFromBool(a >= b); |
||
} |
} |
||
fn equal(a: i32, b: i32) i32 { |
fn equal(a: i32, b: i32) i32 { |
||
return @ |
return @intFromBool(a == b); |
||
} |
} |
||
fn not_equal(a: i32, b: i32) i32 { |
fn not_equal(a: i32, b: i32) i32 { |
||
return @ |
return @intFromBool(a != b); |
||
} |
} |
||
fn add(a: i32, b: i32) i32 { |
fn add(a: i32, b: i32) i32 { |
||
Line 7,205: | Line 7,207: | ||
} |
} |
||
fn @"or"(a: i32, b: i32) i32 { |
fn @"or"(a: i32, b: i32) i32 { |
||
return @ |
return @intFromBool((a != 0) or (b != 0)); |
||
} |
} |
||
fn @"and"(a: i32, b: i32) i32 { |
fn @"and"(a: i32, b: i32) i32 { |
||
return @ |
return @intFromBool((a != 0) and (b != 0)); |
||
} |
} |
||
}; |
}; |
||
Line 7,217: | Line 7,219: | ||
const allocator = arena.allocator(); |
const allocator = arena.allocator(); |
||
var arg_it = std.process. |
var arg_it = try std.process.argsWithAllocator(allocator); |
||
_ = |
_ = arg_it.next() orelse unreachable; // program name |
||
const file_name = arg_it.next( |
const file_name = arg_it.next(); |
||
// We accept both files and standard input. |
// We accept both files and standard input. |
||
var file_handle = blk: { |
var file_handle = blk: { |
||
if (file_name) |file_name_delimited| { |
if (file_name) |file_name_delimited| { |
||
const fname: []const u8 = |
const fname: []const u8 = file_name_delimited; |
||
break :blk try std.fs.cwd().openFile(fname, .{}); |
break :blk try std.fs.cwd().openFile(fname, .{}); |
||
} else { |
} else { |
||
Line 7,339: | Line 7,341: | ||
fn loadASTHelper( |
fn loadASTHelper( |
||
allocator: std.mem.Allocator, |
allocator: std.mem.Allocator, |
||
line_it: *std.mem.SplitIterator(u8), |
line_it: *std.mem.SplitIterator(u8, std.mem.DelimiterType.sequence), |
||
string_pool: *std.ArrayList([]const u8), |
string_pool: *std.ArrayList([]const u8), |
||
) LoadASTError!?*Tree { |
) LoadASTError!?*Tree { |