added statis map object and used it to implement builtins. Also, new objects File and Directory

This commit is contained in:
cozis
2022-03-10 19:00:30 +01:00
parent 5b097e2b76
commit 8deec027d1
19 changed files with 824 additions and 1045 deletions
+15 -5
View File
@@ -20,6 +20,8 @@ gcc -c src/objects/o_map.c -o temp/objects/o_map.o $FLAGS
gcc -c src/objects/o_list.c -o temp/objects/o_list.o $FLAGS
gcc -c src/objects/o_none.c -o temp/objects/o_none.o $FLAGS
gcc -c src/objects/o_bool.c -o temp/objects/o_bool.o $FLAGS
gcc -c src/objects/o_file.c -o temp/objects/o_file.o $FLAGS
gcc -c src/objects/o_dir.c -o temp/objects/o_dir.o $FLAGS
gcc -c src/objects/o_float.c -o temp/objects/o_float.o $FLAGS
gcc -c src/objects/o_string.c -o temp/objects/o_string.o $FLAGS
gcc -c src/objects/o_buffer.c -o temp/objects/o_buffer.o $FLAGS
@@ -40,8 +42,12 @@ gcc -c src/runtime/runtime.c -o temp/runtime/runtime.o $FLAGS
gcc -c src/runtime/o_nfunc.c -o temp/runtime/o_nfunc.o $FLAGS
gcc -c src/runtime/o_func.c -o temp/runtime/o_func.o $FLAGS
gcc -c src/o_builtins.c -o temp/o_builtins.o $FLAGS
gcc -c src/o_net_builtins.c -o temp/o_net_builtins.o $FLAGS
mkdir temp/builtins
gcc -c src/builtins/basic.c -o temp/builtins/basic.o $FLAGS
gcc -c src/builtins/file.c -o temp/builtins/file.o $FLAGS
gcc -c src/builtins/math.c -o temp/builtins/math.o $FLAGS
gcc -c src/o_staticmap.c -o temp/o_staticmap.o $FLAGS
rm -rf build
mkdir build
@@ -70,8 +76,7 @@ ar rcs build/libnoja-runtime.a \
gcc src/main.c \
src/noja.c \
temp/o_builtins.o \
temp/o_net_builtins.o \
temp/o_staticmap.o \
temp/utils/hash.o \
temp/utils/stack.o \
temp/utils/source.o \
@@ -80,6 +85,8 @@ gcc src/main.c \
temp/objects/o_map.o \
temp/objects/o_none.o \
temp/objects/o_list.o \
temp/objects/o_file.o \
temp/objects/o_dir.o \
temp/objects/o_bool.o \
temp/objects/o_buffer.o \
temp/objects/o_string.o \
@@ -88,7 +95,10 @@ gcc src/main.c \
temp/runtime/runtime_error.o \
temp/runtime/o_nfunc.o \
temp/runtime/o_func.o \
temp/builtins/basic.o \
temp/builtins/file.o \
temp/builtins/math.o \
temp/common/executable.o \
-o build/noja $FLAGS -Lbuild/ -lnoja-compile -lnoja-objects -lxjson
-o build/noja $FLAGS -Lbuild/ -lnoja-compile -lnoja-objects -lxjson -lm
rm -rf temp
+2 -1
View File
@@ -56,8 +56,9 @@ none; # The none value:
there are also other types of values (like functions and buffers) but they'll be covered later.
These type of values, in conjuctions with the operators that are made available by the language, can be used to build arbitrarily complex expressions. The basic arithmetic operators are available:
These type of values, in conjuction with the operators that are made available by the language, can be used to build arbitrarily complex expressions.
The basic arithmetic operators are available:
```py
1 + 1; # 2
1 - 2; # -1
+146
View File
@@ -0,0 +1,146 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "basic.h"
#include "file.h"
#include "math.h"
static Object *bin_print(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
for(int i = 0; i < (int) argc; i += 1)
Object_Print(argv[i], stdout);
return Object_NewNone(Runtime_GetHeap(runtime), error);
}
static Object *bin_type(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
(void) runtime;
(void) error;
return (Object*) argv[0]->type;
}
static Object *bin_count(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
int n = Object_Count(argv[0], error);
if(error->occurred)
return NULL;
return Object_FromInt(n, Runtime_GetHeap(runtime), error);
}
static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
for(unsigned int i = 0; i < argc; i += 1)
if(!Object_ToBool(argv[i], error))
{
if(!error->occurred)
Error_Report(error, 0, "Assertion failed");
return NULL;
}
return Object_NewNone(Runtime_GetHeap(runtime), error);
}
static Object *bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
unsigned int total_count = 0;
for(unsigned int i = 0; i < argc; i += 1)
{
if(!Object_IsString(argv[i]))
{
Error_Report(error, 0, "Argument #%d is not a string", i+1);
return NULL;
}
total_count += Object_Count(argv[i], error);
if(error->occurred)
return NULL;
}
char starting[128];
char *buffer = starting;
if(total_count > sizeof(starting)-1)
{
buffer = malloc(total_count+1);
if(buffer == NULL)
{
Error_Report(error, 1, "No memory");
return NULL;
}
}
Object *result = NULL;
for(unsigned int i = 0, written = 0; i < argc; i += 1)
{
int n;
const char *s;
s = Object_ToString(argv[i], &n, Runtime_GetHeap(runtime), error);
if(error->occurred)
goto done;
memcpy(buffer + written, s, n);
written += n;
}
buffer[total_count] = '\0';
result = Object_FromString(buffer, total_count, Runtime_GetHeap(runtime), error);
done:
if(starting != buffer)
free(buffer);
return result;
}
static Object *bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
long long int size = Object_ToInt(argv[0], error);
if(error->occurred == 1)
return NULL;
return Object_NewBuffer(size, Runtime_GetHeap(runtime), error);
}
static Object *bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 3);
long long int offset = Object_ToInt(argv[1], error);
if(error->occurred == 1) return NULL;
long long int length = Object_ToInt(argv[2], error);
if(error->occurred == 1) return NULL;
return Object_SliceBuffer(argv[0], offset, length, Runtime_GetHeap(runtime), error);
}
const StaticMapSlot bins_basic[] = {
{ "math", SM_SMAP, .as_smap = bins_math, },
{ "file", SM_SMAP, .as_smap = bins_file, },
// { "net", SM_SMAP, .as_smap = bins_net, },
{ "newBuffer", SM_FUNCT, .as_funct = bin_newBuffer, .argc = 1 },
{ "sliceBuffer", SM_FUNCT, .as_funct = bin_sliceBuffer, .argc = 3 },
{ "strcat", SM_FUNCT, .as_funct = bin_strcat },
{ "type", SM_FUNCT, .as_funct = bin_type, .argc = 1 },
{ "print", SM_FUNCT, .as_funct = bin_print, .argc = -1 },
{ "count", SM_FUNCT, .as_funct = bin_count, .argc = 1 },
{ "assert", SM_FUNCT, .as_funct = bin_assert, .argc = -1 },
{ NULL, SM_END, {}, {} },
};
+2
View File
@@ -0,0 +1,2 @@
#include "../o_staticmap.h"
extern const StaticMapSlot bins_basic[];
+278
View File
@@ -0,0 +1,278 @@
#include <assert.h>
#include <errno.h>
#include "file.h"
enum {
MD_READ = 0,
MD_WRITE = 1,
MD_APPEND = 2,
};
static Object *bin_openFile(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 2);
if(!Object_IsString(argv[0]))
{
Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
if(!Object_IsInt(argv[1]))
{
Error_Report(error, 0, "Expected second argument to be an int, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
Heap *heap = Runtime_GetHeap(runtime);
const char *path = Object_ToString(argv[0], NULL, heap, error);
if(error->occurred)
return NULL;
int mode = Object_ToInt(argv[1], error);
if(error->occurred)
return NULL;
FILE *fp;
{
const char *mode2;
switch(mode)
{
case MD_READ:
mode2 = "r";
break;
case MD_READ | MD_WRITE:
mode2 = "w+";
break;
case MD_READ | MD_APPEND:
case MD_READ | MD_WRITE | MD_APPEND:
mode2 = "a";
break;
default:
assert(0);
break;
}
fp = fopen(path, mode2);
if(fp == NULL)
return Object_NewNone(heap, error);
}
return Object_FromStream(fp, heap, error);
}
static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 3);
// Arg 0: file
// Arg 1: buffer
// Arg 2: count
if(!Object_IsFile(argv[0]))
{
Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
if(!Object_IsBuffer(argv[1]))
{
Error_Report(error, 0, "Expected first argument to be a buffer, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
Heap *heap = Runtime_GetHeap(runtime);
void *buff_addr;
int buff_size;
buff_addr = Object_GetBufferAddrAndSize(argv[1], &buff_size, error);
int read_size;
if(Object_IsNone(argv[2]))
{
read_size = buff_size;
}
else if(Object_IsInt(argv[2]))
{
long long int temp = Object_ToInt(argv[2], error);
if(error->occurred)
return NULL;
read_size = temp; // TODO: Handle potential overflow.
if(read_size > buff_size)
read_size = buff_size;
}
else
{
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
FILE *fp = Object_ToStream(argv[0], error);
if(fp == NULL)
return NULL;
size_t n = fread(buff_addr, 1, read_size, fp);
return Object_FromInt(n, heap, error);
}
static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 3);
// Arg 0: file
// Arg 1: buffer
// Arg 2: count
if(!Object_IsFile(argv[0]))
{
Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
if(!Object_IsBuffer(argv[1]))
{
Error_Report(error, 0, "Expected first argument to be a buffer, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
Heap *heap = Runtime_GetHeap(runtime);
void *buff_addr;
int buff_size;
buff_addr = Object_GetBufferAddrAndSize(argv[1], &buff_size, error);
int write_size;
if(Object_IsNone(argv[2]))
{
write_size = buff_size;
}
else if(Object_IsInt(argv[2]))
{
long long int temp = Object_ToInt(argv[2], error);
if(error->occurred)
return NULL;
write_size = temp; // TODO: Handle potential overflow.
if(write_size > buff_size)
write_size = buff_size;
}
else
{
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
FILE *fp = Object_ToStream(argv[0], error);
if(fp == NULL)
return NULL;
size_t n = fwrite(buff_addr, 1, write_size, fp);
return Object_FromInt(n, heap, error);
}
static Object *bin_openDir(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
// Arg 0: path
if(!Object_IsString(argv[0]))
{
Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
Heap *heap = Runtime_GetHeap(runtime);
const char *path = Object_ToString(argv[0], NULL, heap, error);
if(error->occurred)
return NULL;
DIR *dir = opendir(path);
if(dir == NULL)
return Object_NewNone(heap, error);
Object *dob = Object_FromDIR(dir, heap, error);
if(error->occurred)
{
(void) closedir(dir);
return NULL;
}
return dob;
}
static Object *bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
// Arg 0: path
if(!Object_IsDir(argv[0]))
{
Error_Report(error, 0, "Expected first argument to be a directory, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
DIR *dir = Object_ToDIR(argv[0], error);
if(error->occurred)
return NULL;
assert(dir != NULL);
Heap *heap = Runtime_GetHeap(runtime);
errno = 0;
struct dirent *ent = readdir(dir);
if(ent == NULL)
{
if(errno == 0)
// Nothing left to read.
return Object_NewNone(heap, error);
// An error occurred.
Error_Report(error, 1, "Failed to read directory item");
return NULL;
}
return Object_FromString(ent->d_name, -1, heap, error);
}
const StaticMapSlot bins_file[] = {
{ "READ", SM_INT, .as_int = MD_READ, },
{ "WRITE", SM_INT, .as_int = MD_WRITE, },
{ "APPEND", SM_INT, .as_int = MD_APPEND, },
{ "openFile", SM_FUNCT, .as_funct = bin_openFile, .argc = 2, },
{ "openDir", SM_FUNCT, .as_funct = bin_openDir, .argc = 1, },
{ "nextDirItem", SM_FUNCT, .as_funct = bin_nextDirItem, .argc = 1, },
{ "read", SM_FUNCT, .as_funct = bin_read, .argc = 2, },
{ "write", SM_FUNCT, .as_funct = bin_write, .argc = 3, },
{ NULL, SM_END, {}, {} },
};
+2
View File
@@ -0,0 +1,2 @@
#include "../o_staticmap.h"
extern const StaticMapSlot bins_file[];
+94
View File
@@ -0,0 +1,94 @@
#include <assert.h>
#include <math.h>
#include "math.h"
#define WRAP_FUNC(name) \
static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \
{ \
assert(argc == 1); \
\
if(Object_IsFloat(argv[0])) \
{ \
double v = Object_ToFloat(argv[0], error); \
\
if(error->occurred) \
return NULL; \
\
return Object_FromFloat(name(v), Runtime_GetHeap(runtime), error); \
} \
else \
{ \
Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\
return NULL; \
} \
}
#define WRAP_FUNC_2(name) \
static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \
{ \
assert(argc == 2); \
\
if(!Object_IsFloat(argv[0])) \
{ \
Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\
return NULL; \
} \
\
if(!Object_IsFloat(argv[1])) \
{ \
Error_Report(error, 0, "Expected second argument to be a float, but it's a %s", Object_GetName(argv[1]));\
return NULL; \
} \
\
double v1 = Object_ToFloat(argv[0], error); \
\
if(error->occurred) \
return NULL; \
\
double v2 = Object_ToFloat(argv[1], error); \
\
if(error->occurred) \
return NULL; \
\
return Object_FromFloat(name(v1, v2), Runtime_GetHeap(runtime), error); \
}
WRAP_FUNC(ceil)
WRAP_FUNC(floor)
WRAP_FUNC(sin)
WRAP_FUNC(cos)
WRAP_FUNC(tan)
WRAP_FUNC(asin)
WRAP_FUNC(acos)
WRAP_FUNC(atan)
WRAP_FUNC(exp)
WRAP_FUNC(log)
WRAP_FUNC(log10)
WRAP_FUNC(sqrt)
WRAP_FUNC_2(atan2)
WRAP_FUNC_2(pow)
const StaticMapSlot bins_math[] = {
{ "PI", SM_FLOAT, .as_float = M_PI },
{ "E", SM_FLOAT, .as_float = M_E },
{ "floor", SM_FUNCT, .as_funct = bin_floor, .argc = 1, },
{ "ceil", SM_FUNCT, .as_funct = bin_ceil, .argc = 1, },
{ "cos", SM_FUNCT, .as_funct = bin_cos, .argc = 1, },
{ "sin", SM_FUNCT, .as_funct = bin_sin, .argc = 1, },
{ "tan", SM_FUNCT, .as_funct = bin_tan, .argc = 1, },
{ "acos", SM_FUNCT, .as_funct = bin_acos, .argc = 1, },
{ "asin", SM_FUNCT, .as_funct = bin_asin, .argc = 1, },
{ "atan", SM_FUNCT, .as_funct = bin_atan, .argc = 1, },
{ "atan2", SM_FUNCT, .as_funct = bin_atan2, .argc = 2, },
{ "exp", SM_FUNCT, .as_funct = bin_exp, .argc = 1, },
{ "log", SM_FUNCT, .as_funct = bin_log, .argc = 1, },
{ "log10", SM_FUNCT, .as_funct = bin_log10, .argc = 1, },
{ "pow", SM_FUNCT, .as_funct = bin_pow, .argc = 1, },
{ "sqrt", SM_FUNCT, .as_funct = bin_sqrt, .argc = 1, },
{ NULL, SM_END, {}, {} },
};
+2
View File
@@ -0,0 +1,2 @@
#include "../o_staticmap.h"
extern const StaticMapSlot bins_math[];
+3 -2
View File
@@ -2,12 +2,13 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "o_builtins.h"
#include "o_staticmap.h"
#include "compiler/parse.h"
#include "compiler/serialize.h"
#include "compiler/compile.h"
#include "runtime/runtime.h"
#include "runtime/runtime_error.h"
#include "builtins/basic.h"
static const char usage[] =
"Usage:\n"
@@ -207,7 +208,7 @@ static _Bool interpret(Source *src)
RuntimeError error;
RuntimeError_Init(&error, runt); // Here we specify the runtime to snapshot in case of failure.
Object *bins = Object_NewBuiltinsMap(runt, Runtime_GetHeap(runt), (Error*) &error);
Object *bins = Object_NewStaticMap(bins_basic, runt, (Error*) &error);
if(bins == NULL)
{
-256
View File
@@ -1,256 +0,0 @@
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include "runtime/runtime.h"
#include "utils/defs.h"
#include "o_builtins.h"
static Object *select_(Object *self, Object *key, Heap *heap, Error *err);
static Object *bin_type (Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_print (Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_count (Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
typedef struct {
Object base;
Runtime *runtime;
} BuiltinsMapOjbect;
static TypeObject t_builtins_map = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "builtins map",
.size = sizeof(BuiltinsMapOjbect),
.select = select_,
};
static Object *select_(Object *self, Object *key, Heap *heap, Error *err)
{
BuiltinsMapOjbect *bm = (BuiltinsMapOjbect*) self;
if(!Object_IsString(key))
{
Error_Report(err, 0, "Non string key");
return NULL;
}
int n;
const char *s;
s = Object_ToString(key, &n, heap, err);
if(s == NULL)
return NULL;
#define PAIR(p, q) \
(((uint64_t) (p) << 32) | (uint32_t) (q))
switch(PAIR(n, s[0]))
{
case PAIR(4, 't'):
{
if(!strcmp(s, "type"))
return Object_FromNativeFunction(bm->runtime, bin_type, 1, heap, err);
return NULL;
}
case PAIR(sizeof("count")-1, 'c'):
{
if(!strcmp(s, "count"))
return Object_FromNativeFunction(bm->runtime, bin_count, 1, heap, err);
return NULL;
}
case PAIR(sizeof("print")-1, 'p'):
{
if(!strcmp(s, "print"))
return Object_FromNativeFunction(bm->runtime, bin_print, -1, heap, err);
return NULL;
}
case PAIR(sizeof("assert")-1, 'a'):
{
if(!strcmp(s, "assert"))
return Object_FromNativeFunction(bm->runtime, bin_assert, -1, heap, err);
return NULL;
}
case PAIR(sizeof("strcat")-1, 's'):
{
if(!strcmp(s, "strcat"))
return Object_FromNativeFunction(bm->runtime, bin_strcat, -1, heap, err);
return NULL;
}
case PAIR(sizeof("sliceBuffer")-1, 's'):
{
if(!strcmp(s, "sliceBuffer"))
return Object_FromNativeFunction(bm->runtime, bin_sliceBuffer, 3, heap, err);
return NULL;
}
case PAIR(sizeof("net")-1, 'n'):
{
if(!strcmp(s, "net"))
return Object_NewNetworkBuiltinsMap(bm->runtime, heap, err);
return NULL;
}
case PAIR(sizeof("newBuffer")-1, 'n'):
{
if(!strcmp(s, "newBuffer"))
return Object_FromNativeFunction(bm->runtime, bin_newBuffer, 1, heap, err);
return NULL;
}
}
// Not found.
return NULL;
}
Object *Object_NewBuiltinsMap(Runtime *runtime, Heap *heap, Error *err)
{
BuiltinsMapOjbect *bm = (BuiltinsMapOjbect*) Heap_Malloc(heap, &t_builtins_map, err);
if(bm == NULL)
return NULL;
bm->runtime = runtime;
return (Object*) bm;
}
static Object *bin_print(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
for(int i = 0; i < (int) argc; i += 1)
Object_Print(argv[i], stdout);
return Object_NewNone(Runtime_GetHeap(runtime), error);
}
static Object *bin_type(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
(void) runtime;
(void) error;
return (Object*) argv[0]->type;
}
static Object *bin_count(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
int n = Object_Count(argv[0], error);
if(error->occurred)
return NULL;
return Object_FromInt(n, Runtime_GetHeap(runtime), error);
}
static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
if(Object_ToBool(argv[0], error))
{
return Object_NewNone(Runtime_GetHeap(runtime), error);
}
else
{
if(!error->occurred)
Error_Report(error, 0, "Assertion failed");
return NULL;
}
}
static Object *bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
unsigned int total_count = 0;
for(unsigned int i = 0; i < argc; i += 1)
{
if(!Object_IsString(argv[i]))
{
Error_Report(error, 0, "Argument #%d is not a string", i+1);
return NULL;
}
total_count += Object_Count(argv[i], error);
if(error->occurred)
return NULL;
}
char starting[128];
char *buffer = starting;
if(total_count > sizeof(starting)-1)
{
buffer = malloc(total_count+1);
if(buffer == NULL)
{
Error_Report(error, 1, "No memory");
return NULL;
}
}
Object *result = NULL;
for(unsigned int i = 0, written = 0; i < argc; i += 1)
{
int n;
const char *s;
s = Object_ToString(argv[i], &n, Runtime_GetHeap(runtime), error);
if(error->occurred)
goto done;
memcpy(buffer + written, s, n);
written += n;
}
buffer[total_count] = '\0';
result = Object_FromString(buffer, total_count, Runtime_GetHeap(runtime), error);
done:
if(starting != buffer)
free(buffer);
return result;
}
static Object *bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
long long int size = Object_ToInt(argv[0], error);
if(error->occurred == 1)
return NULL;
return Object_NewBuffer(size, Runtime_GetHeap(runtime), error);
}
static Object *bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 3);
long long int offset = Object_ToInt(argv[1], error);
if(error->occurred == 1) return NULL;
long long int length = Object_ToInt(argv[2], error);
if(error->occurred == 1) return NULL;
return Object_SliceBuffer(argv[0], offset, length, Runtime_GetHeap(runtime), error);
}
-3
View File
@@ -1,3 +0,0 @@
#include "runtime/runtime.h"
Object *Object_NewBuiltinsMap(Runtime *runtime, Heap *heap, Error *err);
Object *Object_NewNetworkBuiltinsMap(Runtime *runtime, Heap *heap, Error *err);
-755
View File
@@ -1,755 +0,0 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include "runtime/runtime.h"
#include "utils/defs.h"
static Object *select_(Object *self, Object *key, Heap *heap, Error *err);
static Object *bin_bind(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_listen(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_socket(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_accept(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_connect(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_inet_aton(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_inet_ntoa(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_htonl(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_ntohl(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_htons(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_ntohs(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_send(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
static Object *bin_recv(Runtime *runtime, Object **argv, unsigned int argc, Error *error);
typedef struct {
Object base;
Runtime *runtime;
} NetworkBuiltinsMapOjbect;
static TypeObject t_builtins_map = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "network builtins map",
.size = sizeof(NetworkBuiltinsMapOjbect),
.select = select_,
};
static Object *select_(Object *self, Object *key, Heap *heap, Error *err)
{
NetworkBuiltinsMapOjbect *bm = (NetworkBuiltinsMapOjbect*) self;
if(!Object_IsString(key))
{
Error_Report(err, 0, "Non string key");
return NULL;
}
int n;
const char *s;
s = Object_ToString(key, &n, heap, err);
if(s == NULL)
return NULL;
#define PAIR(p, q) \
(((uint64_t) (p) << 32) | (uint32_t) (q))
switch(PAIR(n, s[0]))
{
case PAIR(4, 's'):
{
if(!strcmp(s, "send"))
return Object_FromNativeFunction(bm->runtime, bin_send, 3, heap, err);
return NULL;
}
case PAIR(4, 'r'):
{
if(!strcmp(s, "recv"))
return Object_FromNativeFunction(bm->runtime, bin_recv, 3, heap, err);
return NULL;
}
case PAIR(10, 'I'):
{
if(!strcmp(s, "INADDR_ANY"))
return Object_FromInt(INADDR_ANY, heap, err);
return NULL;
}
case PAIR(6, 'a'):
{
if(!strcmp(s, "accept"))
return Object_FromNativeFunction(bm->runtime, bin_accept, 2, heap, err);
return NULL;
}
case PAIR(4, 'b'):
{
if(!strcmp(s, "bind"))
return Object_FromNativeFunction(bm->runtime, bin_bind, 2, heap, err);
return NULL;
}
case PAIR(6, 'l'):
{
if(!strcmp(s, "listen"))
return Object_FromNativeFunction(bm->runtime, bin_listen, 2, heap, err);
return NULL;
}
case PAIR(5, 'n'):
{
if(!strcmp(s, "ntohl"))
return Object_FromNativeFunction(bm->runtime, bin_ntohl, 1, heap, err);
if(!strcmp(s, "ntohs"))
return Object_FromNativeFunction(bm->runtime, bin_ntohs, 1, heap, err);
return NULL;
}
case PAIR(5, 'h'):
{
if(!strcmp(s, "htonl"))
return Object_FromNativeFunction(bm->runtime, bin_htonl, 1, heap, err);
if(!strcmp(s, "htons"))
return Object_FromNativeFunction(bm->runtime, bin_htons, 1, heap, err);
return NULL;
}
case PAIR(9, 'i'):
{
if(!strcmp(s, "inet_aton"))
return Object_FromNativeFunction(bm->runtime, bin_inet_aton, 2, heap, err);
if(!strcmp(s, "inet_ntoa"))
return Object_FromNativeFunction(bm->runtime, bin_inet_ntoa, 1, heap, err);
return NULL;
}
case PAIR(6, 's'):
{
if(!strcmp(s, "socket"))
return Object_FromNativeFunction(bm->runtime, bin_socket, 3, heap, err);
return NULL;
}
case PAIR(7, 'c'):
{
if(!strcmp(s, "connect"))
return Object_FromNativeFunction(bm->runtime, bin_connect, 2, heap, err);
return NULL;
}
case PAIR(8, 'S'):
{
if(!strcmp(s, "SOCK_RAW"))
return Object_FromInt(SOCK_RAW, heap, err);
if(!strcmp(s, "SOCK_RDM"))
return Object_FromInt(SOCK_RDM, heap, err);
return NULL;
}
case PAIR(10, 'S'):
{
if(!strcmp(s, "SOCK_DGRAM"))
return Object_FromInt(SOCK_DGRAM, heap, err);
return NULL;
}
case PAIR(11, 'S'):
{
if(!strcmp(s, "SOCK_STREAM"))
return Object_FromInt(SOCK_STREAM, heap, err);
if(!strcmp(s, "SOCK_PACKET"))
return Object_FromInt(SOCK_PACKET, heap, err);
return NULL;
}
case PAIR(12, 'S'):
{
if(!strcmp(s, "SOCK_CLOEXEC"))
return Object_FromInt(SOCK_CLOEXEC, heap, err);
return NULL;
}
case PAIR(13, 'S'):
{
if(!strcmp(s, "SOCK_NONBLOCK"))
return Object_FromInt(SOCK_NONBLOCK, heap, err);
return NULL;
}
case PAIR(14, 'S'):
{
if(!strcmp(s, "SOCK_SEQPACKET"))
return Object_FromInt(SOCK_SEQPACKET, heap, err);
return NULL;
}
case PAIR(5, 'A'):
{
if(s[1] == 'F' && s[2] == '_')
{
if(!strcmp(s+3, "IB"))
return Object_FromInt(AF_IB, heap, err);
}
return NULL;
}
case PAIR(6, 'A'):
{
if(s[1] == 'F' && s[2] == '_')
{
if(!strcmp(s+3, "IPX"))
return Object_FromInt(AF_IPX, heap, err);
if(!strcmp(s+3, "X25"))
return Object_FromInt(AF_X25, heap, err);
if(!strcmp(s+3, "KEY"))
return Object_FromInt(AF_KEY, heap, err);
if(!strcmp(s+3, "RDS"))
return Object_FromInt(AF_RDS, heap, err);
if(!strcmp(s+3, "LLC"))
return Object_FromInt(AF_LLC, heap, err);
if(!strcmp(s+3, "CAN"))
return Object_FromInt(AF_CAN, heap, err);
if(!strcmp(s+3, "ALG"))
return Object_FromInt(AF_ALG, heap, err);
if(!strcmp(s+3, "KCM"))
return Object_FromInt(AF_KCM, heap, err);
if(!strcmp(s+3, "XDP"))
return Object_FromInt(AF_XDP, heap, err);
}
return NULL;
}
case PAIR(7, 'A'):
{
if(s[1] == 'F' && s[2] == '_')
{
if(!strcmp(s+3, "UNIX"))
return Object_FromInt(AF_UNIX, heap, err);
if(!strcmp(s+3, "INET"))
return Object_FromInt(AF_INET, heap, err);
if(!strcmp(s+3, "AX25"))
return Object_FromInt(AF_AX25, heap, err);
if(!strcmp(s+3, "MPLS"))
return Object_FromInt(AF_MPLS, heap, err);
if(!strcmp(s+3, "TIPC"))
return Object_FromInt(AF_TIPC, heap, err);
}
return NULL;
}
case PAIR(8, 'A'):
{
if(s[1] == 'F' && s[2] == '_')
{
if(!strcmp(s+3, "LOCAL"))
return Object_FromInt(AF_LOCAL, heap, err);
if(!strcmp(s+3, "INET6"))
return Object_FromInt(AF_INET6, heap, err);
if(!strcmp(s+3, "PPPOX"))
return Object_FromInt(AF_PPPOX, heap, err);
if(!strcmp(s+3, "VSOCK"))
return Object_FromInt(AF_VSOCK, heap, err);
}
return NULL;
}
case PAIR(9, 'A'):
{
if(s[1] == 'F' && s[2] == '_')
{
if(!strcmp(s+3, "DECnet"))
return Object_FromInt(AF_DECnet, heap, err);
if(!strcmp(s+3, "PACKET"))
return Object_FromInt(AF_PACKET, heap, err);
}
return NULL;
}
case PAIR(10, 'A'):
{
if(s[1] == 'F' && s[2] == '_')
{
if(!strcmp(s+3, "NETLINK"))
return Object_FromInt(AF_NETLINK, heap, err);
}
return NULL;
}
case PAIR(12, 'A'):
{
if(s[1] == 'F' && s[2] == '_')
{
if(!strcmp(s+3, "BLUETOOTH"))
return Object_FromInt(AF_BLUETOOTH, heap, err);
if(!strcmp(s+3, "APPLETALK"))
return Object_FromInt(AF_APPLETALK, heap, err);
}
return NULL;
}
}
// Not found.
return NULL;
}
Object *Object_NewNetworkBuiltinsMap(Runtime *runtime, Heap *heap, Error *err)
{
NetworkBuiltinsMapOjbect *bm = (NetworkBuiltinsMapOjbect*) Heap_Malloc(heap, &t_builtins_map, err);
if(bm == NULL)
return NULL;
bm->runtime = runtime;
return (Object*) bm;
}
static Object *bin_socket(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 3);
int domain, type, protocol;
domain = Object_ToInt(argv[0], error);
if(error->occurred == 1) return NULL;
type = Object_ToInt(argv[1], error);
if(error->occurred == 1) return NULL;
protocol = Object_ToInt(argv[2], error);
if(error->occurred == 1) return NULL;
int fd = socket(domain, type, protocol);
return Object_FromInt(fd, Runtime_GetHeap(runtime), error);
}
static _Bool get_in_addr_from_map(Object *map, struct in_addr *addr, Heap *heap, Error *error)
{
Object *o_key = Object_FromString("s_addr", -1, heap, error);
if(o_key == NULL) return 0;
Object *o_s_addr = Object_Select(map, o_key, heap, error);
if(o_s_addr == NULL)
{
if(error->occurred == 0)
Error_Report(error, 0, "Missing the \"s_addr\" key");
return 0;
}
long long int s_addr = Object_ToInt(o_s_addr, error);
if(error->occurred) return 0;
if(s_addr < 0 || s_addr >= (long long int) ULONG_MAX)
{
Error_Report(error, 0, "s_addr must be in range [0, %lu]", ULONG_MAX);
return 0;
}
if(addr)
addr->s_addr = s_addr;
return 1;
}
static _Bool get_sockaddr_in_from_map(Object *map, struct sockaddr_in *addr, Heap *heap, Error *error)
{
Object *o_key = Object_FromString("sin_family", -1, heap, error);
if(o_key == NULL) return 0;
Object *o_sin_family = Object_Select(map, o_key, heap, error);
if(o_sin_family == NULL)
{
if(error->occurred == 0)
Error_Report(error, 0, "Argument 2 is missing the \"sin_family\" key");
return 0;
}
long long int sin_family = Object_ToInt(o_sin_family, error);
if(error->occurred) return 0;
if(sin_family < 0 || sin_family >= 65536)
{
Error_Report(error, 0, "sin_family must be in range [0, 65535]");
return 0;
}
o_key = Object_FromString("sin_port", -1, heap, error);
if(o_key == NULL) return 0;
Object *o_sin_port = Object_Select(map, o_key, heap, error);
if(o_sin_port == NULL)
{
if(error->occurred == 0)
Error_Report(error, 0, "Argument 2 is missing the \"sin_port\" key");
return 0;
}
long long int sin_port = Object_ToInt(o_sin_port, error);
if(error->occurred) return 0;
if(sin_port < 0 || sin_port >= 65536)
{
Error_Report(error, 0, "sin_port must be in range [0, 65535]");
return 0;
}
o_key = Object_FromString("sin_addr", -1, heap, error);
if(o_key == NULL) return 0;
Object *o_sin_addr = Object_Select(map, o_key, heap, error);
if(o_sin_addr == NULL)
{
if(error->occurred == 0)
Error_Report(error, 0, "Argument 2 is missing the \"sin_addr\" key");
return 0;
}
struct in_addr sin_addr;
if(!get_in_addr_from_map(o_sin_addr, &sin_addr, heap, error))
return 0;
if(addr)
{
memset(addr, 0, sizeof(struct sockaddr_in));
addr->sin_family = sin_family;
addr->sin_port = sin_port;
addr->sin_addr = sin_addr;
}
return 1;
}
static Object *bin_connect(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 2);
Heap *heap = Runtime_GetHeap(runtime);
int sockfd;
struct sockaddr_in addr;
sockfd = Object_ToInt(argv[0], error);
if(error->occurred == 1) return NULL;
if(!get_sockaddr_in_from_map(argv[1], &addr, heap, error))
return NULL;
int r = connect(sockfd, (struct sockaddr*) &addr, sizeof(struct sockaddr_in));
return Object_FromInt(r, Runtime_GetHeap(runtime), error);
}
static Object *bin_inet_aton(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 2);
Heap *heap = Runtime_GetHeap(runtime);
const char *s = Object_ToString(argv[0], NULL, heap, error);
if(s == NULL) return NULL;
// Note that the string must be zero-terminated.
struct in_addr addr;
int r = inet_aton(s, &addr);
if(r != 0)
{
// inet_aton succeded.
Object *o_key = Object_FromString("s_addr", -1, heap, error);
if(o_key == NULL) return NULL;
Object *o_val = Object_FromInt(addr.s_addr, heap, error);
if(o_val == NULL) return NULL;
if(!Object_Insert(argv[1], o_key, o_val, heap, error))
return NULL;
}
return Object_FromInt(r, heap, error);
}
static Object *bin_inet_ntoa(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
Heap *heap = Runtime_GetHeap(runtime);
struct in_addr in_addr;
if(!get_in_addr_from_map(argv[0], &in_addr, heap, error))
return NULL;
const char *addr = inet_ntoa(in_addr);
assert(addr != NULL);
return Object_FromString(addr, -1, heap, error);
}
static Object *bin_htonl(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
Heap *heap = Runtime_GetHeap(runtime);
uint32_t r, p;
p = Object_ToInt(argv[0], error);
if(error->occurred) return NULL;
r = htonl(p);
return Object_FromInt(r, heap, error);
}
static Object *bin_ntohl(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
Heap *heap = Runtime_GetHeap(runtime);
uint32_t r, p;
p = Object_ToInt(argv[0], error);
if(error->occurred) return NULL;
r = ntohl(p);
return Object_FromInt(r, heap, error);
}
static Object *bin_ntohs(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
Heap *heap = Runtime_GetHeap(runtime);
int p = Object_ToInt(argv[0], error);
if(error->occurred) return NULL;
if(p < 0 || p > 65535)
{
Error_Report(error, 0, "Argument is not in range [0, 65535]");
return NULL;
}
uint16_t r = ntohs(p);
return Object_FromInt(r, heap, error);
}
static Object *bin_htons(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 1);
Heap *heap = Runtime_GetHeap(runtime);
int p = Object_ToInt(argv[0], error);
if(error->occurred) return NULL;
if(p < 0 || p > 65535)
{
Error_Report(error, 0, "Argument is not in range [0, 65535]");
return NULL;
}
uint16_t r = htons(p);
return Object_FromInt(r, heap, error);
}
static Object *bin_bind(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 2);
Heap *heap = Runtime_GetHeap(runtime);
int sockfd;
struct sockaddr_in addr;
sockfd = Object_ToInt(argv[0], error);
if(error->occurred) return NULL;
if(!get_sockaddr_in_from_map(argv[1], &addr, heap, error))
return 0;
int r = bind(sockfd, (struct sockaddr*) &addr, sizeof(struct sockaddr_in));
return Object_FromInt(r, heap, error);
}
static Object *bin_listen(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 2);
Heap *heap = Runtime_GetHeap(runtime);
int sockfd, backlog;
sockfd = Object_ToInt(argv[0], error);
if(error->occurred) return NULL;
backlog = Object_ToInt(argv[1], error);
if(error->occurred) return NULL;
int r = listen(sockfd, backlog);
return Object_FromInt(r, heap, error);
}
static Object *bin_accept(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 2);
Heap *heap = Runtime_GetHeap(runtime);
long long int sockfd = Object_ToInt(argv[0], error);
if(error->occurred) return NULL;
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
int r = accept(sockfd, (struct sockaddr*) &addr, &len);
if(r >= 0) {
// accept succeded.
Object *o_key,
*o_sin_family,
*o_sin_addr,
*o_sin_port,
*o_s_addr;
o_sin_family = Object_FromInt(addr.sin_family, heap, error);
if(error->occurred) return NULL;
o_sin_port = Object_FromInt(addr.sin_port, heap, error);
if(error->occurred) return NULL;
o_sin_addr = Object_NewMap(1, heap, error);
if(error->occurred) return NULL;
o_s_addr = Object_FromInt(addr.sin_addr.s_addr, heap, error);
if(error->occurred) return NULL;
o_key = Object_FromString("s_addr", -1, heap, error);
if(error->occurred) return NULL;
if(!Object_Insert(o_sin_addr, o_key, o_s_addr, heap, error))
return NULL;
o_key = Object_FromString("sin_family", -1, heap, error);
if(error->occurred) return NULL;
if(!Object_Insert(argv[1], o_key, o_sin_family, heap, error))
return NULL;
o_key = Object_FromString("sin_port", -1, heap, error);
if(error->occurred) return NULL;
if(!Object_Insert(argv[1], o_key, o_sin_port, heap, error))
return NULL;
o_key = Object_FromString("sin_addr", -1, heap, error);
if(error->occurred) return NULL;
if(!Object_Insert(argv[1], o_key, o_sin_addr, heap, error))
return NULL;
}
return Object_FromInt(r, heap, error);
}
static Object *bin_send(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 3);
Heap *heap = Runtime_GetHeap(runtime);
int sockfd = Object_ToInt(argv[0], error);
if(error->occurred) return NULL;
int size;
void *addr = Object_GetBufferAddrAndSize(argv[1], &size, error);
if(addr == NULL) return NULL;
int flags = Object_ToInt(argv[2], error);
if(error->occurred) return NULL;
ssize_t r = send(sockfd, addr, size, flags);
return Object_FromInt(r, heap, error);
}
static Object *bin_recv(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
{
assert(argc == 3);
Heap *heap = Runtime_GetHeap(runtime);
int sockfd = Object_ToInt(argv[0], error);
if(error->occurred) return NULL;
int size;
void *addr = Object_GetBufferAddrAndSize(argv[1], &size, error);
if(addr == NULL) return NULL;
int flags = Object_ToInt(argv[2], error);
if(error->occurred) return NULL;
ssize_t r = recv(sockfd, addr, size, flags);
return Object_FromInt(r, heap, error);
}
+94
View File
@@ -0,0 +1,94 @@
#include <string.h>
#include <assert.h>
#include "o_staticmap.h"
#include "utils/defs.h"
#include "objects/objects.h"
typedef struct {
Object base;
Runtime *runt;
const StaticMapSlot *slots;
} StaticMapObject;
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
static Object *copy(Object *self, Heap *heap, Error *err);
static int hash(Object *self);
static TypeObject t_staticmap = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "static map",
.size = sizeof (StaticMapObject),
.copy = copy,
.hash = hash,
.select = select,
};
static Object *copy(Object *self, Heap *heap, Error *err)
{
(void) heap;
(void) err;
return self;
}
static int hash(Object *self)
{
(void) self;
return 0;
}
Object *Object_NewStaticMap(const StaticMapSlot *slots, Runtime *runt, Error *error)
{
Heap *heap = Runtime_GetHeap(runt);
// Make the thing.
StaticMapObject *obj = (StaticMapObject*) Heap_Malloc(heap, &t_staticmap, error);
{
if(obj == 0)
return 0;
obj->runt = runt;
obj->slots = slots;
}
return (Object*) obj;
}
static Object *select(Object *self, Object *key, Heap *heap, Error *error)
{
assert(self != NULL);
assert(self->type == &t_staticmap);
assert(key != NULL);
assert(heap != NULL);
assert(error != NULL);
StaticMapObject *map = (StaticMapObject*) self;
if(!Object_IsString(key))
return NULL;
const char *name = Object_ToString(key, NULL, heap, error);
if(map->slots == NULL)
return NULL;
for(int i = 0; map->slots[i].name != NULL; i += 1)
if(!strcmp(name, map->slots[i].name))
{
StaticMapSlot slot = map->slots[i];
Object *obj;
switch(slot.kind)
{
case SM_BOOL: return Object_FromBool(slot.as_bool, heap, error);
case SM_INT: return Object_FromInt(slot.as_int, heap, error);
case SM_FLOAT: return Object_FromFloat(slot.as_float, heap, error);
case SM_FUNCT: return Object_FromNativeFunction(map->runt, slot.as_funct, slot.argc, heap, error);
case SM_STRING: return Object_FromString(slot.as_string, slot.length, heap, error);
case SM_SMAP: return Object_NewStaticMap(slot.as_smap, map->runt, error);
case SM_NONE: return Object_NewNone(heap, error);
case SM_TYPE: return (Object*) slot.as_type;
default: assert(0); break;
}
return obj;
}
return NULL;
}
+37
View File
@@ -0,0 +1,37 @@
#ifndef STATICMAP_H
#define STATICMAP_H
#include "objects/objects.h"
#include "runtime/runtime.h"
typedef enum {
SM_END,
SM_BOOL,
SM_INT,
SM_FLOAT,
SM_FUNCT,
SM_STRING,
SM_SMAP,
SM_NONE,
SM_TYPE,
} StaticMapSlotKind;
typedef struct StaticMapSlot StaticMapSlot;
struct StaticMapSlot {
const char *name;
StaticMapSlotKind kind;
union {
const StaticMapSlot *as_smap;
const char *as_string;
_Bool as_bool;
long long int as_int;
double as_float;
Object *(*as_funct)(Runtime*, Object**, unsigned int, Error*);
TypeObject *as_type;
};
union { int argc; int length; };
};
Object *Object_NewStaticMap(const StaticMapSlot *slots, Runtime *runt, Error *error);
#endif
+5
View File
@@ -52,6 +52,11 @@ static TypeObject t_buffer_slice = {
#define THRESHOLD 128
_Bool Object_IsBuffer(Object *obj)
{
return obj->type == &t_buffer_slice || obj->type == &t_buffer;
}
Object *Object_NewBuffer(int size, Heap *heap, Error *error)
{
assert(size >= 0);
+53
View File
@@ -0,0 +1,53 @@
#include "objects.h"
typedef struct {
Object base;
DIR *dir;
} DirObject;
static _Bool dir_free(Object *obj, Error *error);
static TypeObject t_dir = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "Directory",
.size = sizeof(DirObject),
.free = dir_free,
};
_Bool Object_IsDir(Object *obj)
{
return obj->type == &t_dir;
}
Object *Object_FromDIR(DIR *handle, Heap *heap, Error *error)
{
DirObject *dob = (DirObject*) Heap_Malloc(heap, &t_dir, error);
if(dob == NULL)
return NULL;
dob->dir = handle;
return (Object*) dob;
}
DIR *Object_ToDIR(Object *obj, Error *error)
{
if(!Object_IsDir(obj))
{
Error_Report(error, 0, "Object is not a directory");
return NULL;
}
return ((DirObject*) obj)->dir;
}
static _Bool dir_free(Object *obj, Error *error)
{
DirObject *dob = (DirObject*) obj;
if(closedir(dob->dir) == 0)
return 1;
Error_Report(error, 0, "Failed to close directory");
return 0;
}
+53
View File
@@ -0,0 +1,53 @@
#include "objects.h"
typedef struct {
Object base;
FILE *fp;
} FileObject;
static _Bool file_free(Object *self, Error *error);
static TypeObject t_file = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "File",
.size = sizeof(FileObject),
.free = file_free,
};
_Bool Object_IsFile(Object *obj)
{
return obj->type == &t_file;
}
FILE *Object_ToStream(Object *obj, Error *error)
{
if(!Object_IsFile(obj))
{
Error_Report(error, 0, "Object is not a file");
return NULL;
}
return ((FileObject*) obj)->fp;
}
Object *Object_FromStream(FILE *fp, Heap *heap, Error *error)
{
FileObject *fob = Heap_Malloc(heap, &t_file, error);
if(fob == NULL)
return NULL;
fob->fp = fp;
return (Object*) fob;
}
static _Bool file_free(Object *self, Error *error)
{
FileObject *fob = (FileObject*) self;
if(fclose(fob->fp) == 0)
return 1;
Error_Report(error, 0, "Failed to close stream");
return 0;
}
+5
View File
@@ -22,6 +22,11 @@ static Object the_none_object = {
.flags = Object_STATIC,
};
_Bool Object_IsNone(Object *obj)
{
return obj == &the_none_object;
}
static int hash(Object *self)
{
assert(self == &the_none_object);
+10
View File
@@ -1,6 +1,7 @@
#ifndef OBJECT_H
#define OBJECT_H
#include <dirent.h>
#include <stdio.h>
#include "../utils/error.h"
@@ -115,18 +116,27 @@ Object* Object_FromInt (long long int val, Heap *heap, Error *error);
Object* Object_FromBool (_Bool val, Heap *heap, Error *error);
Object* Object_FromFloat (double val, Heap *heap, Error *error);
Object* Object_FromString(const char *str, int len, Heap *heap, Error *error);
Object* Object_FromStream(FILE *fp, Heap *heap, Error *error);
Object* Object_FromDIR(DIR *handle, Heap *heap, Error *error);
_Bool Object_IsNone(Object *obj);
_Bool Object_IsInt(Object *obj);
_Bool Object_IsBool(Object *obj);
_Bool Object_IsFloat(Object *obj);
_Bool Object_IsString(Object *obj);
_Bool Object_IsBuffer(Object *obj);
_Bool Object_IsFile(Object *obj);
_Bool Object_IsDir(Object *obj);
long long int Object_ToInt (Object *obj, Error *err);
_Bool Object_ToBool (Object *obj, Error *err);
double Object_ToFloat(Object *obj, Error *err);
const char *Object_ToString(Object *obj, int *size, Heap *heap, Error *err);
DIR *Object_ToDIR(Object *obj, Error *error);
FILE *Object_ToStream(Object *obj, Error *error);
_Bool Object_Compare(Object *obj1, Object *obj2, Error *error);
extern TypeObject t_type;
#endif