added statis map object and used it to implement builtins. Also, new objects File and Directory
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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, {}, {} },
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "../o_staticmap.h"
|
||||
extern const StaticMapSlot bins_basic[];
|
||||
@@ -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, {}, {} },
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "../o_staticmap.h"
|
||||
extern const StaticMapSlot bins_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, {}, {} },
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "../o_staticmap.h"
|
||||
extern const StaticMapSlot bins_math[];
|
||||
+3
-2
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
+12
-2
@@ -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_IsInt (Object *obj);
|
||||
_Bool Object_IsBool (Object *obj);
|
||||
_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
|
||||
Reference in New Issue
Block a user