mirror of https://github.com/arendst/Tasmota.git
Berry static methods
This commit is contained in:
parent
0d43311782
commit
8faa144d04
|
@ -23,7 +23,7 @@
|
||||||
#define MAGIC_NUMBER1 0xBE
|
#define MAGIC_NUMBER1 0xBE
|
||||||
#define MAGIC_NUMBER2 0xCD
|
#define MAGIC_NUMBER2 0xCD
|
||||||
#define MAGIC_NUMBER3 0xFE
|
#define MAGIC_NUMBER3 0xFE
|
||||||
#define BYTECODE_VERSION 2
|
#define BYTECODE_VERSION 3
|
||||||
|
|
||||||
#define USE_64BIT_INT (BE_INTGER_TYPE == 2 \
|
#define USE_64BIT_INT (BE_INTGER_TYPE == 2 \
|
||||||
|| BE_INTGER_TYPE == 1 && LONG_MAX == 9223372036854775807L)
|
|| BE_INTGER_TYPE == 1 && LONG_MAX == 9223372036854775807L)
|
||||||
|
@ -425,7 +425,7 @@ 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));
|
be_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_member_bind(vm, c, name, bfalse);
|
||||||
|
|
|
@ -75,7 +75,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)
|
void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static)
|
||||||
{
|
{
|
||||||
bclosure *cl;
|
bclosure *cl;
|
||||||
bvalue *attr;
|
bvalue *attr;
|
||||||
|
@ -87,6 +87,9 @@ void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p)
|
||||||
cl = be_newclosure(vm, p->nupvals);
|
cl = be_newclosure(vm, p->nupvals);
|
||||||
cl->proto = p;
|
cl->proto = p;
|
||||||
var_setclosure(attr, cl);
|
var_setclosure(attr, cl);
|
||||||
|
if (is_static) {
|
||||||
|
func_setstatic(attr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f)
|
void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f)
|
||||||
|
|
|
@ -53,7 +53,7 @@ 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_member_bind(bvm *vm, bclass *c, bstring *name, bbool var);
|
||||||
void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p);
|
void be_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_prim_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_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl);
|
||||||
int be_class_closure_count(bclass *c);
|
int be_class_closure_count(bclass *c);
|
||||||
|
|
|
@ -38,6 +38,11 @@ extern "C" {
|
||||||
.type = BE_FUNCTION \
|
.type = BE_FUNCTION \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define be_const_static_func(_func) { \
|
||||||
|
.v.nf = (_func), \
|
||||||
|
.type = BE_FUNCTION | BE_FUNC_STATIC \
|
||||||
|
}
|
||||||
|
|
||||||
#define be_const_nil() { \
|
#define be_const_nil() { \
|
||||||
.v.i = 0, \
|
.v.i = 0, \
|
||||||
.type = BE_NIL \
|
.type = BE_NIL \
|
||||||
|
@ -88,6 +93,11 @@ extern "C" {
|
||||||
.type = BE_CLOSURE \
|
.type = BE_CLOSURE \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define be_const_static_closure(_closure) { \
|
||||||
|
.v.c = &(_closure), \
|
||||||
|
.type = BE_CLOSURE | BE_FUNC_STATIC \
|
||||||
|
}
|
||||||
|
|
||||||
#define be_const_module(_module) { \
|
#define be_const_module(_module) { \
|
||||||
.v.c = &(_module), \
|
.v.c = &(_module), \
|
||||||
.type = BE_MODULE \
|
.type = BE_MODULE \
|
||||||
|
@ -251,6 +261,11 @@ const bntvmodule be_native_module(_module) = { \
|
||||||
BE_FUNCTION \
|
BE_FUNCTION \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define be_const_static_func(_func) { \
|
||||||
|
bvaldata(_func), \
|
||||||
|
BE_FUNCTION | BE_FUNC_STATIC \
|
||||||
|
}
|
||||||
|
|
||||||
#define be_const_nil() { \
|
#define be_const_nil() { \
|
||||||
bvaldata(0), \
|
bvaldata(0), \
|
||||||
BE_NIL \
|
BE_NIL \
|
||||||
|
@ -301,6 +316,11 @@ const bntvmodule be_native_module(_module) = { \
|
||||||
BE_CLOSURE \
|
BE_CLOSURE \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define be_const_static_closure(_closure) { \
|
||||||
|
bvaldata(&(_closure)), \
|
||||||
|
BE_CLOSURE | BE_FUNC_STATIC \
|
||||||
|
}
|
||||||
|
|
||||||
#define be_const_module(_module) { \
|
#define be_const_module(_module) { \
|
||||||
bvaldata(&(_module)), \
|
bvaldata(&(_module)), \
|
||||||
BE_MODULE \
|
BE_MODULE \
|
||||||
|
|
|
@ -348,7 +348,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 (obj->type) {
|
switch (var_type(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;
|
||||||
|
|
|
@ -346,5 +346,7 @@ bmapnode* be_map_val2node(bvalue *value)
|
||||||
void be_map_release(bvm *vm, bmap *map)
|
void be_map_release(bvm *vm, bmap *map)
|
||||||
{
|
{
|
||||||
(void)vm;
|
(void)vm;
|
||||||
|
if (!gc_isconst(map)) {
|
||||||
resize(vm, map, map->count ? map->count : 1);
|
resize(vm, map, map->count ? map->count : 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,25 +11,30 @@
|
||||||
#include "berry.h"
|
#include "berry.h"
|
||||||
|
|
||||||
/* basic types, do not change value */
|
/* basic types, do not change value */
|
||||||
#define BE_NONE (-1) /* unknown type */
|
|
||||||
#define BE_COMPTR (-2) /* common pointer */
|
|
||||||
#define BE_INDEX (-3) /* index for instance variable, previously BE_INT */
|
|
||||||
#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_FUNCTION 4
|
#define BE_NONE 4 /* unknown type */
|
||||||
#define BE_STRING 5 /* from this type can be gced, see BE_GCOBJECT */
|
#define BE_COMPTR 5 /* common pointer */
|
||||||
#define BE_CLASS 6
|
#define BE_INDEX 6 /* index for instance variable, previously BE_INT */
|
||||||
#define BE_INSTANCE 7
|
#define BE_FUNCTION 7
|
||||||
#define BE_PROTO 8
|
#define BE_STRING 8 /* from this type can be gced, see BE_GCOBJECT */
|
||||||
#define BE_LIST 9
|
#define BE_CLASS 9
|
||||||
#define BE_MAP 10
|
#define BE_INSTANCE 10
|
||||||
#define BE_MODULE 11
|
#define BE_PROTO 11
|
||||||
#define BE_COMOBJ 12 /* common object */
|
#define BE_LIST 12
|
||||||
|
#define BE_MAP 13
|
||||||
|
#define BE_MODULE 14
|
||||||
|
#define BE_COMOBJ 15 /* common object */
|
||||||
#define BE_NTVFUNC ((0 << 5) | BE_FUNCTION)
|
#define BE_NTVFUNC ((0 << 5) | BE_FUNCTION)
|
||||||
#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_FUNC_STATIC (1 << 7)
|
||||||
|
|
||||||
|
#define func_isstatic(o) (((o)->type & BE_FUNC_STATIC) != 0)
|
||||||
|
#define func_setstatic(o) ((o)->type |= BE_FUNC_STATIC)
|
||||||
|
#define func_clearstatic(o) ((o)->type &= ~BE_FUNC_STATIC)
|
||||||
|
|
||||||
#define array_count(a) (sizeof(a) / sizeof((a)[0]))
|
#define array_count(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
|
||||||
|
@ -187,7 +192,7 @@ 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)
|
#define var_type(_v) ((_v)->type & 0x7F)
|
||||||
#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_istype(_v, _t) (var_type(_v) == _t)
|
||||||
#define var_settype(_v, _t) ((_v)->type = _t)
|
#define var_settype(_v, _t) ((_v)->type = _t)
|
||||||
|
|
|
@ -1422,12 +1422,28 @@ static void class_static_assignment_expr(bparser *parser, bexpdesc *e, bstring *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void classdef_stmt(bparser *parser, bclass *c, bbool is_static)
|
||||||
|
{
|
||||||
|
bexpdesc e;
|
||||||
|
bstring *name;
|
||||||
|
bproto *proto;
|
||||||
|
/* 'def' ID '(' varlist ')' block 'end' */
|
||||||
|
scan_next_token(parser); /* skip 'def' */
|
||||||
|
name = func_name(parser, &e, 1);
|
||||||
|
check_class_attr(parser, c, name);
|
||||||
|
proto = funcbody(parser, name, is_static ? 0 : FUNC_METHOD);
|
||||||
|
be_method_bind(parser->vm, c, proto->name, proto, is_static);
|
||||||
|
be_stackpop(parser->vm, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void classstatic_stmt(bparser *parser, bclass *c, bexpdesc *e)
|
static void classstatic_stmt(bparser *parser, bclass *c, bexpdesc *e)
|
||||||
{
|
{
|
||||||
bstring *name;
|
bstring *name;
|
||||||
/* 'static' ID ['=' expr] {',' ID ['=' expr] } */
|
/* 'static' ID ['=' expr] {',' ID ['=' expr] } */
|
||||||
scan_next_token(parser); /* skip 'static' */
|
scan_next_token(parser); /* skip 'static' */
|
||||||
if (match_id(parser, name) != NULL) {
|
if (next_type(parser) == KeyDef) { /* 'static' 'def' ... */
|
||||||
|
classdef_stmt(parser, c, btrue);
|
||||||
|
} 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_member_bind(parser->vm, c, name, bfalse);
|
||||||
class_static_assignment_expr(parser, e, name);
|
class_static_assignment_expr(parser, e, name);
|
||||||
|
@ -1446,20 +1462,6 @@ static void classstatic_stmt(bparser *parser, bclass *c, bexpdesc *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void classdef_stmt(bparser *parser, bclass *c)
|
|
||||||
{
|
|
||||||
bexpdesc e;
|
|
||||||
bstring *name;
|
|
||||||
bproto *proto;
|
|
||||||
/* 'def' ID '(' varlist ')' block 'end' */
|
|
||||||
scan_next_token(parser); /* skip 'def' */
|
|
||||||
name = func_name(parser, &e, 1);
|
|
||||||
check_class_attr(parser, c, name);
|
|
||||||
proto = funcbody(parser, name, FUNC_METHOD);
|
|
||||||
be_method_bind(parser->vm, c, proto->name, proto);
|
|
||||||
be_stackpop(parser->vm, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void class_inherit(bparser *parser, bexpdesc *e)
|
static void class_inherit(bparser *parser, bexpdesc *e)
|
||||||
{
|
{
|
||||||
if (next_type(parser) == OptColon) { /* ':' */
|
if (next_type(parser) == OptColon) { /* ':' */
|
||||||
|
@ -1479,7 +1481,7 @@ static void class_block(bparser *parser, bclass *c, bexpdesc *e)
|
||||||
switch (next_type(parser)) {
|
switch (next_type(parser)) {
|
||||||
case KeyVar: classvar_stmt(parser, c); break;
|
case KeyVar: classvar_stmt(parser, c); break;
|
||||||
case KeyStatic: classstatic_stmt(parser, c, e); break;
|
case KeyStatic: classstatic_stmt(parser, c, e); break;
|
||||||
case KeyDef: classdef_stmt(parser, c); break;
|
case KeyDef: classdef_stmt(parser, c, bfalse); break;
|
||||||
case OptSemic: scan_next_token(parser); break;
|
case OptSemic: scan_next_token(parser); break;
|
||||||
default: push_error(parser,
|
default: push_error(parser,
|
||||||
"unexpected token '%s'", token2str(parser));
|
"unexpected token '%s'", token2str(parser));
|
||||||
|
|
|
@ -41,6 +41,9 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
|
||||||
|
|
||||||
static void m_solidify_map(bvm *vm, bmap * map, const char *class_name)
|
static void m_solidify_map(bvm *vm, bmap * map, const char *class_name)
|
||||||
{
|
{
|
||||||
|
// compact first
|
||||||
|
be_map_release(vm, map);
|
||||||
|
|
||||||
logfmt(" be_nested_map(%i,\n", map->count);
|
logfmt(" be_nested_map(%i,\n", map->count);
|
||||||
|
|
||||||
logfmt(" ( (struct bmapnode*) &(const bmapnode[]) {\n");
|
logfmt(" ( (struct bmapnode*) &(const bmapnode[]) {\n");
|
||||||
|
@ -128,7 +131,8 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BE_CLOSURE:
|
case BE_CLOSURE:
|
||||||
logfmt("be_const_closure(%s%s%s_closure)",
|
logfmt("be_const_%sclosure(%s%s%s_closure)",
|
||||||
|
func_isstatic(value) ? "static_" : "",
|
||||||
classname ? classname : "", classname ? "_" : "",
|
classname ? classname : "", classname ? "_" : "",
|
||||||
str(((bclosure*) var_toobj(value))->proto->name));
|
str(((bclosure*) var_toobj(value))->proto->name));
|
||||||
break;
|
break;
|
||||||
|
@ -139,7 +143,9 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
|
||||||
logfmt("be_const_comptr(&be_ntv_%s_%s)", classname ? classname : "unknown", key ? key : "unknown");
|
logfmt("be_const_comptr(&be_ntv_%s_%s)", classname ? classname : "unknown", key ? key : "unknown");
|
||||||
break;
|
break;
|
||||||
case BE_NTVFUNC:
|
case BE_NTVFUNC:
|
||||||
logfmt("be_const_func(be_ntv_%s_%s)", classname ? classname : "unknown", key ? key : "unknown");
|
logfmt("be_const_%sfunc(be_ntv_%s_%s)",
|
||||||
|
func_isstatic(value) ? "static_" : "",
|
||||||
|
classname ? classname : "unknown", key ? key : "unknown");
|
||||||
break;
|
break;
|
||||||
case BE_INSTANCE:
|
case BE_INSTANCE:
|
||||||
{
|
{
|
||||||
|
@ -199,7 +205,7 @@ static void m_solidify_proto_inner_class(bvm *vm, bproto *pr, int builtins)
|
||||||
static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int builtins, int indent)
|
static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int builtins, int indent)
|
||||||
{
|
{
|
||||||
// const char * func_name = str(pr->name);
|
// const char * func_name = str(pr->name);
|
||||||
const char * func_source = str(pr->source);
|
// const char * func_source = str(pr->source);
|
||||||
|
|
||||||
logfmt("%*sbe_nested_proto(\n", indent, "");
|
logfmt("%*sbe_nested_proto(\n", indent, "");
|
||||||
indent += 2;
|
indent += 2;
|
||||||
|
@ -345,7 +351,7 @@ static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins)
|
||||||
logfmt(" NULL,\n");
|
logfmt(" NULL,\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
logfmt(" (be_nested_const_str(\"%s\", %i, %i))\n", class_name, be_strhash(cl->name), str_len(cl->name));
|
logfmt(" (be_nested_str_literal(\"%s\"))\n", class_name);
|
||||||
logfmt(");\n");
|
logfmt(");\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,12 +57,18 @@ int be_eqstr(bstring *s1, bstring *s2)
|
||||||
}
|
}
|
||||||
/* const short strings */
|
/* const short strings */
|
||||||
if (gc_isconst(s1) || gc_isconst(s2)) { /* one of the two string is short const */
|
if (gc_isconst(s1) || gc_isconst(s2)) { /* one of the two string is short const */
|
||||||
if (cast(bcstring*, s1)->hash && cast(bcstring*, s2)->hash) {
|
uint32_t hash1 = cast(bcstring*, s1)->hash;
|
||||||
return 0; /* if they both have a hash, then we know they are different */
|
uint32_t hash2 = cast(bcstring*, s2)->hash;
|
||||||
|
if (hash1 && hash2 && hash1 != hash2) {
|
||||||
|
return 0; /* if hash differ, since we know both are non-null */
|
||||||
}
|
}
|
||||||
|
/* if hash are equals, there might be a chance that they are different */
|
||||||
|
/* This can happen with solidified code that a same string is present more than once */
|
||||||
|
/* so just considering that two strings with the same hash must be same pointer, this is no more true */
|
||||||
return !strcmp(str(s1), str(s2));
|
return !strcmp(str(s1), str(s2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if both strings are in-memory, they can't be equal without having the same pointer */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -854,16 +854,29 @@ newframe: /* a new call frame */
|
||||||
bvalue *a = RA();
|
bvalue *a = RA();
|
||||||
*a = a_temp;
|
*a = a_temp;
|
||||||
if (basetype(type) == BE_FUNCTION) {
|
if (basetype(type) == BE_FUNCTION) {
|
||||||
|
if (func_isstatic(a)) {
|
||||||
|
/* static method, don't bother with the instance */
|
||||||
|
a[1] = a_temp;
|
||||||
|
var_settype(a, NOT_METHOD);
|
||||||
|
} else {
|
||||||
|
/* this is a real method (i.e. non-static) */
|
||||||
/* check if the object is a superinstance, if so get the lowest possible subclass */
|
/* check if the object is a superinstance, if so get the lowest possible subclass */
|
||||||
while (obj->sub) {
|
while (obj->sub) {
|
||||||
obj = obj->sub;
|
obj = obj->sub;
|
||||||
}
|
}
|
||||||
var_setinstance(&a[1], obj); /* replace superinstance by lowest subinstance */
|
var_setinstance(&a[1], obj); /* replace superinstance by lowest subinstance */
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
vm_error(vm, "attribute_error",
|
vm_error(vm, "attribute_error",
|
||||||
"class '%s' has no method '%s'",
|
"class '%s' has no method '%s'",
|
||||||
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)) {
|
||||||
|
class_attribute(vm, b, c, &a_temp);
|
||||||
|
reg = vm->reg;
|
||||||
|
bvalue *a = RA();
|
||||||
|
a[1] = a_temp;
|
||||||
|
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, &a_temp);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
|
@ -893,9 +906,14 @@ newframe: /* a new call frame */
|
||||||
dispatch();
|
dispatch();
|
||||||
}
|
}
|
||||||
if (var_isclass(a) && var_isstr(b)) {
|
if (var_isclass(a) && var_isstr(b)) {
|
||||||
|
/* 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);
|
||||||
if (!be_class_setmember(vm, obj, attr, c)) {
|
bvalue c_static = *c;
|
||||||
|
if (var_isfunction(&c_static)) {
|
||||||
|
c_static.type = func_setstatic(&c_static);
|
||||||
|
}
|
||||||
|
if (!be_class_setmember(vm, obj, attr, &c_static)) {
|
||||||
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'",
|
||||||
|
|
Loading…
Reference in New Issue