refactor: make room for loading and outputting pre-compiled files
This commit is contained in:
parent
3afbbb6ec2
commit
96866ba9ae
11 changed files with 537 additions and 433 deletions
147
src/c_api.zig
147
src/c_api.zig
|
|
@ -1,48 +1,14 @@
|
|||
const std = @import("std");
|
||||
const ink = @import("ink");
|
||||
const Story = ink.Story;
|
||||
const Module = ink.Module;
|
||||
const Compilation = ink.Compilation;
|
||||
const Ast = ink.Ast;
|
||||
const AstGen = ink.AstGen;
|
||||
const Ir = ink.Ir;
|
||||
|
||||
var global_allocator: std.heap.DebugAllocator(.{}) = .init;
|
||||
var stdout_buffer: [4096]u8 align(std.heap.page_size_min) = undefined;
|
||||
|
||||
pub export fn ink_open() callconv(.c) ?*Story {
|
||||
const gpa = global_allocator.allocator();
|
||||
const story = gpa.create(Story) catch |err| switch (err) {
|
||||
error.OutOfMemory => return null,
|
||||
};
|
||||
story.* = .{
|
||||
.gpa = gpa,
|
||||
.arena = .init(gpa),
|
||||
.is_exited = false,
|
||||
.can_advance = false,
|
||||
.stack_top = 0,
|
||||
.call_stack_top = 0,
|
||||
.output_marker = 0,
|
||||
.choice_selected = null,
|
||||
.output_buffer = .empty,
|
||||
.output_scratch = .empty,
|
||||
.current_choices = .empty,
|
||||
.variable_observers = .empty,
|
||||
.globals = .empty,
|
||||
.stack = &.{},
|
||||
.call_stack = &.{},
|
||||
.code_chunks = .empty,
|
||||
.gc_objects = .{},
|
||||
.constants_pool = &.{},
|
||||
.string_bytes = &.{},
|
||||
.dump_writer = null,
|
||||
};
|
||||
return story;
|
||||
}
|
||||
|
||||
pub export fn ink_close(story: *Story) callconv(.c) void {
|
||||
defer _ = global_allocator.deinit();
|
||||
const gpa = story.gpa;
|
||||
story.deinit();
|
||||
gpa.destroy(story);
|
||||
}
|
||||
|
||||
pub const InkLoadOpts = extern struct {
|
||||
filename: [*]const u8,
|
||||
filename_length: usize,
|
||||
|
|
@ -51,61 +17,90 @@ pub const InkLoadOpts = extern struct {
|
|||
flags: i32,
|
||||
};
|
||||
|
||||
fn loadStory(story: *Story, options: *const InkLoadOpts) !void {
|
||||
const gpa = story.gpa;
|
||||
const LoadStoryOptions = struct {
|
||||
filename: []const u8,
|
||||
source_bytes: [:0]const u8,
|
||||
flags: i32,
|
||||
stack_size: usize,
|
||||
error_writer: *std.Io.Writer,
|
||||
};
|
||||
|
||||
fn loadStory(gpa: std.mem.Allocator, options: LoadStoryOptions) !*Story {
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_allocator.deinit();
|
||||
|
||||
const arena = arena_allocator.allocator();
|
||||
const stderr = std.fs.File.stderr();
|
||||
var stderr_writer = stderr.writer(&stdout_buffer);
|
||||
|
||||
var comp = try Module.compile(gpa, arena, .{
|
||||
.source_bytes = options.source_bytes[0..options.source_length :0],
|
||||
.filename = options.filename[0..options.filename_length],
|
||||
.dump_writer = null,
|
||||
.dump_use_color = false,
|
||||
.dump_ast = false,
|
||||
.dump_ir = false,
|
||||
});
|
||||
defer comp.deinit();
|
||||
var tree = try Ast.parse(
|
||||
gpa,
|
||||
arena,
|
||||
options.source_bytes,
|
||||
options.filename,
|
||||
@intCast(options.flags),
|
||||
);
|
||||
defer tree.deinit(gpa);
|
||||
|
||||
if (comp.errors.items.len > 0) {
|
||||
for (comp.errors.items) |err| {
|
||||
try comp.renderError(&stderr_writer.interface, err);
|
||||
var ir = try AstGen.generate(gpa, &tree);
|
||||
defer ir.deinit(gpa);
|
||||
|
||||
var errors: std.ArrayListUnmanaged(Compilation.Error) = .empty;
|
||||
defer errors.deinit(gpa);
|
||||
|
||||
var cu = Compilation.build(gpa, tree, ir, &errors) catch |err| switch (err) {
|
||||
else => |e| return e,
|
||||
};
|
||||
defer cu.deinit();
|
||||
|
||||
if (cu.hasCompileErrors()) {
|
||||
for (cu.errors.items) |err| {
|
||||
try cu.renderError(options.error_writer, err);
|
||||
}
|
||||
return error.LoadFailed;
|
||||
return error.Failed;
|
||||
}
|
||||
|
||||
// TODO: Make this configureable.
|
||||
const stack_size = 128;
|
||||
const eval_stack_ptr = try gpa.alloc(Story.Value, stack_size);
|
||||
errdefer gpa.free(eval_stack_ptr);
|
||||
|
||||
const call_stack_ptr = try gpa.alloc(Story.CallFrame, stack_size);
|
||||
errdefer gpa.free(call_stack_ptr);
|
||||
|
||||
story.can_advance = false;
|
||||
story.stack = eval_stack_ptr;
|
||||
story.call_stack = call_stack_ptr;
|
||||
const story = try gpa.create(Story);
|
||||
errdefer gpa.destroy(story);
|
||||
story.* = .{
|
||||
.gpa = gpa,
|
||||
.arena = .init(gpa),
|
||||
};
|
||||
errdefer story.deinit();
|
||||
|
||||
try comp.setupStoryRuntime(gpa, story);
|
||||
if (story.getKnot(Story.default_knot_name)) |knot| {
|
||||
try story.pushStack(.{ .object = &knot.base });
|
||||
try story.divert(knot, 0);
|
||||
}
|
||||
try Story.Loader.fromCompilationCompat(gpa, &cu, story, .{
|
||||
.stack_size = options.stack_size,
|
||||
});
|
||||
return story;
|
||||
}
|
||||
|
||||
pub export fn ink_load_story_options(
|
||||
story: *Story,
|
||||
options: *const InkLoadOpts,
|
||||
) callconv(.c) c_int {
|
||||
loadStory(story, options) catch |err| {
|
||||
) callconv(.c) ?*Story {
|
||||
const gpa = global_allocator.allocator();
|
||||
const source_bytes = options.source_bytes[0..options.source_length :0];
|
||||
const filename = options.filename[0..options.filename_length :0];
|
||||
const stack_size = 128;
|
||||
const stderr = std.fs.File.stderr();
|
||||
var stderr_writer = stderr.writer(&stdout_buffer);
|
||||
|
||||
return loadStory(gpa, .{
|
||||
.filename = filename,
|
||||
.source_bytes = source_bytes,
|
||||
.flags = options.flags,
|
||||
.error_writer = &stderr_writer.interface,
|
||||
.stack_size = stack_size,
|
||||
}) catch |err| {
|
||||
std.debug.print("{any}\n", .{@errorName(err)});
|
||||
return -1;
|
||||
return null;
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
pub export fn ink_close(optional_story: ?*Story) callconv(.c) void {
|
||||
defer _ = global_allocator.deinit();
|
||||
if (optional_story) |story| {
|
||||
const gpa = story.gpa;
|
||||
story.deinit();
|
||||
gpa.destroy(story);
|
||||
}
|
||||
}
|
||||
|
||||
pub export fn ink_story_can_continue(story: *Story) callconv(.c) bool {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue