Merge branch 'mcode' into newsyn

This commit is contained in:
2026-02-06 02:02:46 -06:00
4 changed files with 143 additions and 169 deletions

View File

@@ -492,7 +492,90 @@ int cell_init(int argc, char **argv)
}
}
/* Check for --mach flag to output machine code JSON */
/* Check for --mcode flag to output MCODE JSON IR */
if (argc >= 3 && strcmp(argv[1], "--mcode") == 0) {
const char *script_or_file = argv[2];
char *script = NULL;
char *allocated_script = NULL;
const char *filename = "<eval>";
struct stat st;
if (stat(script_or_file, &st) == 0 && S_ISREG(st.st_mode)) {
FILE *f = fopen(script_or_file, "r");
if (!f) {
printf("Failed to open file: %s\n", script_or_file);
return 1;
}
allocated_script = malloc(st.st_size + 1);
if (!allocated_script) {
fclose(f);
printf("Failed to allocate memory for script\n");
return 1;
}
size_t read_size = fread(allocated_script, 1, st.st_size, f);
fclose(f);
allocated_script[read_size] = '\0';
script = allocated_script;
filename = script_or_file;
} else {
script = (char *)script_or_file;
}
JSRuntime *rt = JS_NewRuntime();
if (!rt) {
printf("Failed to create JS runtime\n");
free(allocated_script);
return 1;
}
JSContext *ctx = JS_NewContext(rt);
if (!ctx) {
printf("Failed to create JS context\n");
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
char *ast_json = JS_AST(ctx, script, strlen(script), filename);
if (!ast_json) {
printf("Failed to parse AST\n");
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
if (print_json_errors(ast_json)) {
free(ast_json);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
char *mcode_json = JS_Mcode(ctx, ast_json);
free(ast_json);
if (mcode_json) {
if (print_json_errors(mcode_json)) {
free(mcode_json);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
printf("%s\n", mcode_json);
free(mcode_json);
} else {
printf("Failed to generate MCODE\n");
}
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return mcode_json ? 0 : 1;
}
/* Check for --mach flag to dump MACH bytecode */
if (argc >= 3 && strcmp(argv[1], "--mach") == 0) {
const char *script_or_file = argv[2];
char *script = NULL;
@@ -552,113 +635,16 @@ int cell_init(int argc, char **argv)
return 1;
}
char *mach_json = JS_Mach(ctx, ast_json);
JS_DumpMach(ctx, ast_json, JS_NULL);
free(ast_json);
if (mach_json) {
if (print_json_errors(mach_json)) {
free(mach_json);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
printf("%s\n", mach_json);
free(mach_json);
} else {
printf("Failed to generate machine code\n");
}
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return mach_json ? 0 : 1;
return 0;
}
/* Check for --vmcode flag to dump linked register VM bytecode */
if (argc >= 3 && strcmp(argv[1], "--vmcode") == 0) {
const char *script_or_file = argv[2];
char *script = NULL;
char *allocated_script = NULL;
const char *filename = "<eval>";
struct stat st;
if (stat(script_or_file, &st) == 0 && S_ISREG(st.st_mode)) {
FILE *f = fopen(script_or_file, "r");
if (!f) {
printf("Failed to open file: %s\n", script_or_file);
return 1;
}
allocated_script = malloc(st.st_size + 1);
if (!allocated_script) {
fclose(f);
printf("Failed to allocate memory for script\n");
return 1;
}
size_t read_size = fread(allocated_script, 1, st.st_size, f);
fclose(f);
allocated_script[read_size] = '\0';
script = allocated_script;
filename = script_or_file;
} else {
script = (char *)script_or_file;
}
JSRuntime *rt = JS_NewRuntime();
if (!rt) {
printf("Failed to create JS runtime\n");
free(allocated_script);
return 1;
}
JSContext *ctx = JS_NewContext(rt);
if (!ctx) {
printf("Failed to create JS context\n");
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
char *ast_json = JS_AST(ctx, script, strlen(script), filename);
if (!ast_json) {
printf("Failed to parse AST\n");
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
if (print_json_errors(ast_json)) {
free(ast_json);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
char *mach_json = JS_Mach(ctx, ast_json);
free(ast_json);
if (mach_json) {
if (print_json_errors(mach_json)) {
free(mach_json);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
JS_DumpRegisterMach(ctx, mach_json, JS_NULL);
free(mach_json);
} else {
printf("Failed to generate machine code\n");
}
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return mach_json ? 0 : 1;
}
/* Check for --mach-run flag to generate and run machine code through register VM */
/* Check for --mach-run flag to compile and run through MACH VM */
if (argc >= 3 && strcmp(argv[1], "--mach-run") == 0) {
const char *script_or_file = argv[2];
char *script = NULL;
@@ -701,7 +687,6 @@ int cell_init(int argc, char **argv)
return 1;
}
/* Parse to AST */
char *ast_json = JS_AST(ctx, script, strlen(script), filename);
if (!ast_json) {
printf("Failed to parse AST\n");
@@ -719,30 +704,9 @@ int cell_init(int argc, char **argv)
return 1;
}
/* Generate machine code */
char *mach_json = JS_Mach(ctx, ast_json);
JSValue result = JS_RunMach(ctx, ast_json, JS_NULL);
free(ast_json);
if (!mach_json) {
printf("Failed to generate machine code\n");
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
if (print_json_errors(mach_json)) {
free(mach_json);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
free(allocated_script);
return 1;
}
/* Execute through register VM */
JSValue result = JS_IntegrateRegister(ctx, mach_json, JS_NULL);
free(mach_json);
int exit_code = 0;
if (JS_IsException(result)) {
JSValue exc = JS_GetException(ctx);
@@ -753,7 +717,6 @@ int cell_init(int argc, char **argv)
}
exit_code = 1;
} else if (!JS_IsNull(result)) {
/* Print result */
const char *str = JS_ToCString(ctx, result);
if (str) {
printf("%s\n", str);

View File

@@ -453,7 +453,7 @@ typedef struct JSFrameRegister {
Register-Based VM Data Structures
============================================================ */
/* Machine code opcode enum - matches instruction names from JS_Mach output */
/* Machine code opcode enum - matches instruction names from JS_Mcode output */
typedef enum MachOpcode {
MACH_OP_NOP = 0,
/* Constants */
@@ -30741,7 +30741,7 @@ char *JS_Tokenize (JSContext *ctx, const char *source, size_t len, const char *f
}
/* ============================================================
Register-Based Machine Code Generator
MCODE Generator AST to JSON IR
============================================================ */
/* Variable kinds */
@@ -32594,7 +32594,7 @@ static cJSON *mach_gen_program (MachGenState *s, cJSON *ast) {
return result;
}
char *JS_Mach (JSContext *ctx, const char *ast_json) {
char *JS_Mcode (JSContext *ctx, const char *ast_json) {
cJSON *ast = cJSON_Parse (ast_json);
if (!ast) return NULL;
@@ -32633,7 +32633,7 @@ char *JS_Mach (JSContext *ctx, const char *ast_json) {
}
/* ============================================================
Register VM Linker - converts JSON machine code to JSCodeRegister
MACH Linker MCODE to binary bytecode
============================================================ */
/* Opcode name to MachOpcode mapping */
@@ -33189,7 +33189,7 @@ static JSCodeRegister *js_link_mach(JSContext *ctx, const char *mach_json, JSVal
}
/* ============================================================
Register VM Execution Engine
MACH VM register-based bytecode interpreter
============================================================ */
/* Allocate a JSFrameRegister on the GC heap */
@@ -33937,7 +33937,7 @@ done:
}
/* ============================================================
Register VM Public API
MACH Public API
============================================================ */
/* Print a single constant pool value for dump output */
@@ -34275,25 +34275,37 @@ static void dump_register_code(JSContext *ctx, JSCodeRegister *code, int indent)
}
}
/* Dump linked register VM bytecode */
void JS_DumpRegisterMach(JSContext *ctx, const char *mach_json, JSValue env) {
JSCodeRegister *code = js_link_mach(ctx, mach_json, env);
if (!code) {
printf("=== Register VM Bytecode ===\nFailed to link machine code\n=== End Register VM Bytecode ===\n");
/* Dump MACH bytecode to stdout for debugging. Takes AST JSON. */
void JS_DumpMach(JSContext *ctx, const char *ast_json, JSValue env) {
char *mcode_json = JS_Mcode(ctx, ast_json);
if (!mcode_json) {
printf("=== MACH Bytecode ===\nFailed to generate MCODE\n=== End MACH Bytecode ===\n");
return;
}
printf("=== Register VM Bytecode ===\n");
JSCodeRegister *code = js_link_mach(ctx, mcode_json, env);
sys_free(mcode_json);
if (!code) {
printf("=== MACH Bytecode ===\nFailed to link MCODE\n=== End MACH Bytecode ===\n");
return;
}
printf("=== MACH Bytecode ===\n");
dump_register_code(ctx, code, 0);
printf("=== End Register VM Bytecode ===\n");
printf("=== End MACH Bytecode ===\n");
}
/* Link and execute register-based machine code */
JSValue JS_IntegrateRegister(JSContext *ctx, const char *mach_json, JSValue env) {
/* Link the machine code */
JSCodeRegister *code = js_link_mach(ctx, mach_json, env);
/* Compile and execute MACH bytecode. Takes AST JSON. */
JSValue JS_RunMach(JSContext *ctx, const char *ast_json, JSValue env) {
char *mcode_json = JS_Mcode(ctx, ast_json);
if (!mcode_json) {
return JS_ThrowSyntaxError(ctx, "failed to generate MCODE from AST");
}
JSCodeRegister *code = js_link_mach(ctx, mcode_json, env);
sys_free(mcode_json);
if (!code) {
return JS_ThrowSyntaxError(ctx, "failed to link machine code");
return JS_ThrowSyntaxError(ctx, "failed to link MCODE to MACH bytecode");
}
/* Execute the main code */

View File

@@ -1226,19 +1226,18 @@ char *JS_AST (JSContext *ctx, const char *source, size_t len, const char *filena
Returns malloc'd JSON string (caller must free), or NULL on error. */
char *JS_Tokenize (JSContext *ctx, const char *source, size_t len, const char *filename);
/* Generate register-based machine code from AST JSON.
/* Generate MCODE (JSON IR) from AST JSON.
Returns malloc'd JSON string (caller must free), or NULL on error. */
char *JS_Mach (JSContext *ctx, const char *ast_json);
char *JS_Mcode (JSContext *ctx, const char *ast_json);
/* Link and execute register-based machine code.
mach_json: JSON output from JS_Mach
env: stone record for external variable resolution (or JS_NULL)
/* Dump MACH bytecode to stdout for debugging. Takes AST JSON.
Internally generates MCODE and links to binary bytecode. */
void JS_DumpMach (JSContext *ctx, const char *ast_json, JSValue env);
/* Compile and execute MACH bytecode. Takes AST JSON.
Internally generates MCODE and links to binary bytecode.
Returns result of execution, or JS_EXCEPTION on error. */
JSValue JS_IntegrateRegister (JSContext *ctx, const char *mach_json, JSValue env);
/* Dump linked register VM bytecode to stdout for debugging.
Links mach_json and prints the resulting bytecode with resolved labels. */
void JS_DumpRegisterMach (JSContext *ctx, const char *mach_json, JSValue env);
JSValue JS_RunMach (JSContext *ctx, const char *ast_json, JSValue env);
/* Integrate a CellModule with an environment and execute.
Returns callable function value, or JS_EXCEPTION on error. */

View File

@@ -2395,9 +2395,9 @@ TEST(mach_assign_to_const) {
const char *src = "def x = 1; x = 2";
char *ast_json = JS_AST(ctx, src, strlen(src), "<test>");
ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL");
char *mach_json = JS_Mach(ctx, ast_json);
char *mach_json = JS_Mcode(ctx, ast_json);
free(ast_json);
ASSERT_MSG(mach_json != NULL, "JS_Mach returned NULL");
ASSERT_MSG(mach_json != NULL, "JS_Mcode returned NULL");
ASSERT_ERROR_MSG_CONTAINS(mach_json, "cannot assign to constant");
free(mach_json);
return 1;
@@ -2407,9 +2407,9 @@ TEST(mach_assign_to_arg) {
const char *src = "function f(x) { x = 5 }";
char *ast_json = JS_AST(ctx, src, strlen(src), "<test>");
ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL");
char *mach_json = JS_Mach(ctx, ast_json);
char *mach_json = JS_Mcode(ctx, ast_json);
free(ast_json);
ASSERT_MSG(mach_json != NULL, "JS_Mach returned NULL");
ASSERT_MSG(mach_json != NULL, "JS_Mcode returned NULL");
ASSERT_ERROR_MSG_CONTAINS(mach_json, "cannot assign to function argument");
free(mach_json);
return 1;
@@ -2419,9 +2419,9 @@ TEST(mach_redeclare_const) {
const char *src = "def x = 1; def x = 2";
char *ast_json = JS_AST(ctx, src, strlen(src), "<test>");
ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL");
char *mach_json = JS_Mach(ctx, ast_json);
char *mach_json = JS_Mcode(ctx, ast_json);
free(ast_json);
ASSERT_MSG(mach_json != NULL, "JS_Mach returned NULL");
ASSERT_MSG(mach_json != NULL, "JS_Mcode returned NULL");
ASSERT_ERROR_MSG_CONTAINS(mach_json, "cannot redeclare constant");
free(mach_json);
return 1;
@@ -2431,9 +2431,9 @@ TEST(mach_break_outside_loop) {
const char *src = "break";
char *ast_json = JS_AST(ctx, src, strlen(src), "<test>");
ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL");
char *mach_json = JS_Mach(ctx, ast_json);
char *mach_json = JS_Mcode(ctx, ast_json);
free(ast_json);
ASSERT_MSG(mach_json != NULL, "JS_Mach returned NULL");
ASSERT_MSG(mach_json != NULL, "JS_Mcode returned NULL");
ASSERT_ERROR_MSG_CONTAINS(mach_json, "outside of loop");
free(mach_json);
return 1;
@@ -2443,9 +2443,9 @@ TEST(mach_continue_outside_loop) {
const char *src = "continue";
char *ast_json = JS_AST(ctx, src, strlen(src), "<test>");
ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL");
char *mach_json = JS_Mach(ctx, ast_json);
char *mach_json = JS_Mcode(ctx, ast_json);
free(ast_json);
ASSERT_MSG(mach_json != NULL, "JS_Mach returned NULL");
ASSERT_MSG(mach_json != NULL, "JS_Mcode returned NULL");
ASSERT_ERROR_MSG_CONTAINS(mach_json, "outside of loop");
free(mach_json);
return 1;
@@ -2455,9 +2455,9 @@ TEST(mach_assign_unbound_var) {
const char *src = "x = 42";
char *ast_json = JS_AST(ctx, src, strlen(src), "<test>");
ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL");
char *mach_json = JS_Mach(ctx, ast_json);
char *mach_json = JS_Mcode(ctx, ast_json);
free(ast_json);
ASSERT_MSG(mach_json != NULL, "JS_Mach returned NULL");
ASSERT_MSG(mach_json != NULL, "JS_Mcode returned NULL");
ASSERT_ERROR_MSG_CONTAINS(mach_json, "not declared");
free(mach_json);
return 1;
@@ -2467,9 +2467,9 @@ TEST(mach_shadow_is_ok) {
const char *src = "var array = []; array";
char *ast_json = JS_AST(ctx, src, strlen(src), "<test>");
ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL");
char *mach_json = JS_Mach(ctx, ast_json);
char *mach_json = JS_Mcode(ctx, ast_json);
free(ast_json);
ASSERT_MSG(mach_json != NULL, "JS_Mach returned NULL");
ASSERT_MSG(mach_json != NULL, "JS_Mcode returned NULL");
ASSERT_NO_ERRORS(mach_json);
free(mach_json);
return 1;
@@ -2479,9 +2479,9 @@ TEST(mach_valid_no_errors) {
const char *src = "var x = 1; x = x + 1";
char *ast_json = JS_AST(ctx, src, strlen(src), "<test>");
ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL");
char *mach_json = JS_Mach(ctx, ast_json);
char *mach_json = JS_Mcode(ctx, ast_json);
free(ast_json);
ASSERT_MSG(mach_json != NULL, "JS_Mach returned NULL");
ASSERT_MSG(mach_json != NULL, "JS_Mcode returned NULL");
ASSERT_NO_ERRORS(mach_json);
free(mach_json);
return 1;