Skip to content

Commit d8b8cd9

Browse files
committed
feat: Introduce initial standard library modules with native C and ProXPL implementations for core functionalities.
1 parent d7b55e4 commit d8b8cd9

25 files changed

Lines changed: 1073 additions & 101 deletions

src/stdlib/collections_native.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// --------------------------------------------------
2+
// Project: ProX Programming Language (ProXPL)
3+
// Author: ProgrammerKR
4+
// Created: 2025-12-25
5+
// Copyright © 2025. ProXentix India Pvt. Ltd. All rights reserved.
6+
// --------------------------------------------------
7+
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <string.h>
11+
12+
#include "../../include/common.h"
13+
#include "../../include/vm.h"
14+
#include "../../include/value.h"
15+
#include "../../include/object.h"
16+
17+
extern VM vm;
18+
19+
// Helper
20+
static void defineModuleFn(ObjModule* module, const char* name, NativeFn function) {
21+
ObjString* nameObj = copyString(name, (int)strlen(name));
22+
push(&vm, OBJ_VAL(nameObj));
23+
push(&vm, OBJ_VAL(newNative(function)));
24+
tableSet(&module->exports, nameObj, peek(&vm, 0));
25+
pop(&vm);
26+
pop(&vm);
27+
}
28+
29+
// Placeholder for future native collection optimization
30+
static Value native_dummy(int argCount, Value* args) {
31+
return NIL_VAL;
32+
}
33+
34+
ObjModule* create_std_collections_module() {
35+
ObjString* name = copyString("std.native.collections", 22);
36+
push(&vm, OBJ_VAL(name));
37+
ObjModule* module = newModule(name);
38+
push(&vm, OBJ_VAL(module));
39+
40+
defineModuleFn(module, "_init", native_dummy);
41+
42+
pop(&vm);
43+
pop(&vm);
44+
return module;
45+
}

src/stdlib/fs_native.c

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdio.h>
99
#include <stdlib.h>
1010
#include <string.h>
11+
#include <sys/stat.h>
1112

1213
#include "../../include/common.h"
1314
#include "../../include/vm.h"
@@ -29,11 +30,11 @@ static void defineModuleFn(ObjModule* module, const char* name, NativeFn functio
2930
}
3031

3132
// --------------------------------------------------
32-
// std.fs Implementation
33+
// std.native.fs Implementation
3334
// --------------------------------------------------
3435

