mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 02:59:54 +00:00
Add var and def. Make them behave the same
but have different implementations in top level scope in order to enable incremental compilation and repl.
This commit is contained in:
parent
c3d65cb91d
commit
29a39c47b0
@ -34,8 +34,7 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
|
|||||||
GstValue func;
|
GstValue func;
|
||||||
/* Try to compile generated AST */
|
/* Try to compile generated AST */
|
||||||
gst_compiler(&c, vm);
|
gst_compiler(&c, vm);
|
||||||
gst_compiler_usemodule(&c, "std");
|
gst_env_putc(vm, vm->env, "_", last);
|
||||||
gst_compiler_global(&c, "_", last);
|
|
||||||
func = gst_wrap_function(gst_compiler_compile(&c, ast));
|
func = gst_wrap_function(gst_compiler_compile(&c, ast));
|
||||||
/* Check for compilation errors */
|
/* Check for compilation errors */
|
||||||
if (c.error.type != GST_NIL) {
|
if (c.error.type != GST_NIL) {
|
||||||
|
304
core/compile.c
304
core/compile.c
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#define GST_LOCAL_FLAG_MUTABLE 1
|
||||||
|
|
||||||
/* During compilation, FormOptions are passed to ASTs
|
/* During compilation, FormOptions are passed to ASTs
|
||||||
* as configuration options to allow for some optimizations. */
|
* as configuration options to allow for some optimizations. */
|
||||||
typedef struct FormOptions FormOptions;
|
typedef struct FormOptions FormOptions;
|
||||||
@ -31,7 +33,7 @@ struct FormOptions {
|
|||||||
uint16_t target;
|
uint16_t target;
|
||||||
/* If the result of the value being compiled is not going to
|
/* If the result of the value being compiled is not going to
|
||||||
* be used, some forms can simply return a nil slot and save
|
* be used, some forms can simply return a nil slot and save
|
||||||
* copmutation */
|
* co,putation */
|
||||||
uint16_t resultUnused : 1;
|
uint16_t resultUnused : 1;
|
||||||
/* Allows the sub expression to evaluate into a
|
/* Allows the sub expression to evaluate into a
|
||||||
* temporary slot of it's choice. A temporary Slot
|
* temporary slot of it's choice. A temporary Slot
|
||||||
@ -89,8 +91,6 @@ struct GstScope {
|
|||||||
uint16_t *freeHeap;
|
uint16_t *freeHeap;
|
||||||
GstTable *literals;
|
GstTable *literals;
|
||||||
GstArray *literalsArray;
|
GstArray *literalsArray;
|
||||||
GstTable *namedLiterals;
|
|
||||||
GstTable *nilNamedLiterals; /* Work around tables not containg nil */
|
|
||||||
GstTable *locals;
|
GstTable *locals;
|
||||||
GstScope *parent;
|
GstScope *parent;
|
||||||
};
|
};
|
||||||
@ -126,16 +126,24 @@ static void c_error1(GstCompiler *c, GstValue e) {
|
|||||||
longjmp(c->onError, 1);
|
longjmp(c->onError, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Quote something */
|
||||||
|
static GstValue quote(Gst *vm, GstValue x) {
|
||||||
|
GstValue *q = gst_tuple_begin(vm, 2);
|
||||||
|
q[0] = gst_string_cv(vm, "quote");
|
||||||
|
q[1] = x; /* lit contains the var container of the environment */
|
||||||
|
return gst_wrap_tuple(gst_tuple_end(vm, q));
|
||||||
|
}
|
||||||
|
|
||||||
/* Push a new scope in the compiler and return
|
/* Push a new scope in the compiler and return
|
||||||
* a pointer to it for configuration. There is
|
* a pointer to it for configuration. There is
|
||||||
* more configuration that needs to be done if
|
* more configuration that needs to be done if
|
||||||
* the new scope is a function declaration. */
|
* the new scope is a function declaration. */
|
||||||
static GstScope *compiler_push_scope(GstCompiler *c, int sameFunction) {
|
static GstScope *compiler_push_scope(GstCompiler *c, int sameFunction) {
|
||||||
GstScope *scope = gst_alloc(c->vm, sizeof(GstScope));
|
GstScope *scope = gst_alloc(c->vm, sizeof(GstScope));
|
||||||
scope->locals = gst_table(c->vm, 10);
|
scope->locals = gst_table(c->vm, 4);
|
||||||
scope->freeHeap = gst_alloc(c->vm, 10 * sizeof(uint16_t));
|
scope->freeHeap = gst_alloc(c->vm, 4 * sizeof(uint16_t));
|
||||||
scope->heapSize = 0;
|
scope->heapSize = 0;
|
||||||
scope->heapCapacity = 10;
|
scope->heapCapacity = 4;
|
||||||
scope->parent = c->tail;
|
scope->parent = c->tail;
|
||||||
scope->frameSize = 0;
|
scope->frameSize = 0;
|
||||||
scope->touchParent = 0;
|
scope->touchParent = 0;
|
||||||
@ -152,14 +160,10 @@ static GstScope *compiler_push_scope(GstCompiler *c, int sameFunction) {
|
|||||||
scope->nextLocal = c->tail->nextLocal;
|
scope->nextLocal = c->tail->nextLocal;
|
||||||
scope->literals = c->tail->literals;
|
scope->literals = c->tail->literals;
|
||||||
scope->literalsArray = c->tail->literalsArray;
|
scope->literalsArray = c->tail->literalsArray;
|
||||||
scope->namedLiterals = c->tail->namedLiterals;
|
|
||||||
scope->nilNamedLiterals = c->tail->nilNamedLiterals;
|
|
||||||
} else {
|
} else {
|
||||||
scope->nextLocal = 0;
|
scope->nextLocal = 0;
|
||||||
scope->literals = gst_table(c->vm, 10);
|
scope->literals = gst_table(c->vm, 4);
|
||||||
scope->literalsArray = gst_array(c->vm, 10);
|
scope->literalsArray = gst_array(c->vm, 4);
|
||||||
scope->namedLiterals = gst_table(c->vm, 10);
|
|
||||||
scope->nilNamedLiterals = gst_table(c->vm, 10);
|
|
||||||
}
|
}
|
||||||
c->tail = scope;
|
c->tail = scope;
|
||||||
return scope;
|
return scope;
|
||||||
@ -194,7 +198,6 @@ static uint16_t compiler_get_local(GstCompiler *c, GstScope *scope) {
|
|||||||
} else {
|
} else {
|
||||||
return scope->freeHeap[--scope->heapSize];
|
return scope->freeHeap[--scope->heapSize];
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free a slot on the stack for other locals and/or
|
/* Free a slot on the stack for other locals and/or
|
||||||
@ -286,6 +289,33 @@ static Slot compiler_realize_slot(GstCompiler *c, Slot slot) {
|
|||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Coerce a slot to match form options. Can write to buffer. */
|
||||||
|
static Slot compiler_coerce_slot(GstCompiler *c, FormOptions opts, Slot slot) {
|
||||||
|
GstScope *scope = c->tail;
|
||||||
|
if (opts.resultUnused) {
|
||||||
|
compiler_drop_slot(c, scope, slot);
|
||||||
|
slot.isNil = 1;
|
||||||
|
return slot;
|
||||||
|
} else {
|
||||||
|
slot = compiler_realize_slot(c, slot);
|
||||||
|
}
|
||||||
|
if (opts.canChoose) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (slot.index != opts.target) {
|
||||||
|
/* We need to move the variable. This
|
||||||
|
* would occur in a simple assignment like a = b. */
|
||||||
|
GstBuffer *buffer = c->buffer;
|
||||||
|
gst_buffer_push_u16(c->vm, buffer, GST_OP_MOV);
|
||||||
|
gst_buffer_push_u16(c->vm, buffer, opts.target);
|
||||||
|
gst_buffer_push_u16(c->vm, buffer, slot.index);
|
||||||
|
slot.index = opts.target;
|
||||||
|
slot.isTemp = 0; /* We don't own the slot anymore */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
/* Helper to get a nil slot */
|
/* Helper to get a nil slot */
|
||||||
static Slot nil_slot() { Slot ret; ret.isNil = 1; ret.hasReturned = 0; return ret; }
|
static Slot nil_slot() { Slot ret; ret.isNil = 1; ret.hasReturned = 0; return ret; }
|
||||||
|
|
||||||
@ -350,44 +380,59 @@ static uint16_t compiler_add_literal(GstCompiler *c, GstScope *scope, GstValue x
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Declare a symbol in a given scope. */
|
/* Declare a symbol in a given scope. */
|
||||||
static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValue sym) {
|
static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValue sym, uint16_t flags) {
|
||||||
GstValue x;
|
GstValue x;
|
||||||
uint16_t target;
|
uint16_t target;
|
||||||
if (sym.type != GST_STRING)
|
if (sym.type != GST_STRING)
|
||||||
c_error(c, "expected string");
|
c_error(c, "expected string");
|
||||||
target = compiler_get_local(c, scope);
|
target = compiler_get_local(c, scope);
|
||||||
x.type = GST_INTEGER;
|
x.type = GST_INTEGER;
|
||||||
x.data.integer = target;
|
x.data.integer = target + (flags << 16);
|
||||||
gst_table_put(c->vm, scope->locals, sym, x);
|
gst_table_put(c->vm, scope->locals, sym, x);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to resolve a symbol. If the symbol can be resovled, return true and
|
/* Try to resolve a symbol. If the symbol can be resolved, return true and
|
||||||
* pass back the level and index by reference. */
|
* pass back the level and index by reference. */
|
||||||
static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t *index, GstValue *out) {
|
static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t *index, uint16_t *flags, GstValue *out) {
|
||||||
GstScope *scope = c->tail;
|
GstScope *scope = c->tail;
|
||||||
|
GstValue check;
|
||||||
uint32_t currentLevel = scope->level;
|
uint32_t currentLevel = scope->level;
|
||||||
while (scope) {
|
while (scope) {
|
||||||
GstValue check = gst_table_get(scope->locals, x);
|
check = gst_table_get(scope->locals, x);
|
||||||
if (check.type != GST_NIL) {
|
if (check.type != GST_NIL) {
|
||||||
*level = currentLevel - scope->level;
|
*level = currentLevel - scope->level;
|
||||||
*index = (uint16_t) check.data.integer;
|
*index = (uint16_t) (check.data.integer & 0xFFFF);
|
||||||
|
if (flags) *flags = check.data.integer >> 16;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* Check for named literals */
|
|
||||||
check = gst_table_get(scope->namedLiterals, x);
|
|
||||||
if (check.type != GST_NIL) {
|
|
||||||
*out = check;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
/* Check for nil named literal */
|
|
||||||
check = gst_table_get(scope->nilNamedLiterals, x);
|
|
||||||
if (check.type != GST_NIL) {
|
|
||||||
*out = gst_wrap_nil();
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
scope = scope->parent;
|
scope = scope->parent;
|
||||||
}
|
}
|
||||||
|
/* Check for named literals */
|
||||||
|
check = gst_table_get(c->env, x);
|
||||||
|
if (check.type != GST_NIL) {
|
||||||
|
/* Check metadata for var (mutable) */
|
||||||
|
GstTable *metas = gst_env_meta(c->vm, c->env);
|
||||||
|
GstValue maybeMeta = gst_table_get(metas, x);
|
||||||
|
if (maybeMeta.type == GST_TABLE) {
|
||||||
|
GstValue isMutable = gst_table_get(maybeMeta.data.table, gst_string_cv(c->vm, "mutable"));
|
||||||
|
if (gst_truthy(isMutable)) {
|
||||||
|
if (flags) *flags = GST_LOCAL_FLAG_MUTABLE;
|
||||||
|
*out = check;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flags) *flags = 0;
|
||||||
|
*out = check;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
/* Check for nil named literal */
|
||||||
|
check = gst_table_get(gst_env_nils(c->vm, c->env), x);
|
||||||
|
if (check.type != GST_NIL) {
|
||||||
|
if (flags) *flags = 0;
|
||||||
|
*out = gst_wrap_nil();
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +516,7 @@ static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) {
|
|||||||
uint16_t index = 0;
|
uint16_t index = 0;
|
||||||
uint16_t level = 0;
|
uint16_t level = 0;
|
||||||
Slot ret;
|
Slot ret;
|
||||||
int status = symbol_resolve(c, sym, &level, &index, &lit);
|
int status = symbol_resolve(c, sym, &level, &index, NULL, &lit);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
c_error1(c, sym);
|
c_error1(c, sym);
|
||||||
}
|
}
|
||||||
@ -479,6 +524,16 @@ static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) {
|
|||||||
if (status == 2) {
|
if (status == 2) {
|
||||||
/* We have a named literal */
|
/* We have a named literal */
|
||||||
return compile_literal(c, opts, lit);
|
return compile_literal(c, opts, lit);
|
||||||
|
} else if (status == 3) {
|
||||||
|
/* We have a global variable */
|
||||||
|
const GstValue *tup;
|
||||||
|
Gst *vm= c->vm;
|
||||||
|
GstValue *t = gst_tuple_begin(vm, 3);
|
||||||
|
t[0] = gst_string_cv(vm, "get"); /* Todo - replace with ref ro actual cfunc */
|
||||||
|
t[1] = quote(vm, lit);
|
||||||
|
t[2] = quote(vm, sym);
|
||||||
|
tup = gst_tuple_end(vm, t);
|
||||||
|
return compile_value(c, opts, gst_wrap_tuple(tup));
|
||||||
} else if (level > 0) {
|
} else if (level > 0) {
|
||||||
/* We have an upvalue from a parent function. Make
|
/* We have an upvalue from a parent function. Make
|
||||||
* sure that the chain of functions up to the upvalue keep
|
* sure that the chain of functions up to the upvalue keep
|
||||||
@ -522,14 +577,15 @@ static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstV
|
|||||||
FormOptions subOpts;
|
FormOptions subOpts;
|
||||||
uint16_t target = 0;
|
uint16_t target = 0;
|
||||||
uint16_t level = 0;
|
uint16_t level = 0;
|
||||||
|
uint16_t flags = 0;
|
||||||
Slot slot;
|
Slot slot;
|
||||||
int status;
|
int status;
|
||||||
subOpts.isTail = 0;
|
subOpts.isTail = 0;
|
||||||
subOpts.resultUnused = 0;
|
subOpts.resultUnused = 0;
|
||||||
status = symbol_resolve(c, left, &level, &target, &lit);
|
status = symbol_resolve(c, left, &level, &target, &flags, &lit);
|
||||||
if (status == 2) {
|
if (status == 1) {
|
||||||
c_error(c, "cannot set binding");
|
if (!(flags & GST_LOCAL_FLAG_MUTABLE))
|
||||||
} else if (status == 1) {
|
c_error(c, "cannot varset immutable binding");
|
||||||
/* Check if we have an up value. Otherwise, it's just a normal
|
/* Check if we have an up value. Otherwise, it's just a normal
|
||||||
* local variable */
|
* local variable */
|
||||||
if (level != 0) {
|
if (level != 0) {
|
||||||
@ -547,11 +603,21 @@ static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstV
|
|||||||
subOpts.target = target;
|
subOpts.target = target;
|
||||||
slot = compile_value(c, subOpts, right);
|
slot = compile_value(c, subOpts, right);
|
||||||
}
|
}
|
||||||
|
} else if (status == 3) {
|
||||||
|
/* Global var */
|
||||||
|
const GstValue *tup;
|
||||||
|
Gst *vm= c->vm;
|
||||||
|
GstValue *t = gst_tuple_begin(vm, 4);
|
||||||
|
t[0] = gst_string_cv(vm, "set!"); /* Todo - replace with ref ro actual cfunc */
|
||||||
|
t[1] = quote(vm, lit);
|
||||||
|
t[2] = quote(vm, left);
|
||||||
|
t[3] = right;
|
||||||
|
tup = gst_tuple_end(vm, t);
|
||||||
|
subOpts.resultUnused = 1;
|
||||||
|
compile_value(c, subOpts, gst_wrap_tuple(tup));
|
||||||
|
return compile_value(c, opts, left);
|
||||||
} else {
|
} else {
|
||||||
/* We need to declare a new symbol */
|
c_error(c, "cannot varset immutable binding");
|
||||||
subOpts.target = compiler_declare_symbol(c, scope, left);
|
|
||||||
subOpts.canChoose = 0;
|
|
||||||
slot = compile_value(c, subOpts, right);
|
|
||||||
}
|
}
|
||||||
if (opts.resultUnused) {
|
if (opts.resultUnused) {
|
||||||
compiler_drop_slot(c, scope, slot);
|
compiler_drop_slot(c, scope, slot);
|
||||||
@ -561,6 +627,87 @@ static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set a var */
|
||||||
|
static Slot compile_varset(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
||||||
|
if (gst_tuple_length(form) != 3)
|
||||||
|
c_error(c, "expected 2 arguments to varset");
|
||||||
|
if (GST_STRING != form[1].type)
|
||||||
|
c_error(c, "expected symbol as first argument");
|
||||||
|
return compile_assign(c, opts, form[1], form[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global var */
|
||||||
|
static Slot compile_global_var(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
||||||
|
const GstValue *tup;
|
||||||
|
Gst *vm= c->vm;
|
||||||
|
GstValue *t = gst_tuple_begin(vm, 3);
|
||||||
|
GstValue *q = gst_tuple_begin(vm, 2);
|
||||||
|
q[0] = gst_string_cv(vm, "quote");
|
||||||
|
q[1] = form[1];
|
||||||
|
t[0] = gst_string_cv(vm, "global-var"); /* Todo - replace with ref ro actual cfunc */
|
||||||
|
t[1] = gst_wrap_tuple(gst_tuple_end(vm, q));
|
||||||
|
t[2] = form[2];
|
||||||
|
tup = gst_tuple_end(vm, t);
|
||||||
|
return compile_value(c, opts, gst_wrap_tuple(tup));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global define */
|
||||||
|
static Slot compile_global_def(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
||||||
|
const GstValue *tup;
|
||||||
|
Gst *vm= c->vm;
|
||||||
|
GstValue *t = gst_tuple_begin(vm, 3);
|
||||||
|
GstValue *q = gst_tuple_begin(vm, 2);
|
||||||
|
q[0] = gst_string_cv(vm, "quote");
|
||||||
|
q[1] = form[1];
|
||||||
|
t[0] = gst_string_cv(vm, "global-def"); /* Todo - replace with ref ro actual cfunc */
|
||||||
|
t[1] = gst_wrap_tuple(gst_tuple_end(vm, q));
|
||||||
|
t[2] = form[2];
|
||||||
|
tup = gst_tuple_end(vm, t);
|
||||||
|
return compile_value(c, opts, gst_wrap_tuple(tup));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compile def */
|
||||||
|
static Slot compile_def(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
||||||
|
GstScope *scope = c->tail;
|
||||||
|
if (gst_tuple_length(form) != 3)
|
||||||
|
c_error(c, "expected 2 arguments to def");
|
||||||
|
if (GST_STRING != form[1].type)
|
||||||
|
c_error(c, "expected symbol as first argument");
|
||||||
|
if (scope->parent) {
|
||||||
|
FormOptions subOpts;
|
||||||
|
Slot slot;
|
||||||
|
subOpts.isTail = opts.isTail;
|
||||||
|
subOpts.resultUnused = 0;
|
||||||
|
subOpts.canChoose = 0;
|
||||||
|
subOpts.target = compiler_declare_symbol(c, scope, form[1], 0);
|
||||||
|
slot = compile_value(c, subOpts, form[2]);
|
||||||
|
return compiler_coerce_slot(c, opts, slot);
|
||||||
|
} else {
|
||||||
|
return compile_global_def(c, opts, form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compile var */
|
||||||
|
static Slot compile_var(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
||||||
|
GstScope *scope = c->tail;
|
||||||
|
if (gst_tuple_length(form) != 3)
|
||||||
|
c_error(c, "expected 2 arguments to var");
|
||||||
|
if (GST_STRING != form[1].type)
|
||||||
|
c_error(c, "expected symbol as first argument");
|
||||||
|
if (scope->parent) {
|
||||||
|
FormOptions subOpts;
|
||||||
|
Slot slot;
|
||||||
|
subOpts.isTail = opts.isTail;
|
||||||
|
subOpts.resultUnused = 0;
|
||||||
|
subOpts.canChoose = 0;
|
||||||
|
subOpts.target = compiler_declare_symbol(c, scope, form[1], GST_LOCAL_FLAG_MUTABLE);
|
||||||
|
slot = compile_value(c, subOpts, form[2]);
|
||||||
|
return compiler_coerce_slot(c, opts, slot);
|
||||||
|
} else {
|
||||||
|
return compile_global_var(c, opts, form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Compile series of expressions. This compiles the meat of
|
/* Compile series of expressions. This compiles the meat of
|
||||||
* function definitions and the inside of do forms. */
|
* function definitions and the inside of do forms. */
|
||||||
static Slot compile_block(GstCompiler *c, FormOptions opts, const GstValue *form, uint32_t startIndex) {
|
static Slot compile_block(GstCompiler *c, FormOptions opts, const GstValue *form, uint32_t startIndex) {
|
||||||
@ -664,7 +811,7 @@ static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *f
|
|||||||
/* The compiler puts the parameter locals
|
/* The compiler puts the parameter locals
|
||||||
* in the right place by default - at the beginning
|
* in the right place by default - at the beginning
|
||||||
* of the stack frame. */
|
* of the stack frame. */
|
||||||
compiler_declare_symbol(c, subGstScope, param);
|
compiler_declare_symbol(c, subGstScope, param, 0);
|
||||||
}
|
}
|
||||||
/* Mark where we are on the stack so we can
|
/* Mark where we are on the stack so we can
|
||||||
* return to it later. */
|
* return to it later. */
|
||||||
@ -832,13 +979,6 @@ static Slot compile_quote(GstCompiler *c, FormOptions opts, const GstValue *form
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assignment special */
|
|
||||||
static Slot compile_var(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
|
||||||
if (gst_tuple_length(form) != 3)
|
|
||||||
c_error(c, "assignment expects 2 arguments");
|
|
||||||
return compile_assign(c, opts, form[1], form[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apply special */
|
/* Apply special */
|
||||||
static Slot compile_apply(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
static Slot compile_apply(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
||||||
GstScope *scope = c->tail;
|
GstScope *scope = c->tail;
|
||||||
@ -927,7 +1067,7 @@ static SpecialFormHelper get_special(const GstValue *form) {
|
|||||||
/* One character specials. */
|
/* One character specials. */
|
||||||
if (gst_string_length(name) == 1) {
|
if (gst_string_length(name) == 1) {
|
||||||
switch(name[0]) {
|
switch(name[0]) {
|
||||||
case ':': return compile_var;
|
case ':': return compile_def;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -950,6 +1090,10 @@ static SpecialFormHelper get_special(const GstValue *form) {
|
|||||||
if (gst_string_length(name) == 2 &&
|
if (gst_string_length(name) == 2 &&
|
||||||
name[1] == 'o') {
|
name[1] == 'o') {
|
||||||
return compile_do;
|
return compile_do;
|
||||||
|
} else if (gst_string_length(name) == 3 &&
|
||||||
|
name[1] == 'e' &&
|
||||||
|
name[2] == 'f') {
|
||||||
|
return compile_def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -990,6 +1134,23 @@ static SpecialFormHelper get_special(const GstValue *form) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'v':
|
||||||
|
{
|
||||||
|
if (gst_string_length(name) == 3 &&
|
||||||
|
name[1] == 'a' &&
|
||||||
|
name[2] == 'r') {
|
||||||
|
return compile_var;
|
||||||
|
}
|
||||||
|
if (gst_string_length(name) == 6 &&
|
||||||
|
name[1] == 'a' &&
|
||||||
|
name[2] == 'r' &&
|
||||||
|
name[3] == 's' &&
|
||||||
|
name[4] == 'e' &&
|
||||||
|
name[5] == 't') {
|
||||||
|
return compile_varset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
{
|
{
|
||||||
if (gst_string_length(name) == 5 &&
|
if (gst_string_length(name) == 5 &&
|
||||||
@ -1057,7 +1218,7 @@ static Slot compile_table(GstCompiler *c, FormOptions opts, GstTable *tab) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compile a form. Checks for special forms and macros. */
|
/* Compile a form. Checks for special forms. */
|
||||||
static Slot compile_form(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
static Slot compile_form(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
||||||
GstScope *scope = c->tail;
|
GstScope *scope = c->tail;
|
||||||
GstBuffer *buffer = c->buffer;
|
GstBuffer *buffer = c->buffer;
|
||||||
@ -1136,50 +1297,10 @@ void gst_compiler(GstCompiler *c, Gst *vm) {
|
|||||||
c->buffer = gst_buffer(vm, 128);
|
c->buffer = gst_buffer(vm, 128);
|
||||||
c->tail = NULL;
|
c->tail = NULL;
|
||||||
c->error.type = GST_NIL;
|
c->error.type = GST_NIL;
|
||||||
|
c->env = vm->env;
|
||||||
compiler_push_scope(c, 0);
|
compiler_push_scope(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a global variable */
|
|
||||||
void gst_compiler_global(GstCompiler *c, const char *name, GstValue x) {
|
|
||||||
GstScope *scope = c->tail;
|
|
||||||
GstValue sym = gst_string_cv(c->vm, name);
|
|
||||||
if (x.type == GST_NIL)
|
|
||||||
gst_table_put(c->vm, scope->nilNamedLiterals, sym, gst_wrap_boolean(1));
|
|
||||||
else
|
|
||||||
gst_table_put(c->vm, scope->namedLiterals, sym, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add many global variables */
|
|
||||||
void gst_compiler_globals(GstCompiler *c, GstValue env) {
|
|
||||||
GstScope *scope = c->tail;
|
|
||||||
const GstValue *data;
|
|
||||||
uint32_t len;
|
|
||||||
uint32_t i;
|
|
||||||
if (gst_hashtable_view(env, &data, &len))
|
|
||||||
for (i = 0; i < len; i += 2)
|
|
||||||
if (data[i].type == GST_STRING)
|
|
||||||
gst_table_put(c->vm, scope->namedLiterals, data[i], data[i + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add many global variables and bind to nil */
|
|
||||||
void gst_compiler_nilglobals(GstCompiler *c, GstValue env) {
|
|
||||||
GstScope *scope = c->tail;
|
|
||||||
const GstValue *data;
|
|
||||||
uint32_t len;
|
|
||||||
uint32_t i;
|
|
||||||
if (gst_hashtable_view(env, &data, &len))
|
|
||||||
for (i = 0; i < len; i += 2)
|
|
||||||
if (data[i].type == GST_STRING)
|
|
||||||
gst_table_put(c->vm, scope->namedLiterals, data[i], gst_wrap_nil());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Use a module that was loaded into the vm */
|
|
||||||
void gst_compiler_usemodule(GstCompiler *c, const char *modulename) {
|
|
||||||
GstValue mod = gst_table_get(c->vm->modules, gst_string_cv(c->vm, modulename));
|
|
||||||
gst_compiler_globals(c, mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compile interface. Returns a function that evaluates the
|
/* Compile interface. Returns a function that evaluates the
|
||||||
* given AST. Returns NULL if there was an error during compilation. */
|
* given AST. Returns NULL if there was an error during compilation. */
|
||||||
GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) {
|
GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) {
|
||||||
@ -1193,7 +1314,6 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) {
|
|||||||
c->error = gst_string_cv(c->vm, "unknown error");
|
c->error = gst_string_cv(c->vm, "unknown error");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Create a scope */
|
|
||||||
opts.isTail = 1;
|
opts.isTail = 1;
|
||||||
compiler_return(c, compile_value(c, opts, form));
|
compiler_return(c, compile_value(c, opts, form));
|
||||||
def = compiler_gen_funcdef(c, c->buffer->count, 0, 0);
|
def = compiler_gen_funcdef(c, c->buffer->count, 0, 0);
|
||||||
|
@ -276,6 +276,7 @@ void gst_collect(Gst *vm) {
|
|||||||
gst_mark_value(vm, gst_wrap_thread(vm->thread));
|
gst_mark_value(vm, gst_wrap_thread(vm->thread));
|
||||||
gst_mark_value(vm, gst_wrap_table(vm->modules));
|
gst_mark_value(vm, gst_wrap_table(vm->modules));
|
||||||
gst_mark_value(vm, gst_wrap_table(vm->registry));
|
gst_mark_value(vm, gst_wrap_table(vm->registry));
|
||||||
|
gst_mark_value(vm, gst_wrap_table(vm->env));
|
||||||
gst_mark_value(vm, vm->ret);
|
gst_mark_value(vm, vm->ret);
|
||||||
if (vm->scratch)
|
if (vm->scratch)
|
||||||
gc_header(vm->scratch)->color = vm->black;
|
gc_header(vm->scratch)->color = vm->black;
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include "cache.h"
|
||||||
|
|
||||||
/****/
|
/****/
|
||||||
/* Cache */
|
/* Cache */
|
||||||
|
40
core/stl.c
40
core/stl.c
@ -710,6 +710,28 @@ int gst_stl_funcparent(Gst *vm) {
|
|||||||
return GST_RETURN_OK;
|
return GST_RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gst_stl_def(Gst *vm) {
|
||||||
|
if (gst_count_args(vm) != 2) {
|
||||||
|
gst_c_throwc(vm, "expected 2 arguments to global-def");
|
||||||
|
}
|
||||||
|
if (GST_STRING != gst_arg(vm, 0).type) {
|
||||||
|
gst_c_throwc(vm, "expected string as first argument");
|
||||||
|
}
|
||||||
|
gst_env_put(vm, vm->env, gst_arg(vm, 0), gst_arg(vm, 1));
|
||||||
|
gst_c_return(vm, gst_arg(vm, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int gst_stl_var(Gst *vm) {
|
||||||
|
if (gst_count_args(vm) != 2) {
|
||||||
|
gst_c_throwc(vm, "expected 2 arguments to global-var");
|
||||||
|
}
|
||||||
|
if (GST_STRING != gst_arg(vm, 0).type) {
|
||||||
|
gst_c_throwc(vm, "expected string as first argument");
|
||||||
|
}
|
||||||
|
gst_env_putvar(vm, vm->env, gst_arg(vm, 0), gst_arg(vm, 1));
|
||||||
|
gst_c_return(vm, gst_arg(vm, 1));
|
||||||
|
}
|
||||||
|
|
||||||
/****/
|
/****/
|
||||||
/* IO */
|
/* IO */
|
||||||
/****/
|
/****/
|
||||||
@ -1038,13 +1060,11 @@ static int gst_stl_parse(Gst *vm) {
|
|||||||
/* Compile a value */
|
/* Compile a value */
|
||||||
static int gst_stl_compile(Gst *vm) {
|
static int gst_stl_compile(Gst *vm) {
|
||||||
GstFunction *ret;
|
GstFunction *ret;
|
||||||
GstValue std;
|
|
||||||
GstCompiler c;
|
GstCompiler c;
|
||||||
gst_compiler(&c, vm);
|
gst_compiler(&c, vm);
|
||||||
std = gst_table_get(vm->modules, gst_string_cv(vm, "std"));
|
if (gst_arg(vm, 1).type == GST_TABLE) {
|
||||||
gst_compiler_globals(&c, std);
|
c.env = gst_arg(vm, 1).data.table;
|
||||||
gst_compiler_globals(&c, gst_arg(vm, 1));
|
}
|
||||||
gst_compiler_nilglobals(&c, gst_arg(vm, 2));
|
|
||||||
ret = gst_compiler_compile(&c, gst_arg(vm, 0));
|
ret = gst_compiler_compile(&c, gst_arg(vm, 0));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
gst_c_throw(vm, c.error);
|
gst_c_throw(vm, c.error);
|
||||||
@ -1086,8 +1106,8 @@ static const GstModuleItem std_module[] = {
|
|||||||
{"parse-hasvalue", gst_stl_parser_hasvalue},
|
{"parse-hasvalue", gst_stl_parser_hasvalue},
|
||||||
{"parse-charseq", gst_stl_parser_charseq},
|
{"parse-charseq", gst_stl_parser_charseq},
|
||||||
{"parse-status", gst_stl_parser_status},
|
{"parse-status", gst_stl_parser_status},
|
||||||
{"parse-status", gst_stl_parser_status},
|
{"parse-status", gst_stl_parser_status},
|
||||||
{"parse", gst_stl_parse},
|
{"parse", gst_stl_parse},
|
||||||
/* Compile */
|
/* Compile */
|
||||||
{"compile", gst_stl_compile},
|
{"compile", gst_stl_compile},
|
||||||
/* Other */
|
/* Other */
|
||||||
@ -1134,11 +1154,14 @@ static const GstModuleItem std_module[] = {
|
|||||||
{"funcparent", gst_stl_funcparent},
|
{"funcparent", gst_stl_funcparent},
|
||||||
{"gcollect", gst_stl_gcollect},
|
{"gcollect", gst_stl_gcollect},
|
||||||
{"debugp", gst_stl_debugp},
|
{"debugp", gst_stl_debugp},
|
||||||
|
{"global-def", gst_stl_def},
|
||||||
|
{"global-var", gst_stl_var},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Load all libraries */
|
/* Load all libraries */
|
||||||
void gst_stl_load(Gst *vm) {
|
void gst_stl_load(Gst *vm) {
|
||||||
|
GstValue maybeEnv;
|
||||||
/* Load the normal c functions */
|
/* Load the normal c functions */
|
||||||
gst_module_mutable(vm, "std", std_module);
|
gst_module_mutable(vm, "std", std_module);
|
||||||
/* Wrap stdin and stdout */
|
/* Wrap stdin and stdout */
|
||||||
@ -1151,4 +1174,7 @@ void gst_stl_load(Gst *vm) {
|
|||||||
gst_module_put(vm, "std", "stdin", gst_wrap_userdata(inp));
|
gst_module_put(vm, "std", "stdin", gst_wrap_userdata(inp));
|
||||||
gst_module_put(vm, "std", "stdout", gst_wrap_userdata(outp));
|
gst_module_put(vm, "std", "stdout", gst_wrap_userdata(outp));
|
||||||
gst_module_put(vm, "std", "stderr", gst_wrap_userdata(outp));
|
gst_module_put(vm, "std", "stderr", gst_wrap_userdata(outp));
|
||||||
|
maybeEnv = gst_table_get(vm->modules, gst_string_cv(vm, "std"));
|
||||||
|
if (maybeEnv.type == GST_TABLE)
|
||||||
|
gst_env_merge(vm, vm->env, maybeEnv.data.table);
|
||||||
}
|
}
|
||||||
|
106
core/util.c
106
core/util.c
@ -252,3 +252,109 @@ int gst_callc(Gst *vm, GstCFunction fn, int numargs, ...) {
|
|||||||
gst_thread_popframe(vm, vm->thread);
|
gst_thread_popframe(vm, vm->thread);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstTable *gst_env_inttab(Gst *vm, GstTable *env, GstInteger i) {
|
||||||
|
GstTable *tab;
|
||||||
|
GstValue key = gst_wrap_integer(i);
|
||||||
|
GstValue maybeTab = gst_table_get(env, key);
|
||||||
|
if (maybeTab.type != GST_TABLE) {
|
||||||
|
tab = gst_table(vm, 10);
|
||||||
|
gst_table_put(vm, env, key, gst_wrap_table(tab));
|
||||||
|
} else {
|
||||||
|
tab = maybeTab.data.table;
|
||||||
|
}
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstTable *gst_env_nils(Gst *vm, GstTable *env) {
|
||||||
|
return gst_env_inttab(vm, env, GST_ENV_NILS);
|
||||||
|
}
|
||||||
|
|
||||||
|
GstTable *gst_env_meta(Gst *vm, GstTable *env) {
|
||||||
|
return gst_env_inttab(vm, env, GST_ENV_METADATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
GstTable *gst_env_vars(Gst *vm, GstTable *env) {
|
||||||
|
return gst_env_inttab(vm, env, GST_ENV_VARS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add many global variables and bind to nil */
|
||||||
|
static void mergenils(Gst *vm, GstTable *destEnv, GstTable *nils) {
|
||||||
|
const GstValue *data = nils->data;
|
||||||
|
uint32_t len = nils->capacity;
|
||||||
|
uint32_t i;
|
||||||
|
GstTable *destNils = gst_env_nils(vm, destEnv);
|
||||||
|
for (i = 0; i < len; i += 2) {
|
||||||
|
if (data[i].type == GST_STRING) {
|
||||||
|
gst_table_put(vm, destEnv, data[i], gst_wrap_nil());
|
||||||
|
gst_table_put(vm, destNils, data[i], gst_wrap_boolean(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add many global variable metadata */
|
||||||
|
static void mergemeta(Gst *vm, GstTable *destEnv, GstTable *meta) {
|
||||||
|
const GstValue *data = meta->data;
|
||||||
|
uint32_t len = meta->capacity;
|
||||||
|
uint32_t i;
|
||||||
|
GstTable *destMeta = gst_env_meta(vm, destEnv);
|
||||||
|
for (i = 0; i < len; i += 2) {
|
||||||
|
if (data[i].type == GST_STRING) {
|
||||||
|
gst_table_put(vm, destMeta, data[i], data[i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add many global variables */
|
||||||
|
void gst_env_merge(Gst *vm, GstTable *destEnv, GstTable *srcEnv) {
|
||||||
|
const GstValue *data = srcEnv->data;
|
||||||
|
uint32_t len = srcEnv->capacity;
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < len; i += 2) {
|
||||||
|
if (data[i].type == GST_STRING) {
|
||||||
|
gst_table_put(vm, destEnv, data[i], data[i + 1]);
|
||||||
|
} else if (data[i].type == GST_INTEGER) {
|
||||||
|
switch (data[i].data.integer) {
|
||||||
|
case GST_ENV_NILS:
|
||||||
|
if (data[i + 1].type == GST_TABLE)
|
||||||
|
mergenils(vm, destEnv, data[i + 1].data.table);
|
||||||
|
break;
|
||||||
|
case GST_ENV_METADATA:
|
||||||
|
if (data[i + 1].type == GST_TABLE)
|
||||||
|
mergemeta(vm, destEnv, data[i + 1].data.table);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gst_env_put(Gst *vm, GstTable *env, GstValue key, GstValue value) {
|
||||||
|
GstTable *meta = gst_env_meta(vm, env);
|
||||||
|
gst_table_put(vm, meta, key, gst_wrap_nil());
|
||||||
|
gst_table_put(vm, env, key, value);
|
||||||
|
if (value.type == GST_NIL) {
|
||||||
|
gst_table_put(vm, gst_env_nils(vm, env), key, gst_wrap_boolean(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gst_env_putc(Gst *vm, GstTable *env, const char *key, GstValue value) {
|
||||||
|
GstValue keyv = gst_string_cv(vm, key);
|
||||||
|
gst_env_put(vm, env, keyv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gst_env_putvar(Gst *vm, GstTable *env, GstValue key, GstValue value) {
|
||||||
|
GstTable *meta = gst_env_meta(vm, env);
|
||||||
|
GstTable *newmeta = gst_table(vm, 4);
|
||||||
|
GstTable *vars = gst_env_vars(vm, env);
|
||||||
|
gst_table_put(vm, vars, key, value);
|
||||||
|
gst_table_put(vm, env, key, gst_wrap_table(vars));
|
||||||
|
gst_table_put(vm, newmeta, gst_string_cv(vm, "mutable"), gst_wrap_boolean(1));
|
||||||
|
gst_table_put(vm, meta, key, gst_wrap_table(newmeta));
|
||||||
|
}
|
||||||
|
|
||||||
|
void gst_env_putvarc(Gst *vm, GstTable *env, const char *key, GstValue value) {
|
||||||
|
GstValue keyv = gst_string_cv(vm, key);
|
||||||
|
gst_env_putvar(vm, env, keyv, value);
|
||||||
|
}
|
@ -481,6 +481,7 @@ void gst_init(Gst *vm) {
|
|||||||
/* Set up global env */
|
/* Set up global env */
|
||||||
vm->modules = gst_table(vm, 10);
|
vm->modules = gst_table(vm, 10);
|
||||||
vm->registry = gst_table(vm, 10);
|
vm->registry = gst_table(vm, 10);
|
||||||
|
vm->env = gst_table(vm, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear all memory associated with the VM */
|
/* Clear all memory associated with the VM */
|
||||||
|
@ -312,6 +312,7 @@ struct Gst {
|
|||||||
GstThread *thread;
|
GstThread *thread;
|
||||||
GstTable *modules;
|
GstTable *modules;
|
||||||
GstTable *registry;
|
GstTable *registry;
|
||||||
|
GstTable *env;
|
||||||
/* Return state */
|
/* Return state */
|
||||||
const char *crash;
|
const char *crash;
|
||||||
GstValue ret; /* Returned value from gst_start. */
|
GstValue ret; /* Returned value from gst_start. */
|
||||||
@ -371,6 +372,7 @@ struct GstCompiler {
|
|||||||
jmp_buf onError;
|
jmp_buf onError;
|
||||||
GstScope *tail;
|
GstScope *tail;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
GstTable *env;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Bytecode */
|
/* Bytecode */
|
||||||
@ -398,7 +400,7 @@ enum GstOpCode {
|
|||||||
GST_OP_PAR, /* Push array or tuple */
|
GST_OP_PAR, /* Push array or tuple */
|
||||||
GST_OP_CAL, /* Call function */
|
GST_OP_CAL, /* Call function */
|
||||||
GST_OP_TCL, /* Tail call */
|
GST_OP_TCL, /* Tail call */
|
||||||
GST_OP_TRN, /* Transfer to new thread */
|
GST_OP_TRN /* Transfer to new thread */
|
||||||
};
|
};
|
||||||
|
|
||||||
/****/
|
/****/
|
||||||
@ -533,10 +535,8 @@ GstValue gst_parse_consume(GstParser *p);
|
|||||||
/***/
|
/***/
|
||||||
|
|
||||||
void gst_compiler(GstCompiler *c, Gst *vm);
|
void gst_compiler(GstCompiler *c, Gst *vm);
|
||||||
void gst_compiler_nilglobals(GstCompiler *c, GstValue env);
|
void gst_compiler_mergeenv(GstCompiler *c, GstValue env);
|
||||||
void gst_compiler_globals(GstCompiler *c, GstValue env);
|
|
||||||
void gst_compiler_global(GstCompiler *c, const char *name, GstValue x);
|
void gst_compiler_global(GstCompiler *c, const char *name, GstValue x);
|
||||||
void gst_compiler_usemodule(GstCompiler *c, const char *modulename);
|
|
||||||
GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form);
|
GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form);
|
||||||
|
|
||||||
/****/
|
/****/
|
||||||
@ -634,9 +634,21 @@ int gst_hashtable_view(GstValue tab, const GstValue **data, uint32_t *cap);
|
|||||||
/* Misc */
|
/* Misc */
|
||||||
/****/
|
/****/
|
||||||
|
|
||||||
|
#define GST_ENV_NILS 0
|
||||||
|
#define GST_ENV_METADATA 1
|
||||||
|
#define GST_ENV_VARS 2
|
||||||
|
|
||||||
GstReal gst_integer_to_real(GstInteger x);
|
GstReal gst_integer_to_real(GstInteger x);
|
||||||
GstInteger gst_real_to_integer(GstReal x);
|
GstInteger gst_real_to_integer(GstReal x);
|
||||||
GstInteger gst_startrange(GstInteger raw, uint32_t len);
|
GstInteger gst_startrange(GstInteger raw, uint32_t len);
|
||||||
GstInteger gst_endrange(GstInteger raw, uint32_t len);
|
GstInteger gst_endrange(GstInteger raw, uint32_t len);
|
||||||
|
void gst_env_merge(Gst *vm, GstTable *destEnv, GstTable *srcEnv);
|
||||||
|
GstTable *gst_env_nils(Gst *vm, GstTable *env);
|
||||||
|
GstTable *gst_env_meta(Gst *vm, GstTable *env);
|
||||||
|
GstTable *gst_env_vars(Gst *vm, GstTable *env);
|
||||||
|
void gst_env_put(Gst *vm, GstTable *env, GstValue key, GstValue value);
|
||||||
|
void gst_env_putc(Gst *vm, GstTable *env, const char *key, GstValue value);
|
||||||
|
void gst_env_putvar(Gst *vm, GstTable *env, GstValue key, GstValue value);
|
||||||
|
void gst_env_putvarc(Gst *vm, GstTable *env, const char *key, GstValue value);
|
||||||
|
|
||||||
#endif // GST_H_defined
|
#endif // GST_H_defined
|
||||||
|
Loading…
Reference in New Issue
Block a user