mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 18:56:38 +00:00
Berry update internal type system
This commit is contained in:
parent
3d2c9945a8
commit
a9dfd284bb
@ -34,19 +34,19 @@ static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib)
|
|||||||
while (lib->name) {
|
while (lib->name) {
|
||||||
bstring *s = be_newstr(vm, lib->name);
|
bstring *s = be_newstr(vm, lib->name);
|
||||||
if (lib->function) { /* method */
|
if (lib->function) { /* method */
|
||||||
be_prim_method_bind(vm, c, s, lib->function);
|
be_class_native_method_bind(vm, c, s, lib->function);
|
||||||
} else {
|
} else {
|
||||||
be_member_bind(vm, c, s, btrue); /* member */
|
be_class_member_bind(vm, c, s, btrue); /* member */
|
||||||
}
|
}
|
||||||
++lib;
|
++lib;
|
||||||
}
|
}
|
||||||
if (lib->function == (bntvfunc) BE_CLOSURE) {
|
if (lib->function == (bntvfunc)BE_CLOSURE) {
|
||||||
/* next section is closures */
|
/* next section is closures */
|
||||||
struct solidfuncinfo *slib = (struct solidfuncinfo*)++lib;
|
struct solidfuncinfo *slib = (struct solidfuncinfo*)++lib;
|
||||||
while (slib->name) {
|
while (slib->name) {
|
||||||
if (slib->function) { /* method */
|
if (slib->function) { /* method */
|
||||||
bstring *s = be_newstr(vm, slib->name);
|
bstring *s = be_newstr(vm, slib->name);
|
||||||
be_closure_method_bind(vm, c, s, slib->function);
|
be_class_closure_method_bind(vm, c, s, slib->function);
|
||||||
}
|
}
|
||||||
++slib;
|
++slib;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ static bclass *find_class_closure(bclass *cl, bclosure *needle)
|
|||||||
if (members) { /* only iterate if there are members */
|
if (members) { /* only iterate if there are members */
|
||||||
bmapiter iter = be_map_iter();
|
bmapiter iter = be_map_iter();
|
||||||
while ((node = be_map_next(members, &iter)) != NULL) {
|
while ((node = be_map_next(members, &iter)) != NULL) {
|
||||||
if (var_type(&node->value) == BE_CLOSURE) { /* only native functions are considered */
|
if (var_primetype(&node->value) == BE_CLOSURE) { /* only native functions are considered */
|
||||||
bclosure *clos_iter = var_toobj(&node->value); /* retrieve the method's closure */
|
bclosure *clos_iter = var_toobj(&node->value); /* retrieve the method's closure */
|
||||||
if (clos_iter == needle) {
|
if (clos_iter == needle) {
|
||||||
/* we found the closure, we now know its class */
|
/* we found the closure, we now know its class */
|
||||||
@ -140,7 +140,7 @@ static int l_super(bvm *vm)
|
|||||||
if (size >= 2) { /* need at least 2 stackframes: current (for super() native) and caller (the one we are interested in) */
|
if (size >= 2) { /* need at least 2 stackframes: current (for super() native) and caller (the one we are interested in) */
|
||||||
bcallframe *caller = be_vector_at(&vm->callstack, size - 2); /* get the callframe of caller */
|
bcallframe *caller = be_vector_at(&vm->callstack, size - 2); /* get the callframe of caller */
|
||||||
bvalue *func = caller->func; /* function object of caller */
|
bvalue *func = caller->func; /* function object of caller */
|
||||||
if (var_type(func) == BE_CLOSURE) { /* only useful if the caller is a Berry closure (i.e. not native) */
|
if (var_primetype(func) == BE_CLOSURE) { /* only useful if the caller is a Berry closure (i.e. not native) */
|
||||||
bclosure *clos_ctx = var_toobj(func); /* this is the closure we look for in the class chain */
|
bclosure *clos_ctx = var_toobj(func); /* this is the closure we look for in the class chain */
|
||||||
base_class = find_class_closure(o->_class, clos_ctx); /* iterate on current and super classes to find where the closure belongs */
|
base_class = find_class_closure(o->_class, clos_ctx); /* iterate on current and super classes to find where the closure belongs */
|
||||||
}
|
}
|
||||||
|
@ -176,8 +176,8 @@ static void save_class(bvm *vm, void *fp, bclass *c)
|
|||||||
|
|
||||||
static void save_value(bvm *vm, void *fp, bvalue *v)
|
static void save_value(bvm *vm, void *fp, bvalue *v)
|
||||||
{
|
{
|
||||||
save_byte(fp, (uint8_t)var_type(v)); /* type */
|
save_byte(fp, (uint8_t)var_primetype(v)); /* type */
|
||||||
switch (var_type(v)) {
|
switch (var_primetype(v)) {
|
||||||
case BE_INT: save_int(fp, var_toint(v)); break;
|
case BE_INT: save_int(fp, var_toint(v)); break;
|
||||||
case BE_REAL: save_real(fp, var_toreal(v)); break;
|
case BE_REAL: save_real(fp, var_toreal(v)); break;
|
||||||
case BE_STRING: save_string(fp, var_tostr(v)); break;
|
case BE_STRING: save_string(fp, var_tostr(v)); break;
|
||||||
@ -425,16 +425,16 @@ static void load_class(bvm *vm, void *fp, bvalue *v, int version)
|
|||||||
be_incrtop(vm);
|
be_incrtop(vm);
|
||||||
if (load_proto(vm, fp, (bproto**)&var_toobj(value), -3, version)) {
|
if (load_proto(vm, fp, (bproto**)&var_toobj(value), -3, version)) {
|
||||||
/* actual method */
|
/* actual method */
|
||||||
be_method_bind(vm, c, name, var_toobj(value), bfalse);
|
be_class_method_bind(vm, c, name, var_toobj(value), bfalse);
|
||||||
} else {
|
} else {
|
||||||
/* no proto, static member set to nil */
|
/* no proto, static member set to nil */
|
||||||
be_member_bind(vm, c, name, bfalse);
|
be_class_member_bind(vm, c, name, bfalse);
|
||||||
}
|
}
|
||||||
be_stackpop(vm, 2); /* pop the cached string and proto */
|
be_stackpop(vm, 2); /* pop the cached string and proto */
|
||||||
}
|
}
|
||||||
for (count = 0; count < nvar; ++count) { /* load member-variable table */
|
for (count = 0; count < nvar; ++count) { /* load member-variable table */
|
||||||
bstring *name = cache_string(vm, fp);
|
bstring *name = cache_string(vm, fp);
|
||||||
be_member_bind(vm, c, name, btrue);
|
be_class_member_bind(vm, c, name, btrue);
|
||||||
be_stackpop(vm, 1); /* pop the cached string */
|
be_stackpop(vm, 1); /* pop the cached string */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
********************************************************************/
|
********************************************************************/
|
||||||
#include "be_class.h"
|
#include "be_class.h"
|
||||||
#include "be_string.h"
|
#include "be_string.h"
|
||||||
#include "be_vector.h"
|
|
||||||
#include "be_map.h"
|
#include "be_map.h"
|
||||||
#include "be_exec.h"
|
#include "be_exec.h"
|
||||||
#include "be_gc.h"
|
#include "be_gc.h"
|
||||||
#include "be_vm.h"
|
#include "be_vm.h"
|
||||||
#include "be_func.h"
|
#include "be_func.h"
|
||||||
#include "be_var.h"
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define check_members(vm, c) \
|
#define check_members(vm, c) \
|
||||||
@ -44,6 +42,7 @@ void be_class_compress(bvm *vm, bclass *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the type of the class attribute, only used to check if the attribute already exists */
|
||||||
int be_class_attribute(bvm *vm, bclass *c, bstring *attr)
|
int be_class_attribute(bvm *vm, bclass *c, bstring *attr)
|
||||||
{
|
{
|
||||||
for (; c; c = c->super) {
|
for (; c; c = c->super) {
|
||||||
@ -57,7 +56,7 @@ int be_class_attribute(bvm *vm, bclass *c, bstring *attr)
|
|||||||
return BE_NONE;
|
return BE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var)
|
void be_class_member_bind(bvm *vm, bclass *c, bstring *name, bbool var)
|
||||||
{
|
{
|
||||||
bvalue *attr;
|
bvalue *attr;
|
||||||
set_fixed(name);
|
set_fixed(name);
|
||||||
@ -75,7 +74,7 @@ void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static)
|
void be_class_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static)
|
||||||
{
|
{
|
||||||
bclosure *cl;
|
bclosure *cl;
|
||||||
bvalue *attr;
|
bvalue *attr;
|
||||||
@ -88,11 +87,11 @@ void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_stati
|
|||||||
cl->proto = p;
|
cl->proto = p;
|
||||||
var_setclosure(attr, cl);
|
var_setclosure(attr, cl);
|
||||||
if (is_static) {
|
if (is_static) {
|
||||||
func_setstatic(attr);
|
var_markstatic(attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f)
|
void be_class_native_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f)
|
||||||
{
|
{
|
||||||
bvalue *attr;
|
bvalue *attr;
|
||||||
set_fixed(name);
|
set_fixed(name);
|
||||||
@ -103,7 +102,7 @@ void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f)
|
|||||||
attr->type = MT_PRIMMETHOD;
|
attr->type = MT_PRIMMETHOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl)
|
void be_class_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl)
|
||||||
{
|
{
|
||||||
bvalue *attr;
|
bvalue *attr;
|
||||||
check_members(vm, c);
|
check_members(vm, c);
|
||||||
@ -242,7 +241,8 @@ bbool be_class_newobj(bvm *vm, bclass *c, int pos, int argc, int mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Default empty constructor */
|
/* Default empty constructor */
|
||||||
static int default_init_native_method(bvm *vm) {
|
static int default_init_native_method(bvm *vm)
|
||||||
|
{
|
||||||
be_return_nil(vm);
|
be_return_nil(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,10 +253,11 @@ int be_instance_member_simple(bvm *vm, binstance *instance, bstring *name, bvalu
|
|||||||
int type;
|
int type;
|
||||||
be_assert(name != NULL);
|
be_assert(name != NULL);
|
||||||
binstance * obj = instance_member(vm, instance, name, dst);
|
binstance * obj = instance_member(vm, instance, name, dst);
|
||||||
type = var_type(dst);
|
if (obj && var_type(dst) == MT_VARIABLE) {
|
||||||
if (obj && type == MT_VARIABLE) {
|
|
||||||
*dst = obj->members[dst->v.i];
|
*dst = obj->members[dst->v.i];
|
||||||
}
|
}
|
||||||
|
type = var_type(dst);
|
||||||
|
var_clearstatic(dst);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,18 +269,19 @@ int be_instance_member(bvm *vm, binstance *instance, bstring *name, bvalue *dst)
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
be_assert(name != NULL);
|
be_assert(name != NULL);
|
||||||
binstance * obj = instance_member(vm, instance, name, dst);
|
binstance *obj = instance_member(vm, instance, name, dst);
|
||||||
type = var_type(dst);
|
if (obj && var_type(dst) == MT_VARIABLE) {
|
||||||
if (obj && type == MT_VARIABLE) {
|
|
||||||
*dst = obj->members[dst->v.i];
|
*dst = obj->members[dst->v.i];
|
||||||
}
|
}
|
||||||
|
type = var_type(dst);
|
||||||
if (obj) {
|
if (obj) {
|
||||||
|
var_clearstatic(dst);
|
||||||
return type;
|
return type;
|
||||||
} else { /* if no method found, try virtual */
|
} else { /* if no method found, try virtual */
|
||||||
/* if 'init' does not exist, create a virtual empty constructor */
|
/* if 'init' does not exist, create a virtual empty constructor */
|
||||||
if (strcmp(str(name), "init") == 0) {
|
if (strcmp(str(name), "init") == 0) {
|
||||||
var_setntvfunc(dst, default_init_native_method);
|
var_setntvfunc(dst, default_init_native_method);
|
||||||
return var_type(dst);
|
return var_primetype(dst);
|
||||||
} else {
|
} else {
|
||||||
/* get method 'member' */
|
/* get method 'member' */
|
||||||
obj = instance_member(vm, instance, str_literal(vm, "member"), vm->top);
|
obj = instance_member(vm, instance, str_literal(vm, "member"), vm->top);
|
||||||
@ -296,6 +298,7 @@ int be_instance_member(bvm *vm, binstance *instance, bstring *name, bvalue *dst)
|
|||||||
}
|
}
|
||||||
type = var_type(dst);
|
type = var_type(dst);
|
||||||
if (type != BE_NIL) {
|
if (type != BE_NIL) {
|
||||||
|
var_clearstatic(dst);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,11 +313,8 @@ int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst)
|
|||||||
be_assert(name != NULL);
|
be_assert(name != NULL);
|
||||||
obj = class_member(vm, obj, name, dst);
|
obj = class_member(vm, obj, name, dst);
|
||||||
type = var_type(dst);
|
type = var_type(dst);
|
||||||
if (obj) {
|
var_clearstatic(dst);
|
||||||
return type;
|
return obj ? type : BE_NONE;
|
||||||
} else {
|
|
||||||
return BE_NONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bbool be_instance_setmember(bvm *vm, binstance *o, bstring *name, bvalue *src)
|
bbool be_instance_setmember(bvm *vm, binstance *o, bstring *name, bvalue *src)
|
||||||
|
@ -52,17 +52,17 @@ struct binstance {
|
|||||||
bclass* be_newclass(bvm *vm, bstring *name, bclass *super);
|
bclass* be_newclass(bvm *vm, bstring *name, bclass *super);
|
||||||
void be_class_compress(bvm *vm, bclass *c);
|
void be_class_compress(bvm *vm, bclass *c);
|
||||||
int be_class_attribute(bvm *vm, bclass *c, bstring *attr);
|
int be_class_attribute(bvm *vm, bclass *c, bstring *attr);
|
||||||
void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var);
|
void be_class_member_bind(bvm *vm, bclass *c, bstring *name, bbool var);
|
||||||
void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static);
|
void be_class_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static);
|
||||||
void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f);
|
void be_class_native_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f);
|
||||||
void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl);
|
void be_class_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl);
|
||||||
|
int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst);
|
||||||
|
bbool be_class_setmember(bvm *vm, bclass *obj, bstring *name, bvalue *src);
|
||||||
int be_class_closure_count(bclass *c);
|
int be_class_closure_count(bclass *c);
|
||||||
void be_class_upvalue_init(bvm *vm, bclass *c);
|
void be_class_upvalue_init(bvm *vm, bclass *c);
|
||||||
bbool be_class_newobj(bvm *vm, bclass *c, int pos, int argc, int mode);
|
bbool be_class_newobj(bvm *vm, bclass *c, int pos, int argc, int mode);
|
||||||
int be_instance_member_simple(bvm *vm, binstance *obj, bstring *name, bvalue *dst);
|
int be_instance_member_simple(bvm *vm, binstance *obj, bstring *name, bvalue *dst);
|
||||||
int be_instance_member(bvm *vm, binstance *obj, bstring *name, bvalue *dst);
|
int be_instance_member(bvm *vm, binstance *obj, bstring *name, bvalue *dst);
|
||||||
int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst);
|
|
||||||
bbool be_instance_setmember(bvm *vm, binstance *obj, bstring *name, bvalue *src);
|
bbool be_instance_setmember(bvm *vm, binstance *obj, bstring *name, bvalue *src);
|
||||||
bbool be_class_setmember(bvm *vm, bclass *obj, bstring *name, bvalue *src);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,7 +40,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define be_const_static_func(_func) { \
|
#define be_const_static_func(_func) { \
|
||||||
.v.nf = (_func), \
|
.v.nf = (_func), \
|
||||||
.type = BE_NTVFUNC | BE_FUNC_STATIC \
|
.type = BE_NTVFUNC | BE_STATIC \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define be_const_nil() { \
|
#define be_const_nil() { \
|
||||||
@ -79,7 +79,7 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define be_const_comptr(_val) { \
|
#define be_const_comptr(_val) { \
|
||||||
.v.c = (const void*)(_val), \
|
.v.c = (const void*)(_val), \
|
||||||
.type = BE_COMPTR \
|
.type = BE_COMPTR \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define be_const_static_closure(_closure) { \
|
#define be_const_static_closure(_closure) { \
|
||||||
.v.c = &(_closure), \
|
.v.c = &(_closure), \
|
||||||
.type = BE_CLOSURE | BE_FUNC_STATIC \
|
.type = BE_CLOSURE | BE_STATIC \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define be_const_module(_module) { \
|
#define be_const_module(_module) { \
|
||||||
@ -256,7 +256,7 @@ const bntvmodule be_native_module(_module) = { \
|
|||||||
|
|
||||||
#define be_const_static_func(_func) { \
|
#define be_const_static_func(_func) { \
|
||||||
bvaldata(_func), \
|
bvaldata(_func), \
|
||||||
BE_NTVFUNC | BE_FUNC_STATIC \
|
BE_NTVFUNC | BE_STATIC \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define be_const_nil() { \
|
#define be_const_nil() { \
|
||||||
@ -311,7 +311,7 @@ const bntvmodule be_native_module(_module) = { \
|
|||||||
|
|
||||||
#define be_const_static_closure(_closure) { \
|
#define be_const_static_closure(_closure) { \
|
||||||
bvaldata(&(_closure)), \
|
bvaldata(&(_closure)), \
|
||||||
BE_CLOSURE | BE_FUNC_STATIC \
|
BE_CLOSURE | BE_STATIC \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define be_const_module(_module) { \
|
#define be_const_module(_module) { \
|
||||||
|
@ -335,7 +335,7 @@ void be_stackpush(bvm *vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check that the stack is able to store `count` items, and increase stack if needed */
|
/* check that the stack is able to store `count` items, and increase stack if needed */
|
||||||
void be_stack_require(bvm *vm, int count)
|
BERRY_API void be_stack_require(bvm *vm, int count)
|
||||||
{
|
{
|
||||||
if (vm->top + count >= vm->stacktop) {
|
if (vm->top + count >= vm->stacktop) {
|
||||||
be_stack_expansion(vm, count);
|
be_stack_expansion(vm, count);
|
||||||
|
@ -138,7 +138,8 @@ static void mark_gray(bvm *vm, bgcobject *obj)
|
|||||||
{
|
{
|
||||||
if (obj && gc_iswhite(obj) && !gc_isconst(obj)) {
|
if (obj && gc_iswhite(obj) && !gc_isconst(obj)) {
|
||||||
gc_setgray(obj);
|
gc_setgray(obj);
|
||||||
switch (var_type(obj)) {
|
be_assert(!var_isstatic(obj));
|
||||||
|
switch (var_primetype(obj)) {
|
||||||
case BE_STRING: gc_setdark(obj); break; /* just set dark */
|
case BE_STRING: gc_setdark(obj); break; /* just set dark */
|
||||||
case BE_CLASS: link_gray(vm, cast_class(obj)); break;
|
case BE_CLASS: link_gray(vm, cast_class(obj)); break;
|
||||||
case BE_PROTO: link_gray(vm, cast_proto(obj)); break;
|
case BE_PROTO: link_gray(vm, cast_proto(obj)); break;
|
||||||
@ -171,7 +172,7 @@ static void mark_map(bvm *vm, bgcobject *obj)
|
|||||||
while ((node = be_map_next(map, &iter)) != NULL) {
|
while ((node = be_map_next(map, &iter)) != NULL) {
|
||||||
bmapkey *key = &node->key;
|
bmapkey *key = &node->key;
|
||||||
bvalue *val = &node->value;
|
bvalue *val = &node->value;
|
||||||
if (be_isgctype((signed char)key->type)) {
|
if (be_isgcobj(key)) {
|
||||||
mark_gray(vm, var_togc(key));
|
mark_gray(vm, var_togc(key));
|
||||||
}
|
}
|
||||||
mark_gray_var(vm, val);
|
mark_gray_var(vm, val);
|
||||||
@ -348,7 +349,7 @@ static void free_instance(bvm *vm, bgcobject *obj)
|
|||||||
|
|
||||||
static void free_object(bvm *vm, bgcobject *obj)
|
static void free_object(bvm *vm, bgcobject *obj)
|
||||||
{
|
{
|
||||||
switch (var_type(obj)) {
|
switch (var_primetype(obj)) {
|
||||||
case BE_STRING: free_lstring(vm, obj); break; /* long string */
|
case BE_STRING: free_lstring(vm, obj); break; /* long string */
|
||||||
case BE_CLASS: be_free(vm, obj, sizeof(bclass)); break;
|
case BE_CLASS: be_free(vm, obj, sizeof(bclass)); break;
|
||||||
case BE_INSTANCE: free_instance(vm, obj); break;
|
case BE_INSTANCE: free_instance(vm, obj); break;
|
||||||
@ -432,7 +433,8 @@ static void mark_unscanned(bvm *vm)
|
|||||||
bgcobject *obj = vm->gc.gray;
|
bgcobject *obj = vm->gc.gray;
|
||||||
if (obj && !gc_isdark(obj) && !gc_isconst(obj)) {
|
if (obj && !gc_isdark(obj) && !gc_isconst(obj)) {
|
||||||
gc_setdark(obj);
|
gc_setdark(obj);
|
||||||
switch (var_type(obj)) {
|
be_assert(!var_isstatic(obj));
|
||||||
|
switch (var_primetype(obj)) {
|
||||||
case BE_CLASS: mark_class(vm, obj); break;
|
case BE_CLASS: mark_class(vm, obj); break;
|
||||||
case BE_PROTO: mark_proto(vm, obj); break;
|
case BE_PROTO: mark_proto(vm, obj); break;
|
||||||
case BE_INSTANCE: mark_instance(vm, obj); break;
|
case BE_INSTANCE: mark_instance(vm, obj); break;
|
||||||
|
@ -47,8 +47,7 @@ if (!gc_isconst(o)) { \
|
|||||||
#define gc_exmark(o) (((o)->marked >> 4) & 0x0F)
|
#define gc_exmark(o) (((o)->marked >> 4) & 0x0F)
|
||||||
#define gc_setexmark(o, k) ((o)->marked |= (k) << 4)
|
#define gc_setexmark(o, k) ((o)->marked |= (k) << 4)
|
||||||
|
|
||||||
#define be_isgctype(t) ((t) >= BE_GCOBJECT)
|
#define be_isgcobj(o) (var_primetype(o) >= BE_GCOBJECT)
|
||||||
#define be_isgcobj(o) be_isgctype(var_type(o))
|
|
||||||
#define be_gcnew(v, t, s) be_newgcobj((v), (t), sizeof(s))
|
#define be_gcnew(v, t, s) be_newgcobj((v), (t), sizeof(s))
|
||||||
|
|
||||||
#define set_fixed(s) bbool _was_fixed = be_gc_fix_set(vm, cast(bgcobject*, (s)), 1)
|
#define set_fixed(s) bbool _was_fixed = be_gc_fix_set(vm, cast(bgcobject*, (s)), 1)
|
||||||
|
@ -329,10 +329,9 @@ int be_module_attr(bvm *vm, bmodule *module, bstring *attr, bvalue *dst)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return BE_NONE;
|
return BE_NONE;
|
||||||
} else {
|
|
||||||
*dst = *member;
|
|
||||||
return var_type(dst);
|
|
||||||
}
|
}
|
||||||
|
*dst = *member;
|
||||||
|
return var_type(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src)
|
bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
const char* be_vtype2str(bvalue *v)
|
const char* be_vtype2str(bvalue *v)
|
||||||
{
|
{
|
||||||
switch(var_type(v)) {
|
switch(var_primetype(v)) {
|
||||||
case BE_NIL: return "nil";
|
case BE_NIL: return "nil";
|
||||||
case BE_INT: return "int";
|
case BE_INT: return "int";
|
||||||
case BE_REAL: return "real";
|
case BE_REAL: return "real";
|
||||||
|
@ -11,14 +11,14 @@
|
|||||||
#include "berry.h"
|
#include "berry.h"
|
||||||
|
|
||||||
/* basic types, do not change value */
|
/* basic types, do not change value */
|
||||||
|
#define BE_NONE -256 /* unknown type */
|
||||||
#define BE_NIL 0
|
#define BE_NIL 0
|
||||||
#define BE_INT 1
|
#define BE_INT 1
|
||||||
#define BE_REAL 2
|
#define BE_REAL 2
|
||||||
#define BE_BOOL 3
|
#define BE_BOOL 3
|
||||||
#define BE_NONE 4 /* unknown type */
|
#define BE_COMPTR 4 /* common pointer */
|
||||||
#define BE_COMPTR 5 /* common pointer */
|
#define BE_INDEX 5 /* index for instance variable, previously BE_INT */
|
||||||
#define BE_INDEX 6 /* index for instance variable, previously BE_INT */
|
#define BE_FUNCTION 6
|
||||||
#define BE_FUNCTION 7
|
|
||||||
|
|
||||||
#define BE_GCOBJECT 16 /* from this type can be gced */
|
#define BE_GCOBJECT 16 /* from this type can be gced */
|
||||||
|
|
||||||
@ -35,11 +35,11 @@
|
|||||||
#define BE_CLOSURE ((1 << 5) | BE_FUNCTION)
|
#define BE_CLOSURE ((1 << 5) | BE_FUNCTION)
|
||||||
#define BE_NTVCLOS ((2 << 5) | BE_FUNCTION)
|
#define BE_NTVCLOS ((2 << 5) | BE_FUNCTION)
|
||||||
#define BE_CTYPE_FUNC ((3 << 5) | BE_FUNCTION)
|
#define BE_CTYPE_FUNC ((3 << 5) | BE_FUNCTION)
|
||||||
#define BE_FUNC_STATIC (1 << 7)
|
#define BE_STATIC (1 << 7)
|
||||||
|
|
||||||
#define func_isstatic(o) (((o)->type & BE_FUNC_STATIC) != 0)
|
#define func_isstatic(o) (((o)->type & BE_STATIC) != 0)
|
||||||
#define func_setstatic(o) ((o)->type |= BE_FUNC_STATIC)
|
#define func_setstatic(o) ((o)->type |= BE_STATIC)
|
||||||
#define func_clearstatic(o) ((o)->type &= ~BE_FUNC_STATIC)
|
#define func_clearstatic(o) ((o)->type &= ~BE_STATIC)
|
||||||
|
|
||||||
/* values for bproto.varg */
|
/* values for bproto.varg */
|
||||||
#define BE_VA_VARARG (1 << 0) /* function has variable number of arguments */
|
#define BE_VA_VARARG (1 << 0) /* function has variable number of arguments */
|
||||||
@ -201,10 +201,14 @@ typedef const char* (*breader)(void*, size_t*);
|
|||||||
#define cast_bool(_v) cast(bbool, _v)
|
#define cast_bool(_v) cast(bbool, _v)
|
||||||
#define basetype(_t) ((_t) & 0x1F)
|
#define basetype(_t) ((_t) & 0x1F)
|
||||||
|
|
||||||
#define var_type(_v) ((_v)->type & 0x7F)
|
#define var_type(_v) ((_v)->type)
|
||||||
#define var_basetype(_v) basetype((_v)->type)
|
#define var_basetype(_v) basetype((_v)->type)
|
||||||
#define var_istype(_v, _t) (var_type(_v) == _t)
|
#define var_primetype(_v) (var_type(_v) & ~BE_STATIC)
|
||||||
|
#define var_isstatic(_v) ((var_type(_v) & BE_STATIC) == BE_STATIC)
|
||||||
|
#define var_istype(_v, _t) (var_primetype(_v) == _t)
|
||||||
#define var_settype(_v, _t) ((_v)->type = _t)
|
#define var_settype(_v, _t) ((_v)->type = _t)
|
||||||
|
#define var_markstatic(_v) var_settype(_v, var_type(_v) | BE_STATIC)
|
||||||
|
#define var_clearstatic(_v) var_settype(_v, var_type(_v) & ~BE_STATIC)
|
||||||
#define var_setobj(_v, _t, _o) { (_v)->v.p = _o; var_settype(_v, _t); }
|
#define var_setobj(_v, _t, _o) { (_v)->v.p = _o; var_settype(_v, _t); }
|
||||||
|
|
||||||
#define var_isnil(_v) var_istype(_v, BE_NIL)
|
#define var_isnil(_v) var_istype(_v, BE_NIL)
|
||||||
@ -215,7 +219,6 @@ typedef const char* (*breader)(void*, size_t*);
|
|||||||
#define var_isclosure(_v) var_istype(_v, BE_CLOSURE)
|
#define var_isclosure(_v) var_istype(_v, BE_CLOSURE)
|
||||||
#define var_isntvclos(_v) var_istype(_v, BE_NTVCLOS)
|
#define var_isntvclos(_v) var_istype(_v, BE_NTVCLOS)
|
||||||
#define var_isntvfunc(_v) var_istype(_v, BE_NTVFUNC)
|
#define var_isntvfunc(_v) var_istype(_v, BE_NTVFUNC)
|
||||||
#define var_isctypefunc(_v) var_istype(_v, BE_CTYPEFUNC)
|
|
||||||
#define var_isfunction(_v) (var_basetype(_v) == BE_FUNCTION)
|
#define var_isfunction(_v) (var_basetype(_v) == BE_FUNCTION)
|
||||||
#define var_isproto(_v) var_istype(_v, BE_PROTO)
|
#define var_isproto(_v) var_istype(_v, BE_PROTO)
|
||||||
#define var_isclass(_v) var_istype(_v, BE_CLASS)
|
#define var_isclass(_v) var_istype(_v, BE_CLASS)
|
||||||
@ -238,11 +241,10 @@ typedef const char* (*breader)(void*, size_t*);
|
|||||||
#define var_setclosure(_v, _o) var_setobj(_v, BE_CLOSURE, _o)
|
#define var_setclosure(_v, _o) var_setobj(_v, BE_CLOSURE, _o)
|
||||||
#define var_setntvclos(_v, _o) var_setobj(_v, BE_NTVCLOS, _o)
|
#define var_setntvclos(_v, _o) var_setobj(_v, BE_NTVCLOS, _o)
|
||||||
#define var_setntvfunc(_v, _o) { (_v)->v.nf = (_o); var_settype(_v, BE_NTVFUNC); }
|
#define var_setntvfunc(_v, _o) { (_v)->v.nf = (_o); var_settype(_v, BE_NTVFUNC); }
|
||||||
#define var_setctypefunc(_v, _o) { (_v)->v.nf = (_o); var_settype(_v, BE_CTYPEFUNC); }
|
|
||||||
#define var_setlist(_v, _o) var_setobj(_v, BE_LIST, _o)
|
#define var_setlist(_v, _o) var_setobj(_v, BE_LIST, _o)
|
||||||
#define var_setmap(_v, _o) var_setobj(_v, BE_MAP, _o)
|
#define var_setmap(_v, _o) var_setobj(_v, BE_MAP, _o)
|
||||||
#define var_setmodule(_v, _o) var_setobj(_v, BE_MODULE, _o)
|
#define var_setmodule(_v, _o) var_setobj(_v, BE_MODULE, _o)
|
||||||
#define var_setindex(_v, _i) { var_settype(_v, BE_INDEX); (_v)->v.i = (_i); }
|
#define var_setindex(_v, _i) { var_settype(_v, BE_INDEX); (_v)->v.i = (_i); }
|
||||||
#define var_setproto(_v, _o) var_setobj(_v, BE_PROTO, _o)
|
#define var_setproto(_v, _o) var_setobj(_v, BE_PROTO, _o)
|
||||||
|
|
||||||
#define var_tobool(_v) ((_v)->v.b)
|
#define var_tobool(_v) ((_v)->v.b)
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "be_func.h"
|
#include "be_func.h"
|
||||||
#include "be_class.h"
|
#include "be_class.h"
|
||||||
#include "be_decoder.h"
|
#include "be_decoder.h"
|
||||||
#include "be_debug.h"
|
|
||||||
#include "be_exec.h"
|
#include "be_exec.h"
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
@ -1392,11 +1391,11 @@ static void classvar_stmt(bparser *parser, bclass *c)
|
|||||||
scan_next_token(parser); /* skip 'var' */
|
scan_next_token(parser); /* skip 'var' */
|
||||||
if (match_id(parser, name) != NULL) {
|
if (match_id(parser, name) != NULL) {
|
||||||
check_class_attr(parser, c, name);
|
check_class_attr(parser, c, name);
|
||||||
be_member_bind(parser->vm, c, name, btrue);
|
be_class_member_bind(parser->vm, c, name, btrue);
|
||||||
while (match_skip(parser, OptComma)) { /* ',' */
|
while (match_skip(parser, OptComma)) { /* ',' */
|
||||||
if (match_id(parser, name) != NULL) {
|
if (match_id(parser, name) != NULL) {
|
||||||
check_class_attr(parser, c, name);
|
check_class_attr(parser, c, name);
|
||||||
be_member_bind(parser->vm, c, name, btrue);
|
be_class_member_bind(parser->vm, c, name, btrue);
|
||||||
} else {
|
} else {
|
||||||
parser_error(parser, "class var error");
|
parser_error(parser, "class var error");
|
||||||
}
|
}
|
||||||
@ -1433,7 +1432,7 @@ static void classdef_stmt(bparser *parser, bclass *c, bbool is_static)
|
|||||||
name = func_name(parser, &e, 1);
|
name = func_name(parser, &e, 1);
|
||||||
check_class_attr(parser, c, name);
|
check_class_attr(parser, c, name);
|
||||||
proto = funcbody(parser, name, is_static ? 0 : FUNC_METHOD);
|
proto = funcbody(parser, name, is_static ? 0 : FUNC_METHOD);
|
||||||
be_method_bind(parser->vm, c, proto->name, proto, is_static);
|
be_class_method_bind(parser->vm, c, proto->name, proto, is_static);
|
||||||
be_stackpop(parser->vm, 1);
|
be_stackpop(parser->vm, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1446,13 +1445,13 @@ static void classstatic_stmt(bparser *parser, bclass *c, bexpdesc *e)
|
|||||||
classdef_stmt(parser, c, btrue);
|
classdef_stmt(parser, c, btrue);
|
||||||
} else if (match_id(parser, name) != NULL) {
|
} else if (match_id(parser, name) != NULL) {
|
||||||
check_class_attr(parser, c, name);
|
check_class_attr(parser, c, name);
|
||||||
be_member_bind(parser->vm, c, name, bfalse);
|
be_class_member_bind(parser->vm, c, name, bfalse);
|
||||||
class_static_assignment_expr(parser, e, name);
|
class_static_assignment_expr(parser, e, name);
|
||||||
|
|
||||||
while (match_skip(parser, OptComma)) { /* ',' */
|
while (match_skip(parser, OptComma)) { /* ',' */
|
||||||
if (match_id(parser, name) != NULL) {
|
if (match_id(parser, name) != NULL) {
|
||||||
check_class_attr(parser, c, name);
|
check_class_attr(parser, c, name);
|
||||||
be_member_bind(parser->vm, c, name, bfalse);
|
be_class_member_bind(parser->vm, c, name, bfalse);
|
||||||
class_static_assignment_expr(parser, e, name);
|
class_static_assignment_expr(parser, e, name);
|
||||||
} else {
|
} else {
|
||||||
parser_error(parser, "class static error");
|
parser_error(parser, "class static error");
|
||||||
|
@ -148,7 +148,7 @@ static void m_solidify_list(bvm *vm, blist * list, const char *class_name)
|
|||||||
// pass key name in case of class, or NULL if none
|
// pass key name in case of class, or NULL if none
|
||||||
static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, const char *key)
|
static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, const char *key)
|
||||||
{
|
{
|
||||||
int type = var_type(value);
|
int type = var_primetype(value);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BE_NIL:
|
case BE_NIL:
|
||||||
logfmt("be_const_nil()");
|
logfmt("be_const_nil()");
|
||||||
@ -197,7 +197,7 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
|
|||||||
char func_name_id[id_len];
|
char func_name_id[id_len];
|
||||||
toidentifier(func_name_id, func_name);
|
toidentifier(func_name_id, func_name);
|
||||||
logfmt("be_const_%sclosure(%s%s%s_closure)",
|
logfmt("be_const_%sclosure(%s%s%s_closure)",
|
||||||
func_isstatic(value) ? "static_" : "",
|
var_isstatic(value) ? "static_" : "",
|
||||||
classname ? classname : "", classname ? "_" : "",
|
classname ? classname : "", classname ? "_" : "",
|
||||||
func_name_id);
|
func_name_id);
|
||||||
}
|
}
|
||||||
@ -210,7 +210,7 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
|
|||||||
break;
|
break;
|
||||||
case BE_NTVFUNC:
|
case BE_NTVFUNC:
|
||||||
logfmt("be_const_%sfunc(be_ntv_%s_%s)",
|
logfmt("be_const_%sfunc(be_ntv_%s_%s)",
|
||||||
func_isstatic(value) ? "static_" : "",
|
var_isstatic(value) ? "static_" : "",
|
||||||
classname ? classname : "unknown", key ? key : "unknown");
|
classname ? classname : "unknown", key ? key : "unknown");
|
||||||
break;
|
break;
|
||||||
case BE_INSTANCE:
|
case BE_INSTANCE:
|
||||||
|
@ -83,13 +83,15 @@
|
|||||||
|
|
||||||
#define equal_rule(op, iseq) \
|
#define equal_rule(op, iseq) \
|
||||||
bbool res; \
|
bbool res; \
|
||||||
|
be_assert(!var_isstatic(a)); \
|
||||||
|
be_assert(!var_isstatic(b)); \
|
||||||
if (var_isint(a) && var_isint(b)) { \
|
if (var_isint(a) && var_isint(b)) { \
|
||||||
res = ibinop(op, a, b); \
|
res = ibinop(op, a, b); \
|
||||||
} else if (var_isnumber(a) && var_isnumber(b)) { \
|
} else if (var_isnumber(a) && var_isnumber(b)) { \
|
||||||
res = var2real(a) op var2real(b); \
|
res = var2real(a) op var2real(b); \
|
||||||
} else if (var_isinstance(a) && !var_isnil(b)) { \
|
} else if (var_isinstance(a) && !var_isnil(b)) { \
|
||||||
res = object_eqop(vm, #op, iseq, a, b); \
|
res = object_eqop(vm, #op, iseq, a, b); \
|
||||||
} else if (var_type(a) == var_type(b)) { /* same types */ \
|
} else if (var_primetype(a) == var_primetype(b)) { /* same types */ \
|
||||||
if (var_isnil(a)) { /* nil op nil */ \
|
if (var_isnil(a)) { /* nil op nil */ \
|
||||||
res = 1 op 1; \
|
res = 1 op 1; \
|
||||||
} else if (var_isbool(a)) { /* bool op bool */ \
|
} else if (var_isbool(a)) { /* bool op bool */ \
|
||||||
@ -256,6 +258,7 @@ static bbool obj2bool(bvm *vm, bvalue *var)
|
|||||||
binstance *obj = var_toobj(var);
|
binstance *obj = var_toobj(var);
|
||||||
bstring *tobool = str_literal(vm, "tobool");
|
bstring *tobool = str_literal(vm, "tobool");
|
||||||
/* get operator method */
|
/* get operator method */
|
||||||
|
// TODO what if `tobool` is static
|
||||||
int type = be_instance_member(vm, obj, tobool, vm->top);
|
int type = be_instance_member(vm, obj, tobool, vm->top);
|
||||||
if (type != BE_NONE && type != BE_NIL) {
|
if (type != BE_NONE && type != BE_NIL) {
|
||||||
vm->top[1] = *var; /* move self to argv[0] */
|
vm->top[1] = *var; /* move self to argv[0] */
|
||||||
@ -342,6 +345,7 @@ static bbool object_eqop(bvm *vm,
|
|||||||
bbool isself = var_isinstance(b) && o == var_toobj(b);
|
bbool isself = var_isinstance(b) && o == var_toobj(b);
|
||||||
/* first, try to call the overloaded operator of the object */
|
/* first, try to call the overloaded operator of the object */
|
||||||
int type = be_instance_member(vm, o, be_newstr(vm, op), vm->top);
|
int type = be_instance_member(vm, o, be_newstr(vm, op), vm->top);
|
||||||
|
// TODO check that method is not static
|
||||||
if (basetype(type) == BE_FUNCTION) { /* call method */
|
if (basetype(type) == BE_FUNCTION) { /* call method */
|
||||||
bvalue *top = vm->top;
|
bvalue *top = vm->top;
|
||||||
top[1] = self; /* move self to argv[0] */
|
top[1] = self; /* move self to argv[0] */
|
||||||
@ -826,41 +830,41 @@ newframe: /* a new call frame */
|
|||||||
#if BE_USE_PERF_COUNTERS
|
#if BE_USE_PERF_COUNTERS
|
||||||
vm->counter_get++;
|
vm->counter_get++;
|
||||||
#endif
|
#endif
|
||||||
bvalue a_temp; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
|
bvalue result; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
|
||||||
bvalue *b = RKB(), *c = RKC();
|
bvalue *b = RKB(), *c = RKC();
|
||||||
if (var_isinstance(b) && var_isstr(c)) {
|
if (var_isinstance(b) && var_isstr(c)) {
|
||||||
obj_attribute(vm, b, var_tostr(c), &a_temp);
|
obj_attribute(vm, b, var_tostr(c), &result);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
} else if (var_isclass(b) && var_isstr(c)) {
|
} else if (var_isclass(b) && var_isstr(c)) {
|
||||||
class_attribute(vm, b, c, &a_temp);
|
class_attribute(vm, b, c, &result);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
} else if (var_ismodule(b) && var_isstr(c)) {
|
} else if (var_ismodule(b) && var_isstr(c)) {
|
||||||
module_attribute(vm, b, c, &a_temp);
|
module_attribute(vm, b, c, &result);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
} else {
|
} else {
|
||||||
attribute_error(vm, "attribute", b, c);
|
attribute_error(vm, "attribute", b, c);
|
||||||
a_temp = *RA(); /* avoid gcc warning for uninitialized variable a_temp, this code is never reached */
|
result = *RA(); /* avoid gcc warning for uninitialized variable result, this code is never reached */
|
||||||
}
|
}
|
||||||
bvalue *a = RA();
|
bvalue *a = RA();
|
||||||
*a = a_temp; /* assign the resul to the specified register on the updated stack */
|
*a = result; /* assign the resul to the specified register on the updated stack */
|
||||||
dispatch();
|
dispatch();
|
||||||
}
|
}
|
||||||
opcase(GETMET): {
|
opcase(GETMET): {
|
||||||
#if BE_USE_PERF_COUNTERS
|
#if BE_USE_PERF_COUNTERS
|
||||||
vm->counter_get++;
|
vm->counter_get++;
|
||||||
#endif
|
#endif
|
||||||
bvalue a_temp; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
|
bvalue result; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
|
||||||
bvalue *b = RKB(), *c = RKC();
|
bvalue *b = RKB(), *c = RKC();
|
||||||
if (var_isinstance(b) && var_isstr(c)) {
|
if (var_isinstance(b) && var_isstr(c)) {
|
||||||
binstance *obj = var_toobj(b);
|
binstance *obj = var_toobj(b);
|
||||||
int type = obj_attribute(vm, b, var_tostr(c), &a_temp);
|
int type = obj_attribute(vm, b, var_tostr(c), &result);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
bvalue *a = RA();
|
bvalue *a = RA();
|
||||||
*a = a_temp;
|
*a = result;
|
||||||
if (var_basetype(a) == BE_FUNCTION) {
|
if (var_basetype(a) == BE_FUNCTION) {
|
||||||
if (func_isstatic(a) || (type == BE_INDEX)) { /* if instance variable then we consider it's non-method */
|
if ((type & BE_STATIC) || (type == BE_INDEX)) { /* if instance variable then we consider it's non-method */
|
||||||
/* static method, don't bother with the instance */
|
/* static method, don't bother with the instance */
|
||||||
a[1] = a_temp;
|
a[1] = result;
|
||||||
var_settype(a, NOT_METHOD);
|
var_settype(a, NOT_METHOD);
|
||||||
} else {
|
} else {
|
||||||
/* this is a real method (i.e. non-static) */
|
/* this is a real method (i.e. non-static) */
|
||||||
@ -876,16 +880,16 @@ newframe: /* a new call frame */
|
|||||||
str(be_instance_name(obj)), str(var_tostr(c)));
|
str(be_instance_name(obj)), str(var_tostr(c)));
|
||||||
}
|
}
|
||||||
} else if (var_isclass(b) && var_isstr(c)) {
|
} else if (var_isclass(b) && var_isstr(c)) {
|
||||||
class_attribute(vm, b, c, &a_temp);
|
class_attribute(vm, b, c, &result);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
bvalue *a = RA();
|
bvalue *a = RA();
|
||||||
a[1] = a_temp;
|
a[1] = result;
|
||||||
var_settype(a, NOT_METHOD);
|
var_settype(a, NOT_METHOD);
|
||||||
} else if (var_ismodule(b) && var_isstr(c)) {
|
} else if (var_ismodule(b) && var_isstr(c)) {
|
||||||
module_attribute(vm, b, c, &a_temp);
|
module_attribute(vm, b, c, &result);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
bvalue *a = RA();
|
bvalue *a = RA();
|
||||||
a[1] = a_temp;
|
a[1] = result;
|
||||||
var_settype(a, NOT_METHOD);
|
var_settype(a, NOT_METHOD);
|
||||||
} else {
|
} else {
|
||||||
attribute_error(vm, "method", b, c);
|
attribute_error(vm, "method", b, c);
|
||||||
@ -913,11 +917,11 @@ newframe: /* a new call frame */
|
|||||||
/* if value is a function, we mark it as a static to distinguish from methods */
|
/* if value is a function, we mark it as a static to distinguish from methods */
|
||||||
bclass *obj = var_toobj(a);
|
bclass *obj = var_toobj(a);
|
||||||
bstring *attr = var_tostr(b);
|
bstring *attr = var_tostr(b);
|
||||||
bvalue c_static = *c;
|
bvalue result = *c;
|
||||||
if (var_isfunction(&c_static)) {
|
if (var_isfunction(&result)) {
|
||||||
c_static.type = func_setstatic(&c_static);
|
var_markstatic(&result);
|
||||||
}
|
}
|
||||||
if (!be_class_setmember(vm, obj, attr, &c_static)) {
|
if (!be_class_setmember(vm, obj, attr, &result)) {
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
vm_error(vm, "attribute_error",
|
vm_error(vm, "attribute_error",
|
||||||
"class '%s' cannot assign to static attribute '%s'",
|
"class '%s' cannot assign to static attribute '%s'",
|
||||||
@ -1253,6 +1257,7 @@ void be_dofunc(bvm *vm, bvalue *v, int argc)
|
|||||||
be_assert(vm->reg <= v && v < vm->stacktop);
|
be_assert(vm->reg <= v && v < vm->stacktop);
|
||||||
be_assert(vm->stack <= vm->reg && vm->reg < vm->stacktop);
|
be_assert(vm->stack <= vm->reg && vm->reg < vm->stacktop);
|
||||||
int pos = v - vm->reg;
|
int pos = v - vm->reg;
|
||||||
|
be_assert(!var_isstatic(v));
|
||||||
switch (var_type(v)) {
|
switch (var_type(v)) {
|
||||||
case BE_CLASS: do_class(vm, pos, argc); break;
|
case BE_CLASS: do_class(vm, pos, argc); break;
|
||||||
case BE_CLOSURE: do_closure(vm, pos, argc); break;
|
case BE_CLOSURE: do_closure(vm, pos, argc); break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user