35-
// readFile(path) -> String or Null
36-
static Value fs_readFile(int argCount, Value* args) {
36+
// read_file(path) -> String or Null
37+
static Value fs_read_file(int argCount, Value* args) {
3738
if (argCount < 1 || !IS_STRING(args[0])) return NIL_VAL;
3839

3940
const char* path = AS_CSTRING(args[0]);
@@ -54,12 +55,11 @@ static Value fs_readFile(int argCount, Value* args) {
5455
buffer[bytesRead] = '\0';
5556
fclose(file);
5657

57-
Value result = OBJ_VAL(takeString(buffer, (int)bytesRead));
58-
return result;
58+
return OBJ_VAL(takeString(buffer, (int)bytesRead));
5959
}
6060

61-
// writeFile(path, content) -> Bool
62-
static Value fs_writeFile(int argCount, Value* args) {
61+
// write_file(path, content) -> Bool
62+
static Value fs_write_file(int argCount, Value* args) {
6363
if (argCount < 2 || !IS_STRING(args[0]) || !IS_STRING(args[1])) return BOOL_VAL(false);
6464

6565
const char* path = AS_CSTRING(args[0]);
@@ -72,27 +72,63 @@ static Value fs_writeFile(int argCount, Value* args) {
7272
return BOOL_VAL(true);
7373
}
7474

75+
// append_file(path, content) -> Bool
76+
static Value fs_append_file(int argCount, Value* args) {
77+
if (argCount < 2 || !IS_STRING(args[0]) || !IS_STRING(args[1])) return BOOL_VAL(false);
78+
79+
const char* path = AS_CSTRING(args[0]);
80+
FILE* file = fopen(path, "a");
81+
if (!file) return BOOL_VAL(false);
82+
83+
ObjString* content = AS_STRING(args[1]);
84+
fwrite(content->chars, 1, content->length, file);
85+
fclose(file);
86+
return BOOL_VAL(true);
87+
}
88+
7589
// exists(path) -> Bool
7690
static Value fs_exists(int argCount, Value* args) {
7791
if (argCount < 1 || !IS_STRING(args[0])) return BOOL_VAL(false);
7892

79-
FILE* file = fopen(AS_CSTRING(args[0]), "r");
80-
if (file) {
81-
fclose(file);
82-
return BOOL_VAL(true);
93+
struct stat buffer;
94+
return BOOL_VAL(stat(AS_CSTRING(args[0]), &buffer) == 0);
95+
}
96+
97+
// remove(path) -> Bool
98+
static Value fs_remove(int argCount, Value* args) {
99+
if (argCount < 1 || !IS_STRING(args[0])) return BOOL_VAL(false);
100+
return BOOL_VAL(remove(AS_CSTRING(args[0])) == 0);
101+
}
102+
103+
// metadata(path) -> Map { "size": int, "exists": bool }
104+
// Note: Returning a map implies we can create one. If VM doesn't expose map creation easily here,
105+
// we might iterate. For now, let's just return size as integer or -1 if not found.
106+
// Or if the VM has native map support exposed.
107+
// Assuming `newMap` or similar is not easily available without including more headers,
108+
// I'll stick to returning file size for now or NIL.
109+
// Wait, libraries usually return objects. I'll return the size (number).
110+
static Value fs_metadata(int argCount, Value* args) {
111+
if (argCount < 1 || !IS_STRING(args[0])) return NIL_VAL;
112+
113+
struct stat st;
114+
if (stat(AS_CSTRING(args[0]), &st) == 0) {
115+
return NUMBER_VAL((double)st.st_size);
83116
}
84-
return BOOL_VAL(false);
117+
return NIL_VAL;
85118
}
86119

87120
ObjModule* create_std_fs_module() {
88-
ObjString* name = copyString("std.fs", 6);
121+
ObjString* name = copyString("std.native.fs", 13);
89122
push(&vm, OBJ_VAL(name));
90123
ObjModule* module = newModule(name);
91124
push(&vm, OBJ_VAL(module));
92125

93-
defineModuleFn(module, "readFile", fs_readFile);
94-
defineModuleFn(module, "writeFile", fs_writeFile);
126+
defineModuleFn(module, "read_file", fs_read_file);
127+
defineModuleFn(module, "write_file", fs_write_file);
128+
defineModuleFn(module, "append_file", fs_append_file);
95129
defineModuleFn(module, "exists", fs_exists);
130+
defineModuleFn(module, "remove", fs_remove);
131+
defineModuleFn(module, "metadata", fs_metadata); // Currently returns size
96132

97133
pop(&vm);
98134
pop(&vm);

src/stdlib/hash_native.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// --------------------------------------------------
2+
// Project: ProX Programming Language (ProXPL)
3+
// Author: ProgrammerKR
4+
// Created: 2025-12-25
5+
// Copyright © 2025. ProXentix India Pvt. Ltd. All rights reserved.
6+
// --------------------------------------------------
7+
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <string.h>
11+
12+
#include "../../include/common.h"
13+
#include "../../include/vm.h"
14+
#include "../../include/value.h"
15+
#include "../../include/object.h"
16+
17+
extern VM vm;
18+
19+
// Helper
20+
static void defineModuleFn(ObjModule* module, const char* name, NativeFn function) {
21+
ObjString* nameObj = copyString(name, (int)strlen(name));
22+
push(&vm, OBJ_VAL(nameObj));
23+
push(&vm, OBJ_VAL(newNative(function)));
24+
tableSet(&module->exports, nameObj, peek(&vm, 0));
25+
pop(&vm);
26+
pop(&vm);
27+
}
28+
29+
// Simple hash (DJB2) for now unless we link OpenSSL/etc.
30+
static unsigned long djb2(const char *str) {
31+
unsigned long hash = 5381;
32+
int c;
33+
while ((c = *str++))
34+
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
35+
return hash;
36+
}
37+
38+
// md5(str) -> String (Stub/Simple Hash)
39+
static Value native_md5(int argCount, Value* args) {
40+
if (argCount < 1 || !IS_STRING(args[0])) return NIL_VAL;
41+
// Real MD5 requires implementation. Returning a placeholder hash for MVP.
42+
unsigned long h = djb2(AS_CSTRING(args[0]));
43+
char buffer[32];
44+
sprintf(buffer, "%lx", h);
45+
return OBJ_VAL(copyString(buffer, (int)strlen(buffer)));
46+
}
47+
48+
// sha256(str) -> String (Stub)
49+
static Value native_sha256(int argCount, Value* args) {
50+
if (argCount < 1 || !IS_STRING(args[0])) return NIL_VAL;
51+
// Real SHA256 requires implementation.
52+
return native_md5(argCount, args);
53+
}
54+
55+
ObjModule* create_std_hash_module() {
56+
ObjString* name = copyString("std.native.hash", 15);
57+
push(&vm, OBJ_VAL(name));
58+
ObjModule* module = newModule(name);
59+
push(&vm, OBJ_VAL(module));
60+
61+
defineModuleFn(module, "md5", native_md5);
62+
defineModuleFn(module, "sha256", native_sha256);
63+
64+
pop(&vm);
65+
pop(&vm);
66+
return module;
67+
}

src/stdlib/io_native.c

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
// --------------------------------------------------
77

88
/*
9-
* ProXPL Standard Library - I/O Module
10-
* Native C implementation of I/O functions
9+
* ProXPL Standard Library - I/O Module (Native)
10+
* Native C implementation of low-level I/O functions
1111
*/
1212

1313
#include <stdio.h>
@@ -32,22 +32,35 @@ static void defineModuleFn(ObjModule* module, const char* name, NativeFn functio
3232
pop(&vm);
3333
}
3434

35-
// print(...) - Print values to stdout
36-
static Value native_print(int argCount, Value* args) {
37-
for (int i = 0; i < argCount; i++) {
38-
printValue(args[i]);
39-
if (i < argCount - 1) printf(" ");
35+
// print_raw(str) - Print string to stdout without newline
36+
static Value native_print_raw(int argCount, Value* args) {
37+
if (argCount > 0) {
38+
if (IS_STRING(args[0])) {
39+
printf("%s", AS_CSTRING(args[0]));
40+
} else {
41+
printValue(args[0]);
42+
}
4043
}
41-
printf("\n");
4244
return NIL_VAL;
4345
}
4446

45-
// input(prompt) - Read line from stdin
46-
static Value native_input(int argCount, Value* args) {
47+
// eprint_raw(str) - Print string to stderr
48+
static Value native_eprint_raw(int argCount, Value* args) {
4749
if (argCount > 0) {
48-
printValue(args[0]);
50+
if (IS_STRING(args[0])) {
51+
fprintf(stderr, "%s", AS_CSTRING(args[0]));
52+
} else {
53+
// printValue prints to stdout usually, so manual handling might be needed
54+
// For now, just print what we can or rely on printValue if it was flexible
55+
// But let's assume we pass strings primarily
56+
fprintf(stderr, "<value>");
57+
}
4958
}
50-
59+
return NIL_VAL;
60+
}
61+
62+
// input_raw() - Read line from stdin
63+
static Value native_input_raw(int argCount, Value* args) {
5164
char buffer[1024];
5265
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
5366
// Remove newline
@@ -58,21 +71,37 @@ static Value native_input(int argCount, Value* args) {
5871
}
5972
return OBJ_VAL(copyString(buffer, (int)len));
6073
}
61-
6274
return NIL_VAL;
6375
}
6476

77+
// flush_raw() - Flush stdout
78+
static Value native_flush_raw(int argCount, Value* args) {
79+
fflush(stdout);
80+
return NIL_VAL;
81+
}
82+
83+
// set_color_raw(code) - Set terminal color using ANSI
84+
static Value native_set_color_raw(int argCount, Value* args) {
85+
if (argCount > 0 && IS_NUMBER(args[0])) {
86+
int code = (int)AS_NUMBER(args[0]);
87+
printf("\033[%dm", code);
88+
}
89+
return NIL_VAL;
90+
}
6591

6692
// Register all I/O functions with the VM
6793
ObjModule* create_std_io_module() {
68-
ObjString* name = copyString("std.io", 6);
94+
ObjString* name = copyString("std.native.io", 13);
6995
push(&vm, OBJ_VAL(name));
7096
ObjModule* module = newModule(name);
7197
push(&vm, OBJ_VAL(module));
7298

73-
defineModuleFn(module, "print", native_print);
74-
defineModuleFn(module, "input", native_input);
75-
99+
defineModuleFn(module, "print_raw", native_print_raw);
100+
defineModuleFn(module, "eprint_raw", native_eprint_raw);
101+
defineModuleFn(module, "input_raw", native_input_raw);
102+
defineModuleFn(module, "flush_raw", native_flush_raw);
103+
defineModuleFn(module, "set_color_raw", native_set_color_raw);
104+
76105
pop(&vm); // module
77106
pop(&vm); // name
78107
return module;

0 commit comments

Comments
 (0)