vbscipt: Added beginning support for arrays as class members.
This commit is contained in:
parent
3dd7c60742
commit
82cace0f0e
|
@ -1210,6 +1210,28 @@ static void resolve_labels(compile_ctx_t *ctx, unsigned off)
|
|||
ctx->labels_cnt = 0;
|
||||
}
|
||||
|
||||
static HRESULT fill_array_desc(compile_ctx_t *ctx, dim_decl_t *dim_decl, array_desc_t *array_desc)
|
||||
{
|
||||
unsigned dim_cnt = 0, i;
|
||||
dim_list_t *iter;
|
||||
|
||||
for(iter = dim_decl->dims; iter; iter = iter->next)
|
||||
dim_cnt++;
|
||||
|
||||
array_desc->bounds = compiler_alloc(ctx->code, dim_cnt * sizeof(SAFEARRAYBOUND));
|
||||
if(!array_desc->bounds)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
array_desc->dim_cnt = dim_cnt;
|
||||
|
||||
for(iter = dim_decl->dims, i=0; iter; iter = iter->next, i++) {
|
||||
array_desc->bounds[i].cElements = iter->val+1;
|
||||
array_desc->bounds[i].lLbound = 0;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func)
|
||||
{
|
||||
HRESULT hres;
|
||||
|
@ -1304,35 +1326,19 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
|
|||
}
|
||||
|
||||
if(func->array_cnt) {
|
||||
unsigned dim_cnt, array_id = 0;
|
||||
unsigned array_id = 0;
|
||||
dim_decl_t *dim_decl;
|
||||
dim_list_t *iter;
|
||||
|
||||
func->array_descs = compiler_alloc(ctx->code, func->array_cnt * sizeof(array_desc_t));
|
||||
if(!func->array_descs)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
|
||||
if(!dim_decl->is_array)
|
||||
continue;
|
||||
|
||||
dim_cnt = 0;
|
||||
for(iter = dim_decl->dims; iter; iter = iter->next)
|
||||
dim_cnt++;
|
||||
|
||||
func->array_descs[array_id].bounds = compiler_alloc(ctx->code, dim_cnt * sizeof(SAFEARRAYBOUND));
|
||||
if(!func->array_descs[array_id].bounds)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
func->array_descs[array_id].dim_cnt = dim_cnt;
|
||||
|
||||
dim_cnt = 0;
|
||||
for(iter = dim_decl->dims; iter; iter = iter->next) {
|
||||
func->array_descs[array_id].bounds[dim_cnt].cElements = iter->val+1;
|
||||
func->array_descs[array_id].bounds[dim_cnt++].lLbound = 0;
|
||||
if(dim_decl->is_array) {
|
||||
hres = fill_array_desc(ctx, dim_decl, func->array_descs + array_id++);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
}
|
||||
|
||||
array_id++;
|
||||
}
|
||||
|
||||
assert(array_id == func->array_cnt);
|
||||
|
@ -1475,8 +1481,8 @@ static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name)
|
|||
static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
|
||||
{
|
||||
function_decl_t *func_decl, *func_prop_decl;
|
||||
class_prop_decl_t *prop_decl;
|
||||
class_desc_t *class_desc;
|
||||
dim_decl_t *prop_decl;
|
||||
unsigned i;
|
||||
HRESULT hres;
|
||||
|
||||
|
@ -1560,6 +1566,25 @@ static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
|
|||
return E_OUTOFMEMORY;
|
||||
|
||||
class_desc->props[i].is_public = prop_decl->is_public;
|
||||
|
||||
if(prop_decl->is_array) {
|
||||
class_desc->props[i].is_array = TRUE;
|
||||
class_desc->array_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if(class_desc->array_cnt) {
|
||||
class_desc->array_descs = compiler_alloc(ctx->code, class_desc->array_cnt*sizeof(*class_desc->array_descs));
|
||||
if(!class_desc->array_descs)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next) {
|
||||
if(prop_decl->is_array) {
|
||||
hres = fill_array_desc(ctx, prop_decl, class_desc->array_descs + i++);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_desc->next = ctx->classes;
|
||||
|
|
|
@ -146,6 +146,7 @@ typedef struct _dim_list_t {
|
|||
typedef struct _dim_decl_t {
|
||||
const WCHAR *name;
|
||||
BOOL is_array;
|
||||
BOOL is_public; /* Used only for class members. */
|
||||
dim_list_t *dims;
|
||||
struct _dim_decl_t *next;
|
||||
} dim_decl_t;
|
||||
|
@ -176,16 +177,10 @@ typedef struct {
|
|||
function_decl_t *func_decl;
|
||||
} function_statement_t;
|
||||
|
||||
typedef struct _class_prop_decl_t {
|
||||
BOOL is_public;
|
||||
const WCHAR *name;
|
||||
struct _class_prop_decl_t *next;
|
||||
} class_prop_decl_t;
|
||||
|
||||
typedef struct _class_decl_t {
|
||||
const WCHAR *name;
|
||||
function_decl_t *funcs;
|
||||
class_prop_decl_t *props;
|
||||
dim_decl_t *props;
|
||||
struct _class_decl_t *next;
|
||||
} class_decl_t;
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ static case_clausule_t *new_case_clausule(parser_ctx_t*,expression_t*,statement_
|
|||
|
||||
static class_decl_t *new_class_decl(parser_ctx_t*);
|
||||
static class_decl_t *add_class_function(parser_ctx_t*,class_decl_t*,function_decl_t*);
|
||||
static class_decl_t *add_variant_prop(parser_ctx_t*,class_decl_t*,const WCHAR*,unsigned);
|
||||
static class_decl_t *add_dim_prop(parser_ctx_t*,class_decl_t*,dim_decl_t*,unsigned);
|
||||
|
||||
static statement_t *link_statements(statement_t*,statement_t*);
|
||||
|
||||
|
@ -396,7 +396,10 @@ ClassDeclaration
|
|||
ClassBody
|
||||
: /* empty */ { $$ = new_class_decl(ctx); }
|
||||
| FunctionDecl tNL ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
|
||||
| Storage tIdentifier tNL ClassBody { $$ = add_variant_prop(ctx, $4, $2, $1); CHECK_ERROR; }
|
||||
/* FIXME: We should use DimDecl here to support arrays, but that conflicts with PropertyDecl. */
|
||||
| Storage tIdentifier tNL ClassBody { dim_decl_t *dim_decl = new_dim_decl(ctx, $2, FALSE, NULL); CHECK_ERROR;
|
||||
$$ = add_dim_prop(ctx, $4, dim_decl, $1); CHECK_ERROR; }
|
||||
| tDIM DimDecl tNL ClassBody { $$ = add_dim_prop(ctx, $4, $2, 0); CHECK_ERROR; }
|
||||
| PropertyDecl tNL ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
|
||||
|
||||
PropertyDecl
|
||||
|
@ -891,24 +894,17 @@ static class_decl_t *add_class_function(parser_ctx_t *ctx, class_decl_t *class_d
|
|||
return class_decl;
|
||||
}
|
||||
|
||||
static class_decl_t *add_variant_prop(parser_ctx_t *ctx, class_decl_t *class_decl, const WCHAR *identifier, unsigned storage_flags)
|
||||
static class_decl_t *add_dim_prop(parser_ctx_t *ctx, class_decl_t *class_decl, dim_decl_t *dim_decl, unsigned storage_flags)
|
||||
{
|
||||
class_prop_decl_t *prop;
|
||||
|
||||
if(storage_flags & STORAGE_IS_DEFAULT) {
|
||||
FIXME("variant prop van't be default value\n");
|
||||
ctx->hres = E_FAIL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prop = parser_alloc(ctx, sizeof(*prop));
|
||||
if(!prop)
|
||||
return NULL;
|
||||
|
||||
prop->name = identifier;
|
||||
prop->is_public = !(storage_flags & STORAGE_IS_PRIVATE);
|
||||
prop->next = class_decl->props;
|
||||
class_decl->props = prop;
|
||||
dim_decl->is_public = !(storage_flags & STORAGE_IS_PRIVATE);
|
||||
dim_decl->next = class_decl->props;
|
||||
class_decl->props = dim_decl;
|
||||
return class_decl;
|
||||
}
|
||||
|
||||
|
|
|
@ -814,6 +814,9 @@ Class TestClass
|
|||
Public Sub Class_Initialize
|
||||
publicProp2 = 2
|
||||
privateProp = true
|
||||
'todo_wine Call ok(getVT(privateProp) = "VT_BOOL*", "getVT(privateProp) = " & getVT(privateProp))
|
||||
'todo_wine Call ok(getVT(publicProp2) = "VT_I2*", "getVT(publicProp2) = " & getVT(publicProp2))
|
||||
Call ok(getVT(Me.publicProp2) = "VT_I2", "getVT(Me.publicProp2) = " & getVT(Me.publicProp2))
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
|
@ -830,6 +833,7 @@ Call obj.publicFunction()
|
|||
|
||||
Call ok(getVT(obj.publicProp) = "VT_EMPTY", "getVT(obj.publicProp) = " & getVT(obj.publicProp))
|
||||
obj.publicProp = 3
|
||||
Call ok(getVT(obj.publicProp) = "VT_I2", "getVT(obj.publicProp) = " & getVT(obj.publicProp))
|
||||
Call ok(obj.publicProp = 3, "obj.publicProp = " & obj.publicProp)
|
||||
obj.publicProp() = 3
|
||||
|
||||
|
@ -1044,4 +1048,23 @@ next
|
|||
x=1
|
||||
Call ok(forarr(x) = 2, "forarr(x) = " & forarr(x))
|
||||
|
||||
Class ArrClass
|
||||
Dim classarr(3)
|
||||
Dim classnoarr()
|
||||
Dim var
|
||||
|
||||
Private Sub Class_Initialize
|
||||
'todo_wine Call ok(getVT(classarr) = "VT_ARRAY|VT_BYREF|VT_VARIANT*", "getVT(classarr) = " & getVT(classarr))
|
||||
'todo_wine Call testArray(-1, classnoarr)
|
||||
'classarr(0) = 1
|
||||
'classarr(1) = 2
|
||||
'classarr(2) = 3
|
||||
'classarr(3) = 4
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
Set obj = new ArrClass
|
||||
'todo_wine Call ok(getVT(obj.classarr) = "VT_ARRAY|VT_VARIANT", "getVT(obj.classarr) = " & getVT(obj.classarr))
|
||||
'todo_wine Call ok(obj.classarr(1) = 2, "obj.classarr(1) = " & obj.classarr(1))
|
||||
|
||||
reportSuccess()
|
||||
|
|
|
@ -121,6 +121,11 @@ static HRESULT invoke_variant_prop(VARIANT *v, WORD flags, DISPPARAMS *dp, VARIA
|
|||
return DISP_E_PARAMNOTOPTIONAL;
|
||||
}
|
||||
|
||||
if(arg_cnt(dp)) {
|
||||
FIXME("Arguments not supported\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if(res)
|
||||
V_VT(res) = VT_EMPTY;
|
||||
|
||||
|
@ -239,6 +244,13 @@ static void clean_props(vbdisp_t *This)
|
|||
if(!This->desc)
|
||||
return;
|
||||
|
||||
for(i=0; i < This->desc->array_cnt; i++) {
|
||||
if(This->arrays[i]) {
|
||||
SafeArrayDestroy(This->arrays[i]);
|
||||
This->arrays[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i < This->desc->prop_cnt; i++)
|
||||
VariantClear(This->props+i);
|
||||
}
|
||||
|
@ -291,6 +303,7 @@ static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
|
|||
if(!ref && run_terminator(This)) {
|
||||
clean_props(This);
|
||||
list_remove(&This->entry);
|
||||
heap_free(This->arrays);
|
||||
heap_free(This);
|
||||
}
|
||||
|
||||
|
@ -505,6 +518,7 @@ static inline vbdisp_t *unsafe_impl_from_IDispatch(IDispatch *iface)
|
|||
HRESULT create_vbdisp(const class_desc_t *desc, vbdisp_t **ret)
|
||||
{
|
||||
vbdisp_t *vbdisp;
|
||||
HRESULT hres = S_OK;
|
||||
|
||||
vbdisp = heap_alloc_zero( FIELD_OFFSET( vbdisp_t, props[desc->prop_cnt] ));
|
||||
if(!vbdisp)
|
||||
|
@ -516,16 +530,44 @@ HRESULT create_vbdisp(const class_desc_t *desc, vbdisp_t **ret)
|
|||
|
||||
list_add_tail(&desc->ctx->objects, &vbdisp->entry);
|
||||
|
||||
if(desc->class_initialize_id) {
|
||||
DISPPARAMS dp = {0};
|
||||
HRESULT hres;
|
||||
if(desc->array_cnt) {
|
||||
vbdisp->arrays = heap_alloc_zero(desc->array_cnt * sizeof(*vbdisp->arrays));
|
||||
if(vbdisp->arrays) {
|
||||
unsigned i, j;
|
||||
|
||||
for(i=0; i < desc->array_cnt; i++) {
|
||||
if(!desc->array_descs[i].dim_cnt)
|
||||
continue;
|
||||
|
||||
vbdisp->arrays[i] = SafeArrayCreate(VT_VARIANT, desc->array_descs[i].dim_cnt, desc->array_descs[i].bounds);
|
||||
if(!vbdisp->arrays[i]) {
|
||||
hres = E_OUTOFMEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(SUCCEEDED(hres)) {
|
||||
for(i=0, j=0; i < desc->prop_cnt; i++) {
|
||||
if(desc->props[i].is_array) {
|
||||
V_VT(vbdisp->props+i) = VT_ARRAY|VT_BYREF|VT_VARIANT;
|
||||
V_ARRAYREF(vbdisp->props+i) = vbdisp->arrays + j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else {
|
||||
hres = E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if(SUCCEEDED(hres) && desc->class_initialize_id) {
|
||||
DISPPARAMS dp = {0};
|
||||
hres = exec_script(desc->ctx, desc->funcs[desc->class_initialize_id].entries[VBDISP_CALLGET],
|
||||
(IDispatch*)&vbdisp->IDispatchEx_iface, &dp, NULL);
|
||||
if(FAILED(hres)) {
|
||||
IDispatchEx_Release(&vbdisp->IDispatchEx_iface);
|
||||
return hres;
|
||||
}
|
||||
}
|
||||
|
||||
if(FAILED(hres)) {
|
||||
IDispatchEx_Release(&vbdisp->IDispatchEx_iface);
|
||||
return hres;
|
||||
}
|
||||
|
||||
*ret = vbdisp;
|
||||
|
|
|
@ -67,14 +67,21 @@ typedef enum {
|
|||
VBDISP_ANY
|
||||
} vbdisp_invoke_type_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned dim_cnt;
|
||||
SAFEARRAYBOUND *bounds;
|
||||
} array_desc_t;
|
||||
|
||||
typedef struct {
|
||||
BOOL is_public;
|
||||
BOOL is_array;
|
||||
const WCHAR *name;
|
||||
} vbdisp_prop_desc_t;
|
||||
|
||||
typedef struct {
|
||||
const WCHAR *name;
|
||||
BOOL is_public;
|
||||
BOOL is_array;
|
||||
function_t *entries[VBDISP_ANY];
|
||||
} vbdisp_funcprop_desc_t;
|
||||
|
||||
|
@ -101,6 +108,9 @@ typedef struct _class_desc_t {
|
|||
unsigned prop_cnt;
|
||||
vbdisp_prop_desc_t *props;
|
||||
|
||||
unsigned array_cnt;
|
||||
array_desc_t *array_descs;
|
||||
|
||||
unsigned builtin_prop_cnt;
|
||||
const builtin_prop_t *builtin_props;
|
||||
ITypeInfo *typeinfo;
|
||||
|
@ -117,6 +127,7 @@ struct _vbdisp_t {
|
|||
struct list entry;
|
||||
|
||||
const class_desc_t *desc;
|
||||
SAFEARRAY **arrays;
|
||||
VARIANT props[1];
|
||||
};
|
||||
|
||||
|
@ -302,11 +313,6 @@ typedef struct {
|
|||
const WCHAR *name;
|
||||
} var_desc_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned dim_cnt;
|
||||
SAFEARRAYBOUND *bounds;
|
||||
} array_desc_t;
|
||||
|
||||
struct _function_t {
|
||||
function_type_t type;
|
||||
const WCHAR *name;
|
||||
|
|
Loading…
Reference in New Issue