vbscipt: Added beginning support for arrays as class members.

This commit is contained in:
Jacek Caban 2014-03-07 14:27:12 +01:00 committed by Alexandre Julliard
parent 3dd7c60742
commit 82cace0f0e
6 changed files with 141 additions and 54 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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()

View File

@ -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;

View File

@ -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;