Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/wapython
Path: blob/main/python/python-wasm/src/python.zig
1067 views
1
const std = @import("std");
2
const py = @cImport(@cInclude("Python.h"));
3
const signal = @import("./signal.zig");
4
5
export fn keepalive() void {
6
signal.keepalive();
7
}
8
9
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
10
var allocator = gpa.allocator();
11
12
pub const General = error{RuntimeError};
13
const PyObject = py.PyObject;
14
15
var didInit = false;
16
var globals: *PyObject = undefined;
17
export fn cowasm_python_init() c_int {
18
if (didInit) return 0;
19
// std.debug.print("python.init()...\n", .{});
20
py.Py_Initialize();
21
// std.debug.print("success!\n", .{});
22
globals = py.PyDict_New() orelse {
23
return 1;
24
};
25
// Success!
26
didInit = true;
27
return 0;
28
}
29
30
pub fn assertInit() !void {
31
if (!didInit) {
32
std.debug.print("call init() first\n", .{});
33
return General.RuntimeError;
34
}
35
}
36
37
/////////////////////////////////
38
//
39
// Implementation of repr
40
//
41
/////////////////////////////////
42
43
extern fn wasmSendString(ptr: [*]const u8, len: usize) void;
44
45
// TODO: would like to say what the exception actually is. For now, at least inform
46
// that it happened.
47
extern fn wasmSetException() void;
48
49
export fn cowasm_python_repr(s: [*:0]const u8) i32 {
50
const r = repr(s) catch |err| {
51
//todo
52
wasmSetException();
53
std.debug.print("python error: '{}'\nwhen evaluating '{s}'", .{ err, s });
54
return 1;
55
};
56
defer allocator.free(r);
57
// Todo: this r[0..1] is a casting hack -- I think it's harmless
58
// because r itself is null terminated (?).
59
const ptr: [*]const u8 = r[0..1];
60
wasmSendString(ptr, std.mem.len(r));
61
return 0;
62
}
63
64
fn repr(s: [*:0]const u8) ![]u8 {
65
try assertInit();
66
// std.debug.print("eval '{s}'\n", .{s});
67
68
var pstr = py.PyRun_String(s, py.Py_eval_input, globals, globals) orelse {
69
py.PyErr_Clear();
70
std.debug.print("eval -- PyRun_String failed\n", .{});
71
return General.RuntimeError;
72
};
73
defer py.Py_DECREF(pstr);
74
75
var rep = py.PyObject_Repr(pstr) orelse {
76
py.PyErr_Clear();
77
std.debug.print("eval -- PyObject_Repr failed\n", .{});
78
return General.RuntimeError;
79
};
80
defer py.Py_DECREF(rep);
81
// std.debug.print("rep ptr = {*}\n", .{rep});
82
const str_rep = py.PyUnicode_AsUTF8(rep);
83
84
// std.debug.print("str_rep = {s}\n", .{str_rep});
85
return try std.fmt.allocPrint(
86
allocator,
87
"{s}",
88
.{str_rep},
89
);
90
}
91
92
/////////////////////////////////
93
//
94
// Implementation of exec
95
//
96
/////////////////////////////////
97
98
// TODO: If there was an error, there is no way to get the exception information *yet*.
99
fn exec(s: [*:0]const u8) !void {
100
try assertInit();
101
// std.debug.print("exec '{s}'\n", .{s});
102
var pstr = py.PyRun_String(s, py.Py_file_input, globals, globals) orelse {
103
py.PyErr_Clear();
104
// failed - some sort of exception got raised.
105
std.debug.print("failed to run '{s}'\n", .{s});
106
return General.RuntimeError;
107
};
108
// it worked. We don't use the return value for anything.
109
py.Py_DECREF(pstr);
110
}
111
112
export fn cowasm_python_exec(s: [*:0]const u8) i32 {
113
exec(s) catch |err| {
114
//todo
115
wasmSetException();
116
std.debug.print("python error: '{}'\nwhen evaluating '{s}'", .{ err, s });
117
return 1;
118
};
119
return 0;
120
}
121
122
/////////////////////////////////
123
//
124
// Implementation of terminal = running the main function
125
//
126
/////////////////////////////////
127
128
export fn cowasm_python_terminal(argc: i32, argv: [*c][*c]u8) i32 {
129
assertInit() catch |err| {
130
std.debug.print("terminal: must first init python -- {}", .{err});
131
return 1;
132
};
133
// std.debug.print("calling Py_BytesMain()... with argc={}, argv[0]={s} argv[1]={s} inputs\n", .{ argc, argv[0], argv[1] });
134
const r = py.Py_BytesMain(argc, argv);
135
// std.debug.print("Py_BytesMain finished returning r={}\n", .{r});
136
return r;
137
}
138
139