118 lines
3.1 KiB
C++
118 lines
3.1 KiB
C++
|
#include "stdlib.hpp"
|
||
|
|
||
|
#include "common.hpp"
|
||
|
#include "pod.hpp"
|
||
|
#include "writer.hpp"
|
||
|
|
||
|
typedef Result<Value> (*StdlibFunctionIdPtr)(const Array& params);
|
||
|
|
||
|
struct StdlibFunctionEntry {
|
||
|
const char* name;
|
||
|
StdlibFunctionId fun_id;
|
||
|
StdlibFunctionIdPtr fun_ptr;
|
||
|
};
|
||
|
|
||
|
Result<Value> stdlib_unknown(const Array& params) {
|
||
|
return ERROR(NotImplemented);
|
||
|
}
|
||
|
|
||
|
Result<void> print_string(const String& s) {
|
||
|
auto ba = TRY(ByteArray::create(s));
|
||
|
|
||
|
for (uint64_t i = 0; i < ba.size(); i++) {
|
||
|
std::cout << TRY(ba[i]);
|
||
|
}
|
||
|
|
||
|
return Result<void>();
|
||
|
}
|
||
|
|
||
|
Result<Value> stdlib_print(const Array& params) {
|
||
|
for (uint64_t i = 0; i < params.size(); i++) {
|
||
|
Value param = TRY(params.get(i));
|
||
|
|
||
|
if (i != 0) {
|
||
|
std::cout << " ";
|
||
|
}
|
||
|
if (param.is<String>()) {
|
||
|
TRY(print_string(*param.to<String>()));
|
||
|
} else {
|
||
|
auto s = TRY(write_one(param));
|
||
|
TRY(print_string(s));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Value(TRY(Nil::create()));
|
||
|
}
|
||
|
|
||
|
Result<Value> stdlib_println(const Array& params) {
|
||
|
TRY(stdlib_print(params));
|
||
|
std::cout << "\n";
|
||
|
|
||
|
return Value(TRY(Nil::create()));
|
||
|
}
|
||
|
|
||
|
Result<Value> stdlib_prn(const Array& params) { return ERROR(NotImplemented); }
|
||
|
|
||
|
#define STDLIB_FUNCTION(name, id) \
|
||
|
[(uint64_t)StdlibFunctionId::id] = {#name, StdlibFunctionId::id, \
|
||
|
stdlib_##name}
|
||
|
|
||
|
static StdlibFunctionEntry function_entries[] = {
|
||
|
STDLIB_FUNCTION(unknown, Unknown),
|
||
|
STDLIB_FUNCTION(print, Print),
|
||
|
STDLIB_FUNCTION(println, PrintLn),
|
||
|
STDLIB_FUNCTION(prn, Prn),
|
||
|
[(uint64_t)StdlibFunctionId::Max] = {0, StdlibFunctionId::Max,
|
||
|
stdlib_unknown},
|
||
|
};
|
||
|
|
||
|
// TODO: this just scans through the array of functions linearly every time.
|
||
|
// It doesn't have much effect at runtime, because such lookup is likely to
|
||
|
// happen on compile-time only. But anyway, this is worth speeding up
|
||
|
// eventually.
|
||
|
StdlibFunctionEntry get_function_entry(const char* name) {
|
||
|
for (uint64_t i = 1; i < (uint64_t)StdlibFunctionId::Max; i++) {
|
||
|
if (strcmp(function_entries[i].name, name) == 0) {
|
||
|
return function_entries[i];
|
||
|
}
|
||
|
}
|
||
|
return function_entries[(uint64_t)StdlibFunctionId::Unknown];
|
||
|
}
|
||
|
|
||
|
Result<StdlibFunctionId> get_stdlib_function(const Symbol& name) {
|
||
|
const uint64_t bufsize = 256;
|
||
|
char buf[bufsize];
|
||
|
if (name.size() + 1 > bufsize) {
|
||
|
return ERROR(KeyError);
|
||
|
}
|
||
|
|
||
|
for (uint64_t i = 0; i < name.size(); i++) {
|
||
|
buf[i] = (char)TRY(name[i]);
|
||
|
}
|
||
|
buf[name.size()] = 0;
|
||
|
|
||
|
StdlibFunctionId fun_id = get_function_entry(buf).fun_id;
|
||
|
if (fun_id == StdlibFunctionId::Unknown) {
|
||
|
return ERROR(KeyError);
|
||
|
}
|
||
|
|
||
|
return fun_id;
|
||
|
}
|
||
|
|
||
|
Result<Value> call_stdlib_function(StdlibFunctionId fun_id,
|
||
|
const Array& params) {
|
||
|
if (fun_id == StdlibFunctionId(0) || fun_id >= StdlibFunctionId::Max) {
|
||
|
return ERROR(KeyError);
|
||
|
}
|
||
|
|
||
|
return function_entries[(uint64_t)fun_id].fun_ptr(params);
|
||
|
}
|
||
|
|
||
|
Result<const char*> get_stdlib_function_name(StdlibFunctionId fun_id) {
|
||
|
if (fun_id == StdlibFunctionId(0) || fun_id >= StdlibFunctionId::Max) {
|
||
|
return ERROR(KeyError);
|
||
|
}
|
||
|
|
||
|
return function_entries[(uint64_t)fun_id].name;
|
||
|
}
|