simplified the architecture
This commit is contained in:
@@ -18,3 +18,4 @@ embedder
|
|||||||
*_n.c
|
*_n.c
|
||||||
|
|
||||||
profiling-results.txt
|
profiling-results.txt
|
||||||
|
tokens.txt
|
||||||
+2
-4
@@ -33,10 +33,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "../lib/runtime/run.h"
|
#include "../lib/run.h"
|
||||||
#include "../lib/runtime/runtime.h"
|
#include "../lib/runtime.h"
|
||||||
#include "../lib/runtime/builtins_api.h"
|
|
||||||
#include "../lib/runtime/serialize_profiling.h"
|
|
||||||
|
|
||||||
static void usage(FILE *stream, const char *name)
|
static void usage(FILE *stream, const char *name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "../executable.h"
|
||||||
#include "../utils/error.h"
|
#include "../utils/error.h"
|
||||||
#include "../utils/source.h"
|
#include "../utils/source.h"
|
||||||
#include "../utils/labellist.h"
|
#include "../utils/labellist.h"
|
||||||
#include "../common/executable.h"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *str;
|
const char *str;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef ASSEMBLE_H
|
#ifndef ASSEMBLE_H
|
||||||
#define ASSEMBLE_H
|
#define ASSEMBLE_H
|
||||||
|
#include "../executable.h"
|
||||||
#include "../utils/error.h"
|
#include "../utils/error.h"
|
||||||
#include "../utils/source.h"
|
#include "../utils/source.h"
|
||||||
#include "../common/executable.h"
|
|
||||||
Executable *assemble(Source *src, Error *error, int *error_offset);
|
Executable *assemble(Source *src, Error *error, int *error_offset);
|
||||||
#endif /* ASSEMBLE_H */
|
#endif /* ASSEMBLE_H */
|
||||||
@@ -40,11 +40,11 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
#include "../defs.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../common/defs.h"
|
|
||||||
#include "../objects/objects.h"
|
#include "../objects/objects.h"
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
#include "../runtime/run.h"
|
#include "../run.h"
|
||||||
|
|
||||||
static int bin_getCurrentWorkingDirectory(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
|
static int bin_getCurrentWorkingDirectory(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,6 +28,6 @@
|
|||||||
** +--------------------------------------------------------------------------+
|
** +--------------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
void bins_basic_init(StaticMapSlot slots[]);
|
void bins_basic_init(StaticMapSlot slots[]);
|
||||||
extern StaticMapSlot bins_basic[];
|
extern StaticMapSlot bins_basic[];
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../utils/utf8.h"
|
#include "../utils/utf8.h"
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
|
|
||||||
static int bin_new(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
|
static int bin_new(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
|
||||||
{
|
{
|
||||||
@@ -31,23 +31,13 @@ static int bin_sliceUp(Runtime *runtime, Object **argv, unsigned int argc, Objec
|
|||||||
UNUSED(argc);
|
UNUSED(argc);
|
||||||
ASSERT(argc == 3);
|
ASSERT(argc == 3);
|
||||||
|
|
||||||
if(!Object_IsInt(argv[1]))
|
ParsedArgument pargs[3];
|
||||||
{
|
if (!parseArgs(error, argv, argc, pargs, "Bii"))
|
||||||
Error_Report(error, ErrorType_RUNTIME, "Argument 1 is not an int");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
long long int offset = pargs[1].as_int;
|
||||||
|
long long int length = pargs[2].as_int;
|
||||||
if(!Object_IsInt(argv[2]))
|
|
||||||
{
|
|
||||||
Error_Report(error, ErrorType_RUNTIME, "Argument 2 is not an int");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
long long int offset = Object_GetInt(argv[1]);
|
|
||||||
long long int length = Object_GetInt(argv[2]);
|
|
||||||
|
|
||||||
Object *temp = Object_SliceBuffer(argv[0], offset, length, Runtime_GetHeap(runtime), error);
|
Object *temp = Object_SliceBuffer(argv[0], offset, length, Runtime_GetHeap(runtime), error);
|
||||||
|
|
||||||
if(temp == NULL)
|
if(temp == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
extern StaticMapSlot bins_buffer[];
|
extern StaticMapSlot bins_buffer[];
|
||||||
@@ -28,5 +28,5 @@
|
|||||||
** +--------------------------------------------------------------------------+
|
** +--------------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
extern StaticMapSlot bins_files[];
|
extern StaticMapSlot bins_files[];
|
||||||
@@ -28,5 +28,5 @@
|
|||||||
** +--------------------------------------------------------------------------+
|
** +--------------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
extern StaticMapSlot bins_math[];
|
extern StaticMapSlot bins_math[];
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
extern StaticMapSlot bins_net[];
|
extern StaticMapSlot bins_net[];
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
extern StaticMapSlot bins_random[];
|
extern StaticMapSlot bins_random[];
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../utils/utf8.h"
|
#include "../utils/utf8.h"
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
|
|
||||||
static int bin_ord(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
|
static int bin_ord(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
extern StaticMapSlot bins_string[];
|
extern StaticMapSlot bins_string[];
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "../utils/error.h"
|
#include "../utils/error.h"
|
||||||
#include "../objects/objects.h"
|
#include "../objects/objects.h"
|
||||||
#include "../runtime/runtime.h"
|
#include "../runtime.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool defined;
|
bool defined;
|
||||||
|
|||||||
@@ -158,7 +158,6 @@ typedef struct {
|
|||||||
Node *set;
|
Node *set;
|
||||||
} IndexSelectionExprNode;
|
} IndexSelectionExprNode;
|
||||||
|
|
||||||
#warning "temp"
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ExprNode base;
|
ExprNode base;
|
||||||
Node *argv;
|
Node *argv;
|
||||||
|
|||||||
@@ -30,9 +30,9 @@
|
|||||||
|
|
||||||
#ifndef CODEGEN_H
|
#ifndef CODEGEN_H
|
||||||
#define CODEGEN_H
|
#define CODEGEN_H
|
||||||
|
#include "../executable.h"
|
||||||
#include "../utils/error.h"
|
#include "../utils/error.h"
|
||||||
#include "../utils/bpalloc.h"
|
#include "../utils/bpalloc.h"
|
||||||
#include "../common/executable.h"
|
|
||||||
#include "AST.h"
|
#include "AST.h"
|
||||||
Executable *codegen(AST *ast, BPAlloc *alloc, Error *error, int *error_offset);
|
Executable *codegen(AST *ast, BPAlloc *alloc, Error *error, int *error_offset);
|
||||||
#endif /* CODEGEN_H */
|
#endif /* CODEGEN_H */
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef CODEGENCTX_H
|
#ifndef CODEGENCTX_H
|
||||||
#define CODEGENCTX_H
|
#define CODEGENCTX_H
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include "../common/executable.h"
|
#include "../executable.h"
|
||||||
|
|
||||||
typedef struct CodegenContext CodegenContext;
|
typedef struct CodegenContext CodegenContext;
|
||||||
CodegenContext *CodegenContext_New(Error *error, BPAlloc *alloc);
|
CodegenContext *CodegenContext_New(Error *error, BPAlloc *alloc);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef COMPILE_H
|
#ifndef COMPILE_H
|
||||||
#define COMPILE_H
|
#define COMPILE_H
|
||||||
|
#include "../executable.h"
|
||||||
#include "../utils/error.h"
|
#include "../utils/error.h"
|
||||||
#include "../utils/source.h"
|
#include "../utils/source.h"
|
||||||
#include "../common/executable.h"
|
|
||||||
Executable *compile(Source *src, Error *error, int *error_offset);
|
Executable *compile(Source *src, Error *error, int *error_offset);
|
||||||
#endif /* COMPILE_H */
|
#endif /* COMPILE_H */
|
||||||
@@ -62,6 +62,11 @@
|
|||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "ASTi.h"
|
#include "ASTi.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
FILE *token_dest;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
||||||
TOPT = '?',
|
TOPT = '?',
|
||||||
@@ -438,6 +443,10 @@ AST *parse(Source *src, BPAlloc *alloc, Error *error, int *error_offset)
|
|||||||
assert(alloc != NULL);
|
assert(alloc != NULL);
|
||||||
assert(error != NULL);
|
assert(error != NULL);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
token_dest = fopen("tokens.txt", "wb");
|
||||||
|
#endif
|
||||||
|
|
||||||
AST *ast = BPAlloc_Malloc(alloc, sizeof(AST));
|
AST *ast = BPAlloc_Malloc(alloc, sizeof(AST));
|
||||||
|
|
||||||
if(ast == NULL)
|
if(ast == NULL)
|
||||||
@@ -482,10 +491,7 @@ static inline TokenKind current(Context *ctx)
|
|||||||
return current_token(ctx)->kind;
|
return current_token(ctx)->kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile with -DDEBUG to get debugging messages printed to stderr.
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
static inline TokenKind next(Context *ctx, const char *file, int line)
|
static inline TokenKind next(Context *ctx, const char *file, int line)
|
||||||
{
|
{
|
||||||
assert(ctx != NULL);
|
assert(ctx != NULL);
|
||||||
@@ -495,12 +501,12 @@ static inline TokenKind next(Context *ctx, const char *file, int line)
|
|||||||
Token *prev = ctx->token;
|
Token *prev = ctx->token;
|
||||||
|
|
||||||
ctx->token = ctx->token->next;
|
ctx->token = ctx->token->next;
|
||||||
/*
|
|
||||||
fprintf(stderr, "NEXT [%.*s] -> [%.*s] from %s:%d\n",
|
fprintf(token_dest, "NEXT [%.*s] -> [%.*s] from %s:%d\n",
|
||||||
prev->length, ctx->src + prev->offset,
|
prev->length, ctx->src + prev->offset,
|
||||||
ctx->token->length, ctx->src + ctx->token->offset,
|
ctx->token->length, ctx->src + ctx->token->offset,
|
||||||
file, line);
|
file, line);
|
||||||
*/
|
|
||||||
return current(ctx);
|
return current(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,7 +523,7 @@ static inline TokenKind prev(Context *ctx)
|
|||||||
|
|
||||||
static void Error_Report_(Error *error, const char *file, const char *func, int line, _Bool internal, const char *fmt, ...)
|
static void Error_Report_(Error *error, const char *file, const char *func, int line, _Bool internal, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Reporting error at %s:%d (in %s)\n", file, line, func);
|
//fprintf(stderr, "Reporting error at %s:%d (in %s)\n", file, line, func);
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "../utils/defs.h"
|
|
||||||
#include "../utils/bucketlist.h"
|
|
||||||
#include "executable.h"
|
#include "executable.h"
|
||||||
|
#include "utils/defs.h"
|
||||||
|
#include "utils/bucketlist.h"
|
||||||
|
|
||||||
#define MAX_OPS 3
|
#define MAX_OPS 3
|
||||||
#define MAX_OPCODE_NAME_SIZE 127
|
#define MAX_OPCODE_NAME_SIZE 127
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
#ifndef EXECUTABLE_H
|
#ifndef EXECUTABLE_H
|
||||||
#define EXECUTABLE_H
|
#define EXECUTABLE_H
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "../utils/source.h"
|
#include "utils/source.h"
|
||||||
#include "../utils/promise.h"
|
#include "utils/promise.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OPTP_IDX,
|
OPTP_IDX,
|
||||||
@@ -47,9 +47,9 @@
|
|||||||
*/
|
*/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "../runtime/runtime.h"
|
#include "runtime.h"
|
||||||
#include "../utils/defs.h"
|
#include "utils/defs.h"
|
||||||
#include "../objects/objects.h"
|
#include "objects/objects.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Object base;
|
Object base;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
#include "../defs.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../common/defs.h"
|
|
||||||
|
|
||||||
static void print(Object *obj, FILE *fp);
|
static void print(Object *obj, FILE *fp);
|
||||||
static _Bool op_eql(Object *self, Object *other);
|
static _Bool op_eql(Object *self, Object *other);
|
||||||
|
|||||||
@@ -31,8 +31,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
#include "../defs.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../common/defs.h"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t refs, size;
|
size_t refs, size;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Object base;
|
Object base;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Object base;
|
Object base;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../utils/hash.h"
|
#include "../utils/hash.h"
|
||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
|
|
||||||
static void print(Object *obj, FILE *fp);
|
static void print(Object *obj, FILE *fp);
|
||||||
static _Bool op_eql(Object *self, Object *other);
|
static _Bool op_eql(Object *self, Object *other);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../utils/hash.h"
|
#include "../utils/hash.h"
|
||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
|
|
||||||
static void print(Object *obj, FILE *fp);
|
static void print(Object *obj, FILE *fp);
|
||||||
static _Bool op_eql(Object *self, Object *other);
|
static _Bool op_eql(Object *self, Object *other);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Object base;
|
Object base;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Object base;
|
Object base;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
|
|
||||||
static _Bool op_eql(Object *self, Object *other);
|
static _Bool op_eql(Object *self, Object *other);
|
||||||
static void print(Object *obj, FILE *fp);
|
static void print(Object *obj, FILE *fp);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
|
||||||
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
|
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../utils/hash.h"
|
#include "../utils/hash.h"
|
||||||
#include "../utils/utf8.h"
|
#include "../utils/utf8.h"
|
||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Object base;
|
Object base;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
|
||||||
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
|
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "../utils/defs.h"
|
#include "../utils/defs.h"
|
||||||
#include "../common/defs.h"
|
#include "../defs.h"
|
||||||
|
|
||||||
static _Bool op_eql(Object *self, Object *other);
|
static _Bool op_eql(Object *self, Object *other);
|
||||||
static bool istypeof(Object *self, Object *other, Heap *heap, Error *error);
|
static bool istypeof(Object *self, Object *other, Heap *heap, Error *error);
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "../utils/defs.h"
|
#include "utils/defs.h"
|
||||||
#include "../utils/path.h"
|
#include "utils/path.h"
|
||||||
#include "../compiler/compile.h"
|
#include "compiler/compile.h"
|
||||||
#include "../assembler/assemble.h"
|
#include "assembler/assemble.h"
|
||||||
|
|
||||||
static int runExecutableAtIndex(Runtime *runtime, Error *error,
|
static int runExecutableAtIndex(Runtime *runtime, Error *error,
|
||||||
Executable *exe, int index,
|
Executable *exe, int index,
|
||||||
@@ -1040,7 +1040,7 @@ static _Bool runInstruction(Runtime *runtime, Error *error)
|
|||||||
UNUSED(retc);
|
UNUSED(retc);
|
||||||
ASSERT(retc >= 0);
|
ASSERT(retc >= 0);
|
||||||
ASSERT(retc <= MAX_RETS);
|
ASSERT(retc <= MAX_RETS);
|
||||||
ASSERT(retc == Runtime_GetFrameStackUsage(runtime));
|
ASSERT((size_t) retc == Runtime_GetFrameStackUsage(runtime));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,11 +28,15 @@
|
|||||||
** +--------------------------------------------------------------------------+
|
** +--------------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "run.h"
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "../utils/path.h"
|
#include "utils/path.h"
|
||||||
#include "../utils/defs.h"
|
#include "utils/defs.h"
|
||||||
#include "../utils/stack.h"
|
#include "utils/stack.h"
|
||||||
|
#include "builtins/basic.h"
|
||||||
|
|
||||||
#define MAX_FRAME_STACK 16
|
#define MAX_FRAME_STACK 16
|
||||||
#define MAX_FRAMES 16
|
#define MAX_FRAMES 16
|
||||||
@@ -216,6 +220,74 @@ void Runtime_PrintStackTrace(Runtime *runtime, FILE *stream)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the length written in buff (not considering the zero byte)
|
||||||
|
size_t Runtime_GetCurrentScriptFolder(Runtime *runtime, char *buff, size_t buffsize)
|
||||||
|
{
|
||||||
|
const char *path = Runtime_GetCurrentScriptAbsolutePath(runtime);
|
||||||
|
if(path == NULL) {
|
||||||
|
if(getcwd(buff, buffsize) == NULL)
|
||||||
|
return 0;
|
||||||
|
size_t cwdlen = strlen(buff);
|
||||||
|
if (buff[cwdlen-1] == '/')
|
||||||
|
return cwdlen;
|
||||||
|
else {
|
||||||
|
if (cwdlen+1 >= buffsize)
|
||||||
|
return 0;
|
||||||
|
buff[cwdlen] = '/';
|
||||||
|
return cwdlen+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This following block is a custom implementation
|
||||||
|
// of [dirname], which doesn't write into the input
|
||||||
|
// string and is way buggier. It will for sure give
|
||||||
|
// problems in the future!!
|
||||||
|
size_t dir_len;
|
||||||
|
{
|
||||||
|
// This is buggy code!!
|
||||||
|
size_t path_len = strlen(path);
|
||||||
|
ASSERT(path_len > 0); // Not empty
|
||||||
|
ASSERT(Path_IsAbsolute(path)); // Is absolute
|
||||||
|
ASSERT(path[path_len-1] != '/'); // Doesn't end with a slash.
|
||||||
|
|
||||||
|
size_t popped = 0;
|
||||||
|
while(path[path_len-1-popped] != '/')
|
||||||
|
popped += 1;
|
||||||
|
|
||||||
|
ASSERT(path_len > popped);
|
||||||
|
|
||||||
|
dir_len = path_len - popped;
|
||||||
|
|
||||||
|
ASSERT(dir_len < path_len);
|
||||||
|
ASSERT(path[dir_len-1] == '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dir_len >= buffsize)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memcpy(buff, path, dir_len);
|
||||||
|
buff[dir_len] = '\0';
|
||||||
|
return dir_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *Runtime_GetCurrentScriptAbsolutePath(Runtime *runtime)
|
||||||
|
{
|
||||||
|
Executable *exe = Runtime_GetMostRecentExecutable(runtime);
|
||||||
|
if (exe == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Source *src = Executable_GetSource(exe);
|
||||||
|
if(src == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
const char *path = Source_GetAbsolutePath(src);
|
||||||
|
if(path == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ASSERT(path[0] != '\0');
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
Executable *Runtime_GetMostRecentExecutable(Runtime *runtime)
|
Executable *Runtime_GetMostRecentExecutable(Runtime *runtime)
|
||||||
{
|
{
|
||||||
Frame *frame = runtime->frame;
|
Frame *frame = runtime->frame;
|
||||||
@@ -658,3 +730,84 @@ bool Runtime_CollectGarbage(Runtime *runtime, Error *error)
|
|||||||
|
|
||||||
return Heap_StopCollection(runtime->heap);
|
return Heap_StopCollection(runtime->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Runtime_plugBuiltinsFromStaticMap(Runtime *runtime, StaticMapSlot *bin_table, void (*bin_table_constructor)(StaticMapSlot*), Error *error)
|
||||||
|
{
|
||||||
|
Object *object = Object_NewStaticMap(bin_table, bin_table_constructor, runtime, error);
|
||||||
|
if (object == NULL)
|
||||||
|
return false;
|
||||||
|
return Runtime_plugBuiltins(runtime, object, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Runtime_plugBuiltinsFromSource(Runtime *runtime, Source *source, Error *error)
|
||||||
|
{
|
||||||
|
Object *rets[8];
|
||||||
|
int retc = runSource(runtime, source, rets, error);
|
||||||
|
if(retc < 0)
|
||||||
|
return false;
|
||||||
|
if (retc == 0)
|
||||||
|
return true;
|
||||||
|
return Runtime_plugBuiltins(runtime, rets[0], error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Runtime_plugBuiltinsFromFile(Runtime *runtime, const char *file, Error *error)
|
||||||
|
{
|
||||||
|
Source *source = Source_FromFile(file, error);
|
||||||
|
if (source == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool result = Runtime_plugBuiltinsFromSource(runtime, source, error);
|
||||||
|
|
||||||
|
Source_Free(source);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Runtime_plugBuiltinsFromString(Runtime *runtime, const char *string, Error *error)
|
||||||
|
{
|
||||||
|
Source *source = Source_FromString("<prelude>", string, -1, error);
|
||||||
|
if (source == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool result = Runtime_plugBuiltinsFromSource(runtime, source, error);
|
||||||
|
|
||||||
|
Source_Free(source);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Runtime_plugDefaultBuiltins(Runtime *runtime, Error *error)
|
||||||
|
{
|
||||||
|
extern char start_noja[];
|
||||||
|
return Runtime_plugBuiltinsFromStaticMap(runtime, bins_basic, bins_basic_init, error)
|
||||||
|
&& Runtime_plugBuiltinsFromString(runtime, start_noja, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runtime_SerializeProfilingResultsToStream(Runtime *runtime, FILE *stream)
|
||||||
|
{
|
||||||
|
TimingTable *table = Runtime_GetTimingTable(runtime);
|
||||||
|
if (table == NULL)
|
||||||
|
return; // Runtime wasn't profiling
|
||||||
|
|
||||||
|
size_t count;
|
||||||
|
const FunctionExecutionSummary *summary = TimingTable_getSummary(table, &count);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
if (summary[i].calls > 0) {
|
||||||
|
fprintf(stream, "%20s - %s - %ld calls - %.2lfus\n",
|
||||||
|
summary[i].name,
|
||||||
|
Source_GetName(summary[i].src),
|
||||||
|
summary[i].calls,
|
||||||
|
summary[i].time * 1000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Runtime_SerializeProfilingResultsToFile(Runtime *runtime, const char *file)
|
||||||
|
{
|
||||||
|
FILE *stream = fopen(file, "wb");
|
||||||
|
if (stream == NULL)
|
||||||
|
return false;
|
||||||
|
Runtime_SerializeProfilingResultsToStream(runtime, stream);
|
||||||
|
fclose(stream);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -33,10 +33,10 @@
|
|||||||
|
|
||||||
#include <stdio.h> // meh.. just for the definition of FILE.
|
#include <stdio.h> // meh.. just for the definition of FILE.
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
#include "../utils/error.h"
|
#include "executable.h"
|
||||||
#include "../utils/stack.h"
|
#include "utils/error.h"
|
||||||
#include "../objects/objects.h"
|
#include "utils/stack.h"
|
||||||
#include "../common/executable.h"
|
#include "objects/objects.h"
|
||||||
|
|
||||||
typedef struct xRuntime Runtime;
|
typedef struct xRuntime Runtime;
|
||||||
typedef struct xSnapshot Snapshot;
|
typedef struct xSnapshot Snapshot;
|
||||||
@@ -57,6 +57,13 @@ typedef struct {
|
|||||||
Runtime* Runtime_New(RuntimeConfig config);
|
Runtime* Runtime_New(RuntimeConfig config);
|
||||||
void Runtime_Free(Runtime *runtime);
|
void Runtime_Free(Runtime *runtime);
|
||||||
|
|
||||||
|
bool Runtime_plugDefaultBuiltins(Runtime *runtime, Error *error);
|
||||||
|
bool Runtime_plugBuiltinsFromString(Runtime *runtime, const char *string, Error *error);
|
||||||
|
bool Runtime_plugBuiltinsFromFile(Runtime *runtime, const char *file, Error *error);
|
||||||
|
bool Runtime_plugBuiltinsFromStaticMap(Runtime *runtime, StaticMapSlot *bin_table, void (*bin_table_constructor)(StaticMapSlot*), Error *error);
|
||||||
|
bool Runtime_plugBuiltinsFromSource(Runtime *runtime, Source *source, Error *error);
|
||||||
|
void Runtime_SerializeProfilingResultsToStream(Runtime *runtime, FILE *stream);
|
||||||
|
bool Runtime_SerializeProfilingResultsToFile(Runtime *runtime, const char *file);
|
||||||
Object *Runtime_Top(Runtime *runtime, int n);
|
Object *Runtime_Top(Runtime *runtime, int n);
|
||||||
bool Runtime_Pop (Runtime *runtime, Error *error, Object **p, unsigned int n);
|
bool Runtime_Pop (Runtime *runtime, Error *error, Object **p, unsigned int n);
|
||||||
bool Runtime_Push(Runtime *runtime, Error *error, Object *obj);
|
bool Runtime_Push(Runtime *runtime, Error *error, Object *obj);
|
||||||
@@ -71,6 +78,8 @@ Object *Runtime_GetLocals(Runtime *runtime);
|
|||||||
Object *Runtime_GetClosure(Runtime *runtime);
|
Object *Runtime_GetClosure(Runtime *runtime);
|
||||||
size_t Runtime_GetFrameStackUsage(Runtime *runtime);
|
size_t Runtime_GetFrameStackUsage(Runtime *runtime);
|
||||||
bool Runtime_WasInterrupted(Runtime *runtime);
|
bool Runtime_WasInterrupted(Runtime *runtime);
|
||||||
|
const char *Runtime_GetCurrentScriptAbsolutePath(Runtime *runtime);
|
||||||
|
size_t Runtime_GetCurrentScriptFolder(Runtime *runtime, char *buff, size_t buffsize);
|
||||||
RuntimeCallback Runtime_GetCallback(Runtime *runtime);
|
RuntimeCallback Runtime_GetCallback(Runtime *runtime);
|
||||||
bool Runtime_CollectGarbage(Runtime *runtime, Error *error);
|
bool Runtime_CollectGarbage(Runtime *runtime, Error *error);
|
||||||
void Runtime_PrintStackTrace(Runtime *runtime, FILE *stream);
|
void Runtime_PrintStackTrace(Runtime *runtime, FILE *stream);
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
#include "run.h"
|
|
||||||
#include "builtins_api.h"
|
|
||||||
#include "../builtins/basic.h"
|
|
||||||
|
|
||||||
bool Runtime_plugBuiltinsFromStaticMap(Runtime *runtime, StaticMapSlot *bin_table, void (*bin_table_constructor)(StaticMapSlot*), Error *error)
|
|
||||||
{
|
|
||||||
Object *object = Object_NewStaticMap(bin_table, bin_table_constructor, runtime, error);
|
|
||||||
if (object == NULL)
|
|
||||||
return false;
|
|
||||||
return Runtime_plugBuiltins(runtime, object, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Runtime_plugBuiltinsFromSource(Runtime *runtime, Source *source, Error *error)
|
|
||||||
{
|
|
||||||
Object *rets[8];
|
|
||||||
int retc = runSource(runtime, source, rets, error);
|
|
||||||
if(retc < 0)
|
|
||||||
return false;
|
|
||||||
if (retc == 0)
|
|
||||||
return true;
|
|
||||||
return Runtime_plugBuiltins(runtime, rets[0], error);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Runtime_plugBuiltinsFromFile(Runtime *runtime, const char *file, Error *error)
|
|
||||||
{
|
|
||||||
Source *source = Source_FromFile(file, error);
|
|
||||||
if (source == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool result = Runtime_plugBuiltinsFromSource(runtime, source, error);
|
|
||||||
|
|
||||||
Source_Free(source);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Runtime_plugBuiltinsFromString(Runtime *runtime, const char *string, Error *error)
|
|
||||||
{
|
|
||||||
Source *source = Source_FromString("<prelude>", string, -1, error);
|
|
||||||
if (source == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool result = Runtime_plugBuiltinsFromSource(runtime, source, error);
|
|
||||||
|
|
||||||
Source_Free(source);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Runtime_plugDefaultBuiltins(Runtime *runtime, Error *error)
|
|
||||||
{
|
|
||||||
extern char start_noja[];
|
|
||||||
return Runtime_plugBuiltinsFromStaticMap(runtime, bins_basic, bins_basic_init, error)
|
|
||||||
&& Runtime_plugBuiltinsFromString(runtime, start_noja, error)
|
|
||||||
&& Runtime_plugBuiltinsFromString(runtime, "XXX=999;", error);
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#include "runtime.h"
|
|
||||||
bool Runtime_plugDefaultBuiltins(Runtime *runtime, Error *error);
|
|
||||||
bool Runtime_plugBuiltinsFromString(Runtime *runtime, const char *string, Error *error);
|
|
||||||
bool Runtime_plugBuiltinsFromFile(Runtime *runtime, const char *file, Error *error);
|
|
||||||
bool Runtime_plugBuiltinsFromStaticMap(Runtime *runtime, StaticMapSlot *bin_table, void (*bin_table_constructor)(StaticMapSlot*), Error *error);
|
|
||||||
bool Runtime_plugBuiltinsFromSource(Runtime *runtime, Source *source, Error *error);
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "path.h"
|
|
||||||
#include "../utils/defs.h"
|
|
||||||
#include "../utils/path.h"
|
|
||||||
|
|
||||||
// Returns the length written in buff (not considering the zero byte)
|
|
||||||
size_t Runtime_GetCurrentScriptFolder(Runtime *runtime, char *buff, size_t buffsize)
|
|
||||||
{
|
|
||||||
const char *path = Runtime_GetCurrentScriptAbsolutePath(runtime);
|
|
||||||
if(path == NULL) {
|
|
||||||
if(getcwd(buff, buffsize) == NULL)
|
|
||||||
return 0;
|
|
||||||
size_t cwdlen = strlen(buff);
|
|
||||||
if (buff[cwdlen-1] == '/')
|
|
||||||
return cwdlen;
|
|
||||||
else {
|
|
||||||
if (cwdlen+1 >= buffsize)
|
|
||||||
return 0;
|
|
||||||
buff[cwdlen] = '/';
|
|
||||||
return cwdlen+1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This following block is a custom implementation
|
|
||||||
// of [dirname], which doesn't write into the input
|
|
||||||
// string and is way buggier. It will for sure give
|
|
||||||
// problems in the future!!
|
|
||||||
size_t dir_len;
|
|
||||||
{
|
|
||||||
// This is buggy code!!
|
|
||||||
size_t path_len = strlen(path);
|
|
||||||
ASSERT(path_len > 0); // Not empty
|
|
||||||
ASSERT(Path_IsAbsolute(path)); // Is absolute
|
|
||||||
ASSERT(path[path_len-1] != '/'); // Doesn't end with a slash.
|
|
||||||
|
|
||||||
size_t popped = 0;
|
|
||||||
while(path[path_len-1-popped] != '/')
|
|
||||||
popped += 1;
|
|
||||||
|
|
||||||
ASSERT(path_len > popped);
|
|
||||||
|
|
||||||
dir_len = path_len - popped;
|
|
||||||
|
|
||||||
ASSERT(dir_len < path_len);
|
|
||||||
ASSERT(path[dir_len-1] == '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dir_len >= buffsize)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memcpy(buff, path, dir_len);
|
|
||||||
buff[dir_len] = '\0';
|
|
||||||
return dir_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *Runtime_GetCurrentScriptAbsolutePath(Runtime *runtime)
|
|
||||||
{
|
|
||||||
Executable *exe = Runtime_GetMostRecentExecutable(runtime);
|
|
||||||
if (exe == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
Source *src = Executable_GetSource(exe);
|
|
||||||
if(src == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
const char *path = Source_GetAbsolutePath(src);
|
|
||||||
if(path == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ASSERT(path[0] != '\0');
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#include <stddef.h>
|
|
||||||
#include "runtime.h"
|
|
||||||
const char *Runtime_GetCurrentScriptAbsolutePath(Runtime *runtime);
|
|
||||||
size_t Runtime_GetCurrentScriptFolder(Runtime *runtime, char *buff, size_t buffsize);
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#include "serialize_profiling.h"
|
|
||||||
|
|
||||||
void Runtime_SerializeProfilingResultsToStream(Runtime *runtime, FILE *stream)
|
|
||||||
{
|
|
||||||
TimingTable *table = Runtime_GetTimingTable(runtime);
|
|
||||||
if (table == NULL)
|
|
||||||
return; // Runtime wasn't profiling
|
|
||||||
|
|
||||||
size_t count;
|
|
||||||
const FunctionExecutionSummary *summary = TimingTable_getSummary(table, &count);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
if (summary[i].calls > 0) {
|
|
||||||
fprintf(stream, "%20s - %s - %ld calls - %.2lfus\n",
|
|
||||||
summary[i].name,
|
|
||||||
Source_GetName(summary[i].src),
|
|
||||||
summary[i].calls,
|
|
||||||
summary[i].time * 1000000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Runtime_SerializeProfilingResultsToFile(Runtime *runtime, const char *file)
|
|
||||||
{
|
|
||||||
FILE *stream = fopen(file, "wb");
|
|
||||||
if (stream == NULL)
|
|
||||||
return false;
|
|
||||||
Runtime_SerializeProfilingResultsToStream(runtime, stream);
|
|
||||||
fclose(stream);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#include "runtime.h"
|
|
||||||
|
|
||||||
void Runtime_SerializeProfilingResultsToStream(Runtime *runtime, FILE *stream);
|
|
||||||
bool Runtime_SerializeProfilingResultsToFile(Runtime *runtime, const char *file);
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
#include "../utils/defs.h"
|
#include "utils/defs.h"
|
||||||
|
|
||||||
struct TimingTable {
|
struct TimingTable {
|
||||||
FunctionExecutionSummary *entries;
|
FunctionExecutionSummary *entries;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#define TIMING_H
|
#define TIMING_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "../utils/source.h"
|
#include "utils/source.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t calls;
|
size_t calls;
|
||||||
+1
-1
@@ -4,9 +4,9 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include "../lib/executable.h"
|
||||||
#include "../lib/utils/source.h"
|
#include "../lib/utils/source.h"
|
||||||
#include "../lib/compiler/compile.h"
|
#include "../lib/compiler/compile.h"
|
||||||
#include "../lib/common/executable.h"
|
|
||||||
#include "../lib/assembler/assemble.h"
|
#include "../lib/assembler/assemble.h"
|
||||||
|
|
||||||
//Regular text
|
//Regular text
|
||||||
|
|||||||
Reference in New Issue
Block a user