summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2009-12-01 16:10:11 +0100
committerJohannes Weiner <hannes@cmpxchg.org>2009-12-01 16:35:14 +0100
commitd95e463ef11084159c0c5f3e7d5247c75081b966 (patch)
tree38990a75364f9ac4915fe3cca5c9b7761bcac1c0
parent5c1f75312e20beb34fdb316b63f124d7198997e2 (diff)
vm: vm->builtins
In order to re-use all builtins in different modules without them interefering with each other, move the builtins to their own environment layer - vm->builtins. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
-rw-r--r--include/sheep/vm.h8
-rw-r--r--sheep/bool.c11
-rw-r--r--sheep/compile.c55
-rw-r--r--sheep/core.c19
-rw-r--r--sheep/list.c9
-rw-r--r--sheep/number.c41
-rw-r--r--sheep/vm.c22
7 files changed, 100 insertions, 65 deletions
diff --git a/include/sheep/vm.h b/include/sheep/vm.h
index 2604a52..635bae9 100644
--- a/include/sheep/vm.h
+++ b/include/sheep/vm.h
@@ -10,6 +10,7 @@
#include <sheep/module.h>
#include <sheep/object.h>
#include <sheep/vector.h>
+#include <sheep/alien.h>
#include <sheep/map.h>
struct sheep_vm {
@@ -23,6 +24,7 @@ struct sheep_vm {
/* Compiler */
struct sheep_map specials;
+ struct sheep_map builtins;
struct sheep_module main;
/* Evaluator */
@@ -41,6 +43,12 @@ static inline unsigned int sheep_vm_global(struct sheep_vm *vm)
return sheep_vector_push(&vm->globals, NULL);
}
+unsigned int sheep_vm_bind(struct sheep_vm *, struct sheep_map *,
+ const char *, sheep_t);
+
+void sheep_vm_variable(struct sheep_vm *, const char *, sheep_t);
+void sheep_vm_function(struct sheep_vm *, const char *, sheep_alien_t);
+
void sheep_vm_init(struct sheep_vm *);
void sheep_vm_exit(struct sheep_vm *);
diff --git a/sheep/bool.c b/sheep/bool.c
index 58dab20..e4f4f18 100644
--- a/sheep/bool.c
+++ b/sheep/bool.c
@@ -4,7 +4,6 @@
* Copyright (c) 2009 Johannes Weiner <hannes@cmpxchg.org>
*/
#include <sheep/compile.h>
-#include <sheep/module.h>
#include <sheep/object.h>
#include <sheep/core.h>
#include <sheep/util.h>
@@ -82,10 +81,10 @@ static sheep_t eval_not(struct sheep_vm *vm, unsigned int nr_args)
void sheep_bool_builtins(struct sheep_vm *vm)
{
- sheep_module_shared(vm, &vm->main, "true", &sheep_true);
- sheep_module_shared(vm, &vm->main, "false", &sheep_false);
+ sheep_vm_variable(vm, "true", &sheep_true);
+ sheep_vm_variable(vm, "false", &sheep_false);
- sheep_module_function(vm, &vm->main, "=", eval_equal);
- sheep_module_function(vm, &vm->main, "bool", eval_bool);
- sheep_module_function(vm, &vm->main, "not", eval_not);
+ sheep_vm_function(vm, "=", eval_equal);
+ sheep_vm_function(vm, "bool", eval_bool);
+ sheep_vm_function(vm, "not", eval_not);
}
diff --git a/sheep/compile.c b/sheep/compile.c
index 37c15ec..8e0ea6d 100644
--- a/sheep/compile.c
+++ b/sheep/compile.c
@@ -48,22 +48,28 @@ int sheep_compile_constant(struct sheep_vm *vm, struct sheep_function *function,
}
enum env_level {
+ ENV_NONE,
ENV_LOCAL,
ENV_GLOBAL,
ENV_FOREIGN,
+ ENV_BUILTIN,
};
-static int lookup(struct sheep_context *context, const char *name,
- unsigned int *dist, unsigned int *slot,
- enum env_level *env_level)
+static enum env_level lookup_env(struct sheep_vm *vm,
+ struct sheep_context *context, const char *name,
+ unsigned int *dist, unsigned int *slot)
{
struct sheep_context *current = context;
unsigned int distance = 0;
void *entry;
while (sheep_map_get(current->env, name, &entry)) {
- if (!current->parent)
- return -1;
+ if (!current->parent) {
+ if (sheep_map_get(&vm->builtins, name, &entry))
+ return ENV_NONE;
+ current = NULL;
+ break;
+ }
if (current->flags & SHEEP_CONTEXT_FUNCTION)
distance++;
current = current->parent;
@@ -72,14 +78,13 @@ static int lookup(struct sheep_context *context, const char *name,
*dist = distance;
*slot = (unsigned long)entry;
+ if (!current)
+ return ENV_BUILTIN;
if (!current->parent)
- *env_level = ENV_GLOBAL;
- else if (!distance)
- *env_level = ENV_LOCAL;
- else
- *env_level = ENV_FOREIGN;
-
- return 0;
+ return ENV_GLOBAL;
+ if (!distance)
+ return ENV_LOCAL;
+ return ENV_FOREIGN;
}
static unsigned int slot_foreign(struct sheep_function *function,
@@ -112,22 +117,19 @@ static unsigned int slot_foreign(struct sheep_function *function,
return sheep_vector_push(foreign, freevar);
}
-static int __sheep_compile_name(struct sheep_vm *vm,
- struct sheep_function *function,
- struct sheep_context *context,
- sheep_t expr, int set)
+static int compile_name(struct sheep_vm *vm,
+ struct sheep_function *function,
+ struct sheep_context *context,
+ sheep_t expr, int set)
{
unsigned int dist, slot;
- enum env_level level;
const char *name;
name = sheep_cname(expr);
- if (lookup(context, name, &dist, &slot, &level)) {
+ switch (lookup_env(vm, context, name, &dist, &slot)) {
+ case ENV_NONE:
fprintf(stderr, "unbound name: %s\n", name);
return -1;
- }
-
- switch (level) {
case ENV_LOCAL:
if (set)
sheep_emit(&function->code, SHEEP_SET_LOCAL, slot);
@@ -144,6 +146,13 @@ static int __sheep_compile_name(struct sheep_vm *vm,
sheep_emit(&function->code, SHEEP_SET_FOREIGN, slot);
sheep_emit(&function->code, SHEEP_FOREIGN, slot);
break;
+ case ENV_BUILTIN:
+ if (set) {
+ fprintf(stderr, "read-only bound: %s\n", name);
+ return -1;
+ }
+ sheep_emit(&function->code, SHEEP_GLOBAL, slot);
+ break;
}
return 0;
}
@@ -151,13 +160,13 @@ static int __sheep_compile_name(struct sheep_vm *vm,
int sheep_compile_name(struct sheep_vm *vm, struct sheep_function *function,
struct sheep_context *context, sheep_t expr)
{
- return __sheep_compile_name(vm, function, context, expr, 0);
+ return compile_name(vm, function, context, expr, 0);
}
int sheep_compile_set(struct sheep_vm *vm, struct sheep_function *function,
struct sheep_context *context, sheep_t expr)
{
- return __sheep_compile_name(vm, function, context, expr, 1);
+ return compile_name(vm, function, context, expr, 1);
}
static int compile_call(struct sheep_vm *vm, struct sheep_function *function,
diff --git a/sheep/core.c b/sheep/core.c
index 511f5f2..5c7d333 100644
--- a/sheep/core.c
+++ b/sheep/core.c
@@ -5,7 +5,6 @@
*/
#include <sheep/function.h>
#include <sheep/compile.h>
-#include <sheep/module.h>
#include <sheep/number.h>
#include <sheep/string.h>
#include <sheep/unpack.h>
@@ -712,17 +711,17 @@ void sheep_core_init(struct sheep_vm *vm)
sheep_map_set(&vm->specials, "if", compile_if);
sheep_map_set(&vm->specials, "set", compile_set);
- sheep_module_function(vm, &vm->main, "string", eval_string);
- sheep_module_function(vm, &vm->main, "split", eval_split);
- sheep_module_function(vm, &vm->main, "join", eval_join);
+ sheep_vm_function(vm, "string", eval_string);
+ sheep_vm_function(vm, "split", eval_split);
+ sheep_vm_function(vm, "join", eval_join);
- sheep_module_function(vm, &vm->main, "length", eval_length);
- sheep_module_function(vm, &vm->main, "concat", eval_concat);
- sheep_module_function(vm, &vm->main, "reverse", eval_reverse);
- sheep_module_function(vm, &vm->main, "map", eval_map);
- sheep_module_function(vm, &vm->main, "reduce", eval_reduce);
+ sheep_vm_function(vm, "length", eval_length);
+ sheep_vm_function(vm, "concat", eval_concat);
+ sheep_vm_function(vm, "reverse", eval_reverse);
+ sheep_vm_function(vm, "map", eval_map);
+ sheep_vm_function(vm, "reduce", eval_reduce);
- sheep_module_function(vm, &vm->main, "disassemble", eval_disassemble);
+ sheep_vm_function(vm, "disassemble", eval_disassemble);
}
void sheep_core_exit(struct sheep_vm *vm)
diff --git a/sheep/list.c b/sheep/list.c
index ce6f334..b4571ef 100644
--- a/sheep/list.c
+++ b/sheep/list.c
@@ -4,7 +4,6 @@
* Copyright (c) 2009 Johannes Weiner <hannes@cmpxchg.org>
*/
#include <sheep/compile.h>
-#include <sheep/module.h>
#include <sheep/object.h>
#include <sheep/string.h>
#include <sheep/core.h>
@@ -246,8 +245,8 @@ static sheep_t eval_tail(struct sheep_vm *vm, unsigned int nr_args)
void sheep_list_builtins(struct sheep_vm *vm)
{
- sheep_module_function(vm, &vm->main, "cons", eval_cons);
- sheep_module_function(vm, &vm->main, "list", eval_list);
- sheep_module_function(vm, &vm->main, "head", eval_head);
- sheep_module_function(vm, &vm->main, "tail", eval_tail);
+ sheep_vm_function(vm, "cons", eval_cons);
+ sheep_vm_function(vm, "list", eval_list);
+ sheep_vm_function(vm, "head", eval_head);
+ sheep_vm_function(vm, "tail", eval_tail);
}
diff --git a/sheep/number.c b/sheep/number.c
index 2579500..1758c75 100644
--- a/sheep/number.c
+++ b/sheep/number.c
@@ -4,7 +4,6 @@
* Copyright (c) 2009 Johannes Weiner <hannes@cmpxchg.org>
*/
#include <sheep/compile.h>
-#include <sheep/module.h>
#include <sheep/object.h>
#include <sheep/string.h>
#include <sheep/bool.h>
@@ -276,24 +275,24 @@ static sheep_t eval_shiftr(struct sheep_vm *vm, unsigned int nr_args)
void sheep_number_builtins(struct sheep_vm *vm)
{
- sheep_module_function(vm, &vm->main, "number", eval_number);
-
- sheep_module_function(vm, &vm->main, "<", eval_less);
- sheep_module_function(vm, &vm->main, "<=", eval_lesseq);
- sheep_module_function(vm, &vm->main, ">=", eval_moreeq);
- sheep_module_function(vm, &vm->main, ">", eval_more);
-
- sheep_module_function(vm, &vm->main, "+", eval_plus);
- sheep_module_function(vm, &vm->main, "-", eval_minus);
- sheep_module_function(vm, &vm->main, "*", eval_multiply);
- sheep_module_function(vm, &vm->main, "/", eval_divide);
- sheep_module_function(vm, &vm->main, "%", eval_modulo);
-
- sheep_module_function(vm, &vm->main, "~", eval_lnot);
- sheep_module_function(vm, &vm->main, "|", eval_lor);
- sheep_module_function(vm, &vm->main, "&", eval_land);
- sheep_module_function(vm, &vm->main, "^", eval_lxor);
-
- sheep_module_function(vm, &vm->main, "<<", eval_shiftl);
- sheep_module_function(vm, &vm->main, ">>", eval_shiftr);
+ sheep_vm_function(vm, "number", eval_number);
+
+ sheep_vm_function(vm, "<", eval_less);
+ sheep_vm_function(vm, "<=", eval_lesseq);
+ sheep_vm_function(vm, ">=", eval_moreeq);
+ sheep_vm_function(vm, ">", eval_more);
+
+ sheep_vm_function(vm, "+", eval_plus);
+ sheep_vm_function(vm, "-", eval_minus);
+ sheep_vm_function(vm, "*", eval_multiply);
+ sheep_vm_function(vm, "/", eval_divide);
+ sheep_vm_function(vm, "%", eval_modulo);
+
+ sheep_vm_function(vm, "~", eval_lnot);
+ sheep_vm_function(vm, "|", eval_lor);
+ sheep_vm_function(vm, "&", eval_land);
+ sheep_vm_function(vm, "^", eval_lxor);
+
+ sheep_vm_function(vm, "<<", eval_shiftl);
+ sheep_vm_function(vm, ">>", eval_shiftr);
}
diff --git a/sheep/vm.c b/sheep/vm.c
index a661eee..e50ec0c 100644
--- a/sheep/vm.c
+++ b/sheep/vm.c
@@ -5,6 +5,7 @@
*/
#include <sheep/number.h>
#include <sheep/object.h>
+#include <sheep/alien.h>
#include <sheep/bool.h>
#include <sheep/core.h>
#include <sheep/eval.h>
@@ -32,6 +33,26 @@ void sheep_vm_mark(struct sheep_vm *vm)
sheep_mark(vm->stack.items[i]);
}
+unsigned int sheep_vm_bind(struct sheep_vm *vm, struct sheep_map *env,
+ const char *name, sheep_t value)
+{
+ unsigned int slot;
+
+ slot = sheep_vm_constant(vm, value);
+ sheep_map_set(env, name, (void *)(unsigned long)slot);
+ return slot;
+}
+
+void sheep_vm_variable(struct sheep_vm *vm, const char *name, sheep_t value)
+{
+ sheep_vm_bind(vm, &vm->builtins, name, value);
+}
+
+void sheep_vm_function(struct sheep_vm *vm, const char *name, sheep_alien_t f)
+{
+ sheep_vm_variable(vm, name, sheep_make_alien(vm, f, name));
+}
+
void sheep_vm_init(struct sheep_vm *vm)
{
memset(vm, 0, sizeof(*vm));
@@ -43,6 +64,7 @@ void sheep_vm_init(struct sheep_vm *vm)
void sheep_vm_exit(struct sheep_vm *vm)
{
+ sheep_map_drain(&vm->builtins);
sheep_core_exit(vm);
sheep_evaluator_exit(vm);
sheep_free(vm->globals.items);