From 5bebe33e189e14df40cabc06153e754e9380b26e Mon Sep 17 00:00:00 2001 From: SanderMertens Date: Mon, 16 Mar 2015 14:09:40 -0400 Subject: [PATCH 1/4] #14 Move buddies to ic layer --- dev/include/cx_ic.h | 1 + dev/src/cx_ic.c | 17 +++++++ interface/fast/Fast.xml | 15 ------ interface/fast/include/Fast.h | 2 - interface/fast/include/Fast_IteratorLocal.h | 28 ------------ interface/fast/include/Fast_IteratorObject.h | 28 ------------ interface/fast/include/Fast_Variable.h | 6 --- interface/fast/include/Fast__type.h | 48 ++++++-------------- interface/fast/src/Fast_IteratorLocal.c | 17 ------- interface/fast/src/Fast_IteratorObject.c | 17 ------- interface/fast/src/Fast_Parser.c | 6 +-- interface/fast/src/Fast_PostFix.c | 19 ++++++-- interface/fast/src/Fast_Unary.c | 18 ++++++-- interface/fast/src/Fast_Variable.c | 8 ---- interface/fast/src/fast.y | 19 +++++--- 15 files changed, 76 insertions(+), 173 deletions(-) delete mode 100644 interface/fast/include/Fast_IteratorLocal.h delete mode 100644 interface/fast/include/Fast_IteratorObject.h delete mode 100644 interface/fast/src/Fast_IteratorLocal.c delete mode 100644 interface/fast/src/Fast_IteratorObject.c diff --git a/dev/include/cx_ic.h b/dev/include/cx_ic.h index de7429c4..a11ac159 100644 --- a/dev/include/cx_ic.h +++ b/dev/include/cx_ic.h @@ -137,6 +137,7 @@ typedef struct cx_icStorage_s { cx_bool isReference; /* Is the storage a reference */ cx_uint32 used; /* Count how many times value is used in program */ cx_bool holdsReturn; /* If accumulator holds returnvalue, it potentially holds resources */ + cx_icLocal buddy; /* A register that is bound in lifecycle with the storage */ }cx_icStorage_s; typedef struct cx_icObject_s { diff --git a/dev/src/cx_ic.c b/dev/src/cx_ic.c index b633eac6..587210b8 100644 --- a/dev/src/cx_ic.c +++ b/dev/src/cx_ic.c @@ -498,6 +498,19 @@ cx_icProgram cx_icProgram__create(cx_string filename) { return result; } +cx_icLocal cx_icBuddy__create(cx_icProgram program, cx_icStorage storage) { + /* Insert buddy storage in correct scope so that lifecycle is equal to storage */ + if (storage->kind == CX_STORAGE_OBJECT) { + + } else if (storage->kind == CX_STORAGE_LOCAL) { + + } else if (storage->kind == CX_STORAGE_MEMBER) { + + } else if (storage->kind == CX_STORAGE_ELEMENT) { + + } +} + void cx_icStorage_init( cx_icStorage storage, cx_icProgram program, @@ -515,6 +528,10 @@ void cx_icStorage_init( storage->type = type; storage->isReference = type->reference; storage->holdsReturn = FALSE; + + if (type->kind == CX_ITERATOR) { + storage->buddy = cx_icBuddy__create(storage); + } } cx_icObject cx_icObject__create(cx_icProgram program, cx_uint32 line, cx_object ptr) { diff --git a/interface/fast/Fast.xml b/interface/fast/Fast.xml index 6bf6680f..2443c651 100644 --- a/interface/fast/Fast.xml +++ b/interface/fast/Fast.xml @@ -181,7 +181,6 @@ - @@ -206,13 +205,6 @@ - - - - - - - @@ -239,13 +231,6 @@ - - - - - - - diff --git a/interface/fast/include/Fast.h b/interface/fast/include/Fast.h index fd040ee3..32a74041 100644 --- a/interface/fast/include/Fast.h +++ b/interface/fast/include/Fast.h @@ -66,8 +66,6 @@ Fast_valueKind Fast_valueKindFromType(cx_type type); #include "Fast_InitializerVariable.h" #include "Fast_InitOper.h" #include "Fast_Integer.h" -#include "Fast_IteratorLocal.h" -#include "Fast_IteratorObject.h" #include "Fast_Literal.h" #include "Fast_Local.h" #include "Fast_Lvalue.h" diff --git a/interface/fast/include/Fast_IteratorLocal.h b/interface/fast/include/Fast_IteratorLocal.h deleted file mode 100644 index a3fa6f54..00000000 --- a/interface/fast/include/Fast_IteratorLocal.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Fast_IteratorLocal.h - * - * This file contains generated code. Do not modify! - */ - -#ifndef Fast_IteratorLocal_H -#define Fast_IteratorLocal_H - -#include "cortex.h" -#include "Fast_Local.h" -#include "Fast__type.h" - -#include "Fast__api.h" - -#include "Fast__meta.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* ::cortex::Fast::IteratorLocal::getBuddy() */ -Fast_Local Fast_IteratorLocal_getBuddy(Fast_IteratorLocal _this); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/interface/fast/include/Fast_IteratorObject.h b/interface/fast/include/Fast_IteratorObject.h deleted file mode 100644 index 6dae6e58..00000000 --- a/interface/fast/include/Fast_IteratorObject.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Fast_IteratorObject.h - * - * This file contains generated code. Do not modify! - */ - -#ifndef Fast_IteratorObject_H -#define Fast_IteratorObject_H - -#include "cortex.h" -#include "Fast_Object.h" -#include "Fast__type.h" - -#include "Fast__api.h" - -#include "Fast__meta.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* ::cortex::Fast::IteratorObject::getBuddy() */ -Fast_Local Fast_IteratorObject_getBuddy(Fast_IteratorObject _this); - -#ifdef __cplusplus -} -#endif -#endif - diff --git a/interface/fast/include/Fast_Variable.h b/interface/fast/include/Fast_Variable.h index 346592c7..ca89870a 100644 --- a/interface/fast/include/Fast_Variable.h +++ b/interface/fast/include/Fast_Variable.h @@ -21,12 +21,6 @@ extern "C" { /* ::cortex::Fast::Variable::construct() */ cx_int16 Fast_Variable_construct(Fast_Variable _this); -/* virtual ::cortex::Fast::Variable::getBuddy() */ -Fast_Local Fast_Variable_getBuddy(Fast_Variable _this); - -/* ::cortex::Fast::Variable::getBuddy() */ -Fast_Local Fast_Variable_getBuddy_v(Fast_Variable _this); - #ifdef __cplusplus } #endif diff --git a/interface/fast/include/Fast__type.h b/interface/fast/include/Fast__type.h index 8a439f92..60352200 100644 --- a/interface/fast/include/Fast__type.h +++ b/interface/fast/include/Fast__type.h @@ -36,8 +36,6 @@ extern "C" { #define Fast_Initializer(o) ((Fast_Initializer)o) #define Fast_InitializerExpression(o) ((Fast_InitializerExpression)o) #define Fast_Integer(o) ((Fast_Integer)o) -#define Fast_IteratorLocal(o) ((Fast_IteratorLocal)o) -#define Fast_IteratorObject(o) ((Fast_IteratorObject)o) #define Fast_Literal(o) ((Fast_Literal)o) #define Fast_Local(o) ((Fast_Local)o) #define Fast_Member(o) ((Fast_Member)o) @@ -412,37 +410,6 @@ typedef enum Fast_InitializerKind { Fast_InitExpression = 2 } Fast_InitializerKind; -/* ::cortex::Fast::IteratorLocal */ -CX_CLASS(Fast_IteratorLocal); - -CX_CLASS_DEF(Fast_IteratorLocal) { - CX_EXTEND(Fast_Local); - Fast_Local buddy; -}; - -/* ::cortex::Fast::ObjectBase */ -CX_CLASS(Fast_ObjectBase); - -CX_CLASS_DEF(Fast_ObjectBase) { - CX_EXTEND(Fast_Variable); - cx_object value; -}; - -/* ::cortex::Fast::Object */ -CX_CLASS(Fast_Object); - -CX_CLASS_DEF(Fast_Object) { - CX_EXTEND(Fast_ObjectBase); -}; - -/* ::cortex::Fast::IteratorObject */ -CX_CLASS(Fast_IteratorObject); - -CX_CLASS_DEF(Fast_IteratorObject) { - CX_EXTEND(Fast_Object); - Fast_Local buddy; -}; - /* ::cortex::Fast::Lvalue */ typedef struct Fast_Lvalue Fast_Lvalue; @@ -478,6 +445,21 @@ CX_CLASS_DEF(Fast_Null) { CX_EXTEND(Fast_Literal); }; +/* ::cortex::Fast::ObjectBase */ +CX_CLASS(Fast_ObjectBase); + +CX_CLASS_DEF(Fast_ObjectBase) { + CX_EXTEND(Fast_Variable); + cx_object value; +}; + +/* ::cortex::Fast::Object */ +CX_CLASS(Fast_Object); + +CX_CLASS_DEF(Fast_Object) { + CX_EXTEND(Fast_ObjectBase); +}; + CX_LIST(Fast_Binding_list); CX_LIST(cx_word_list); diff --git a/interface/fast/src/Fast_IteratorLocal.c b/interface/fast/src/Fast_IteratorLocal.c deleted file mode 100644 index b0f91996..00000000 --- a/interface/fast/src/Fast_IteratorLocal.c +++ /dev/null @@ -1,17 +0,0 @@ -/* Fast_IteratorLocal.c - * - * This file contains the implementation for the generated interface. - * - * Don't mess with the begin and end tags, since these will ensure that modified - * code in interface functions isn't replaced when code is re-generated. - */ - -#include "Fast.h" -#include "Fast__meta.h" - -/* ::cortex::Fast::IteratorLocal::getBuddy() */ -Fast_Local Fast_IteratorLocal_getBuddy(Fast_IteratorLocal _this) { -/* $begin(::cortex::Fast::IteratorLocal::getBuddy) */ - return _this->buddy; -/* $end */ -} diff --git a/interface/fast/src/Fast_IteratorObject.c b/interface/fast/src/Fast_IteratorObject.c deleted file mode 100644 index d2ab3733..00000000 --- a/interface/fast/src/Fast_IteratorObject.c +++ /dev/null @@ -1,17 +0,0 @@ -/* Fast_IteratorObject.c - * - * This file contains the implementation for the generated interface. - * - * Don't mess with the begin and end tags, since these will ensure that modified - * code in interface functions isn't replaced when code is re-generated. - */ - -#include "Fast.h" -#include "Fast__meta.h" - -/* ::cortex::Fast::IteratorObject::getBuddy() */ -Fast_Local Fast_IteratorObject_getBuddy(Fast_IteratorObject _this) { -/* $begin(::cortex::Fast::IteratorObject::getBuddy) */ - return _this->buddy; -/* $end */ -} diff --git a/interface/fast/src/Fast_Parser.c b/interface/fast/src/Fast_Parser.c index 658871bb..0d982af8 100644 --- a/interface/fast/src/Fast_Parser.c +++ b/interface/fast/src/Fast_Parser.c @@ -1470,11 +1470,7 @@ Fast_Variable Fast_Parser_declaration(Fast_Parser _this, Fast_Variable type, cx_ cx_free_ext(_this, o, "Free object from resolve (2nd run)"); } if (o) { - if (cx_type(Fast_ObjectBase(type)->value)->kind == CX_ITERATOR) { - result = Fast_Variable(Fast_IteratorObject__create(o)); - } else { - result = Fast_Variable(Fast_Object__create(o)); - } + result = Fast_Variable(Fast_Object__create(o)); Fast_Parser_collect(_this, result); _this->variables[_this->variableCount] = result; _this->variableCount++; diff --git a/interface/fast/src/Fast_PostFix.c b/interface/fast/src/Fast_PostFix.c index c1978a80..f1e5d554 100644 --- a/interface/fast/src/Fast_PostFix.c +++ b/interface/fast/src/Fast_PostFix.c @@ -32,6 +32,7 @@ cx_int16 Fast_PostFix_construct(Fast_PostFix _this) { } else { cx_id id; switch(lvalueType->kind) { + case CX_PRIMITIVE: switch(cx_primitive(lvalueType)->kind) { case CX_INTEGER: @@ -47,6 +48,18 @@ cx_int16 Fast_PostFix_construct(Fast_PostFix _this) { break; } break; + Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(lvalueType)); + + case CX_ITERATOR: + if (_this->operator == CX_INC) { + /* The result of an expression that increments an iterator is a boolean */ + Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(cx_bool_o)); + } else { + Fast_Parser_error(yparser(), "invalid operator for iterator"); + goto error; + } + break; + default: Fast_Parser_error( yparser(), "invalid operator for type '%s'", Fast_Parser_id(lvalueType, id)); @@ -55,10 +68,8 @@ cx_int16 Fast_PostFix_construct(Fast_PostFix _this) { } } - Fast_Node(_this)->kind = Fast_PostfixExpr; - Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(lvalueType)); - + return 0; error: return -1; @@ -70,7 +81,7 @@ cx_ic Fast_PostFix_toIc_v(Fast_PostFix _this, cx_icProgram program, cx_icStorage /* $begin(::cortex::Fast::PostFix::toIc) */ cx_icStorage result; cx_ic lvalue; - cx_icOp op; + cx_icOp op = NULL; CX_UNUSED(stored); if (storage) { diff --git a/interface/fast/src/Fast_Unary.c b/interface/fast/src/Fast_Unary.c index 7e2d8ca3..f17343bb 100644 --- a/interface/fast/src/Fast_Unary.c +++ b/interface/fast/src/Fast_Unary.c @@ -24,13 +24,25 @@ cx_int16 Fast_Unary_construct(Fast_Unary _this) { lvalueType = Fast_Expression_getType(_this->lvalue); Fast_Node(_this)->kind = Fast_UnaryExpr; - if (_this->operator == CX_COND_NOT) { - Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(cx_bool_o)); + if (lvalueType->kind != CX_ITERATOR) { + if (_this->operator == CX_COND_NOT) { + Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(cx_bool_o)); + } else { + Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(lvalueType)); + } } else { - Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(lvalueType)); + if (_this->operator == CX_MUL) { + cx_type iterType = cx_iterator(lvalueType)->elementType; + Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(iterType)); + } else { + Fast_Parser_error(yparser(), "invalid operator for iterator"); + goto error; + } } return 0; +error: + return -1; /* $end */ } diff --git a/interface/fast/src/Fast_Variable.c b/interface/fast/src/Fast_Variable.c index 8d9bf75f..2b1dc839 100644 --- a/interface/fast/src/Fast_Variable.c +++ b/interface/fast/src/Fast_Variable.c @@ -18,11 +18,3 @@ cx_int16 Fast_Variable_construct(Fast_Variable _this) { return 0; /* $end */ } - -/* ::cortex::Fast::Variable::getBuddy() */ -Fast_Local Fast_Variable_getBuddy_v(Fast_Variable _this) { -/* $begin(::cortex::Fast::Variable::getBuddy) */ - CX_UNUSED(_this); - return NULL; -/* $end */ -} diff --git a/interface/fast/src/fast.y b/interface/fast/src/fast.y index e1b1eb9e..9efead74 100644 --- a/interface/fast/src/fast.y +++ b/interface/fast/src/fast.y @@ -161,7 +161,7 @@ Fast_Expression Fast_declarationSeqDo(Fast_Variable type, Fast_ParserDeclaration /* Syntax tree nodes */ %type statement statements - expr literal_expr primary_expr postfix_expr unary_expr multiplicative_expr additive_expr shift_expr + expr literal_expr primary_expr iter_expr postfix_expr unary_expr multiplicative_expr additive_expr shift_expr boolean_expr equality_expr and_expr xor_expr or_expr logical_and_expr logical_or_expr assignment_expr comma_expr bracket_expr conditional_expr wait_expr declaration declaration_expr declaration_ref function_declaration @@ -405,16 +405,21 @@ bracket_expr primary_expr : bracket_expr - | literal_expr {$$=$1;} - | identifier {$$=$1;} + | literal_expr {$$ = $1;} + | identifier {$$ = $1;} ; -postfix_expr +iter_expr : primary_expr + | '*' iter_expr {$$ = Fast_Parser_unaryExpr(yparser(), $2, CX_MUL); fast_op;} + ; + +postfix_expr + : iter_expr | postfix_expr {PUSHCOMPLEX($1)} '[' expr ']' {$$ = Fast_Parser_elementExpr(yparser(), $1, $4); fast_op; POPCOMPLEX()} - | postfix_expr '(' ')' {$$ = Fast_Parser_callExpr(yparser(), $1, NULL); fast_op;} - | postfix_expr bracket_expr {$$ = Fast_Parser_callExpr(yparser(), $1, $2); fast_op;} - | postfix_expr '.' any_id {Fast_String str = Fast_String__create($3); if (!str) {YYERROR;} $$ = Fast_Parser_memberExpr(yparser(), $1, Fast_Expression(str)); cx_free(str); fast_op;} + | postfix_expr '(' ')' {$$ = Fast_Parser_callExpr(yparser(), $1, NULL); fast_op;} + | postfix_expr bracket_expr {$$ = Fast_Parser_callExpr(yparser(), $1, $2); fast_op;} + | postfix_expr '.' any_id {Fast_String str = Fast_String__create($3); if (!str) {YYERROR;} $$ = Fast_Parser_memberExpr(yparser(), $1, Fast_Expression(str)); cx_free(str); fast_op;} | postfix_expr INC {$$ = Fast_Parser_postfixExpr(yparser(), $1, CX_INC); fast_op} | postfix_expr DEC {$$ = Fast_Parser_postfixExpr(yparser(), $1, CX_DEC); fast_op} ; From 4e7eba826782e4f2fbd9e8810a8c23ba930e2cfd Mon Sep 17 00:00:00 2001 From: SanderMertens Date: Sun, 22 Mar 2015 04:08:05 -0400 Subject: [PATCH 2/4] #14 Implemented iterator functionality for arrays and sequences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A minor issue still exists with lists, which has to do with how values smaller than a word size are stored in a list. The ‘current’ member of the iterator expects an address to the value, however for the above mentioned values the list doesn’t store an address to the value, but the value itself. Further TODO’s is implement initializers and build testcases. --- cx/include/cx_async.h | 2 +- cx/include/cx_def.h | 4 +- cx/include/cx_iterator.h | 4 +- cx/include/cx_vm_def.h | 2 +- cx/src/cx_iterator.c | 129 ++++++++---------------------- cx/src/cx_vm.c | 19 +++-- dev/include/cx_ic.h | 1 - dev/src/cx_generatorDepWalk.c | 3 +- dev/src/cx_ic.c | 23 +----- dev/src/cx_ic_assemble.c | 27 ++++++- interface/fast/src/Fast_PostFix.c | 8 +- interface/fast/src/Fast_Unary.c | 17 +++- 12 files changed, 102 insertions(+), 137 deletions(-) diff --git a/cx/include/cx_async.h b/cx/include/cx_async.h index 9075813f..c666e28e 100644 --- a/cx/include/cx_async.h +++ b/cx/include/cx_async.h @@ -70,7 +70,7 @@ int cx_ainc(int* count); int cx_adec(int* count); /* use GNU atomic compare and swap */ -#define cx_cas(ptr,old,new) __sync_bool_compare_and_swap(ptr,old,new) +#define cx_cas(ptr, old, new) __sync_bool_compare_and_swap(ptr, old, new) #ifdef __cplusplus } diff --git a/cx/include/cx_def.h b/cx/include/cx_def.h index ec384d04..6b766785 100644 --- a/cx/include/cx_def.h +++ b/cx/include/cx_def.h @@ -64,11 +64,13 @@ typedef struct cx_ll_s* cx_ll; /* C language binding type definition macro's */ #define CX_ANY(__type) typedef struct __type {cx_type type; void *value; cx_bool owner;} __type #define CX_ITERATOR(__type) typedef struct __type {\ + void *current;\ cx_collection type;\ union {\ struct { /* CX_ARRAY and CX_SEQUENCE */\ void *array;\ - void *element;\ + int32_t elementSize;\ + void* max;\ } array;\ struct {\ cx_ll *ll;\ diff --git a/cx/include/cx_iterator.h b/cx/include/cx_iterator.h index 5f6bbc4c..fdf8b3e3 100644 --- a/cx/include/cx_iterator.h +++ b/cx/include/cx_iterator.h @@ -20,6 +20,7 @@ extern "C" { /* $header() */ cx_int16 cx_iterator_set(void *_this, void *collection, cx_collection collectionType); +cx_bool cx_iterator_next(void *_this); /* $end */ /* virtual ::cortex::lang::iterator::castable(type type) */ @@ -37,9 +38,6 @@ cx_bool cx_iterator_compatible_v(cx_iterator _this, cx_type type); /* ::cortex::lang::iterator::init() */ cx_int16 cx_iterator_init(cx_iterator _this); -cx_bool cx_iterator_hasNext(void *_this); -void *cx_iterator_next(void *_this); - #ifdef __cplusplus } #endif diff --git a/cx/include/cx_vm_def.h b/cx/include/cx_vm_def.h index 852422e3..9f12b0cf 100644 --- a/cx/include/cx_vm_def.h +++ b/cx/include/cx_vm_def.h @@ -94,7 +94,7 @@ extern "C" { OP2_EXP(expand##2, ELEMM, W, R, PQRV, typeAction, opAction)\ OP2_EXP(expand##2, ELEMMX, W, R, PQRV, typeAction, opAction)\ OP2_EXP(expand##2, ITER_SET, W, PQR, PQRV, typeAction, opAction)\ - OP3_EXP(expand##3, ITER_NEXT, W, PQR, PQR, PQRV, typeAction, opAction)\ + OP2_EXP(expand##2, ITER_NEXT, W, PQR, PQRV, typeAction, opAction)\ OP1_EXP(expand##1, PUSH, BSLD, PQRV, typeAction, opAction) /* Regular push */\ OP1_EXP(expand##1, PUSHX, BSLD, R, typeAction, opAction) /* Push address of a register */\ OP1_EXP(expand##1, PUSHANY, W, PQRV, typeAction, opAction) /* Push any value */\ diff --git a/cx/src/cx_iterator.c b/cx/src/cx_iterator.c index 1a345a82..7d348821 100644 --- a/cx/src/cx_iterator.c +++ b/cx/src/cx_iterator.c @@ -10,17 +10,25 @@ #include "cx__meta.h" /* $header() */ +CX_ITERATOR(iteratorType); +CX_SEQUENCE(seqType, cx_object, ); cx_int16 cx_iterator_set(void* _this, void* collection, cx_collection collectionType) { - CX_ITERATOR(IteratorType); - IteratorType *iter = _this; + iteratorType *iter = _this; iter->type = collectionType; switch (collectionType->kind) { case CX_ARRAY: - case CX_SEQUENCE: iter->is.array.array = collection; - iter->is.array.element = collection; + iter->is.array.elementSize = cx_type_sizeof(collectionType->elementType); + iter->is.array.max = CX_OFFSET(iter->is.array.array, collectionType->max * iter->is.array.elementSize); + iter->current = CX_OFFSET(collection, -iter->is.array.elementSize); + break; + case CX_SEQUENCE: + iter->is.array.array = ((seqType*)collection)->buffer; + iter->is.array.elementSize = cx_type_sizeof(collectionType->elementType); + iter->is.array.max = CX_OFFSET(iter->is.array.array, ((seqType*)collection)->length * iter->is.array.elementSize); + iter->current = CX_OFFSET(iter->is.array.array, -iter->is.array.elementSize); break; case CX_LIST: iter->is.ll.ll = collection; @@ -32,123 +40,56 @@ cx_int16 cx_iterator_set(void* _this, void* collection, cx_collection collection return 0; } -static cx_bool cx_iterator_hasNext_array(void* iterator) { - CX_ITERATOR(IteratorType); - IteratorType *iter = iterator; - cx_collection collection = iter->type; - cx_void *array = iter->is.array.array; - void *element = iter->is.array.element; - cx_bool hasNext = FALSE; - cx_type elementType = collection->elementType; - cx_uint32 elementSize = cx_type_sizeof(elementType); - cx_uint32 length = collection->max; - if (element < CX_OFFSET(array, elementSize * length)) { - hasNext = TRUE; +/* Combined hasNext and next */ +static cx_bool cx_iterator_next_array(void* iterator) { + iteratorType *iter = iterator; + cx_uint32 elementSize = iter->is.array.elementSize; + void *current = iter->current; + cx_bool result = FALSE; + current = CX_OFFSET(current, elementSize); + if (current < iter->is.array.max) { + iter->current = current; + result = TRUE; } - return hasNext; + return result; } -static int cx_iterator_next_array(void* iterator, void** nextElement) { - CX_ITERATOR(IteratorType); - IteratorType *iter; - cx_collection collection; - cx_void *array; - void *element; - cx_type elementType; - cx_uint32 elementSize; - cx_uint32 length; - int error; - - error = 1; - iter = iterator; - collection = iter->type; - array = iter->is.array.array; - element = iter->is.array.element; - elementType = collection->elementType; - elementSize = cx_type_sizeof(elementType); - length = collection->max; - if (element < CX_OFFSET(array, elementSize * length)) { - *nextElement = CX_OFFSET(element, elementSize); - iter->is.array.element = *nextElement; - error = 0; +static cx_bool cx_iterator_next_ll(void* iterator) { + iteratorType *iter = iterator; + cx_bool result = FALSE; + if ((result = cx_iterHasNext(&iter->is.ll.iter))) { + iter->current = cx_iterNext(&iter->is.ll.iter); + result = TRUE; } - return error; -} - -static cx_bool cx_iterator_hasNext_ll(void* iterator) { - CX_ITERATOR(IteratorType); - IteratorType *iter = iterator; - cx_bool result = cx_iterHasNext(&(iter->is.ll.iter)); return result; } -static int cx_iterator_next_ll(void* iterator, void** nextElement) { - CX_ITERATOR(IteratorType); - IteratorType *iter = iterator; - *nextElement = cx_iterNext(&iter->is.ll.iter); - return 0; -} - -static cx_bool cx_iterator_hasNext_map(void* iterator) { - // CX_ITERATOR(IteratorType); +static cx_bool cx_iterator_next_map(void* iterator) { CX_UNUSED(iterator); // TODO implement - return 0; -} - -static int cx_iterator_next_map(void* iterator, void** nextElement) { - // CX_ITERATOR(IteratorType); - CX_UNUSED(iterator); - CX_UNUSED(nextElement); - // TODO implement return 1; } -cx_bool cx_iterator_hasNext(void* _this) { +cx_bool cx_iterator_next(void* _this) { CX_ITERATOR(iteratorType); iteratorType *iterator = _this; cx_bool result = FALSE; - switch (iterator->type->kind) { - case CX_ARRAY: - case CX_SEQUENCE: - result = cx_iterator_hasNext_array(iterator); - break; - case CX_LIST: - result = cx_iterator_hasNext_ll(iterator); - break; - case CX_MAP: - result = cx_iterator_hasNext_map(iterator); - break; - default: - break; - } - return result; -} - -void* cx_iterator_next(void* _this) { - CX_ITERATOR(iteratorType); - iteratorType *iterator = _this; - int error = 0; - void *result = NULL; switch (iterator->type->kind) { case CX_ARRAY: case CX_SEQUENCE: - error = cx_iterator_next_array(iterator, &result); - break; + result = cx_iterator_next_array(iterator); break; case CX_LIST: - error = cx_iterator_next_ll(iterator, &result); + result = cx_iterator_next_ll(iterator); break; case CX_MAP: - error = cx_iterator_next_map(iterator, &result); + result = cx_iterator_next_map(iterator); break; default: break; } - if (error || result == NULL) { - cx_critical("error retrieving next element from collection"); - } + return result; } diff --git a/cx/src/cx_vm.c b/cx/src/cx_vm.c index 4f949c84..dda7a577 100644 --- a/cx/src/cx_vm.c +++ b/cx/src/cx_vm.c @@ -730,10 +730,8 @@ typedef union Di2f_t { /* op1 is hasNext, op2 is the result of next and op3 is the iterator */ #define ITER_NEXT(type,code)\ ITER_NEXT_##code:\ - fetchOp3(ITER_NEXT, code);\ - if ((op1_##code = (W_t)cx_iterator_hasNext((void*)op3_##code))) {\ - op2_##code = (W_t)cx_iterator_next((void*)op3_##code);\ - }\ + fetchOp2(ITER_NEXT, code);\ + op1_##code = (W_t)cx_iterator_next((void*)op2_##code);\ next();\ #define JUMP(type, code)\ @@ -1070,13 +1068,20 @@ int32_t cx_vm_run(cx_vmProgram program, void *result) { /* This function converts a single instruction to a string */ #ifdef CX_IC_TRACING -char * cx_vmOp_toString(char * string, cx_vmOp *instr, const char *op, const char *type, const char *lvalue, const char *rvalue, const char* fetch) { +char * cx_vmOp_toString( + char * string, cx_vmOp *instr, const char *op, const char *type, const char *lvalue, const char *rvalue, const char* fetch) { char *result = string; if (fetch && strlen(fetch)) { - result = strappend(result, "%s_%s%s%s_%s %u %u %u %u\n", op, type, lvalue, rvalue, fetch, instr->ic.b._1, instr->ic.b._2, instr->lo.w, instr->hi.w); + result = strappend( + result, + "%s_%s%s%s_%s %u %u %u %u\n", + op, type, lvalue, rvalue, fetch, instr->ic.b._1, instr->ic.b._2, instr->lo.w, instr->hi.w); } else { - result = strappend(result, "%s_%s%s%s %hu %hu %u %u\n", op, type, lvalue, rvalue, instr->ic.b._1, instr->ic.b._2, instr->lo.w, instr->hi.w); + result = strappend( + result, + "%s_%s%s%s %hu %hu %u %u\n", + op, type, lvalue, rvalue, instr->ic.b._1, instr->ic.b._2, instr->lo.w, instr->hi.w); } return result; diff --git a/dev/include/cx_ic.h b/dev/include/cx_ic.h index a11ac159..de7429c4 100644 --- a/dev/include/cx_ic.h +++ b/dev/include/cx_ic.h @@ -137,7 +137,6 @@ typedef struct cx_icStorage_s { cx_bool isReference; /* Is the storage a reference */ cx_uint32 used; /* Count how many times value is used in program */ cx_bool holdsReturn; /* If accumulator holds returnvalue, it potentially holds resources */ - cx_icLocal buddy; /* A register that is bound in lifecycle with the storage */ }cx_icStorage_s; typedef struct cx_icObject_s { diff --git a/dev/src/cx_generatorDepWalk.c b/dev/src/cx_generatorDepWalk.c index 5b2c010b..562daf2e 100644 --- a/dev/src/cx_generatorDepWalk.c +++ b/dev/src/cx_generatorDepWalk.c @@ -380,6 +380,7 @@ int cx_genDepBuildAction(cx_object o, void* userData) { g_itemDepend(dependee, CX_DECLARED, type, CX_DEFINED); } + /* TODO: this is not nice */ if (cx_class_instanceof(cx_procedure_o, cx_typeof(o))) { /* Insert base-dependency: methods may only be declared after the base of a class has been defined. */ if (cx_typeof(o) != cx_type(cx_function_o)) { @@ -412,7 +413,7 @@ int cx_genDepBuildAction(cx_object o, void* userData) { g_itemDepend(dependee, CX_DECLARED, parent, CX_DECLARED); /* If child must be declared when parent is declared, parent may only be defined after - * all such childs are defined. */ + * all such children are defined. */ g_itemDepend(parent, CX_DEFINED, dependee, CX_DEFINED); break; case CX_DEFINED: diff --git a/dev/src/cx_ic.c b/dev/src/cx_ic.c index 587210b8..5cda261a 100644 --- a/dev/src/cx_ic.c +++ b/dev/src/cx_ic.c @@ -498,19 +498,6 @@ cx_icProgram cx_icProgram__create(cx_string filename) { return result; } -cx_icLocal cx_icBuddy__create(cx_icProgram program, cx_icStorage storage) { - /* Insert buddy storage in correct scope so that lifecycle is equal to storage */ - if (storage->kind == CX_STORAGE_OBJECT) { - - } else if (storage->kind == CX_STORAGE_LOCAL) { - - } else if (storage->kind == CX_STORAGE_MEMBER) { - - } else if (storage->kind == CX_STORAGE_ELEMENT) { - - } -} - void cx_icStorage_init( cx_icStorage storage, cx_icProgram program, @@ -528,10 +515,6 @@ void cx_icStorage_init( storage->type = type; storage->isReference = type->reference; storage->holdsReturn = FALSE; - - if (type->kind == CX_ITERATOR) { - storage->buddy = cx_icBuddy__create(storage); - } } cx_icObject cx_icObject__create(cx_icProgram program, cx_uint32 line, cx_object ptr) { @@ -556,7 +539,8 @@ cx_icObject cx_icObject__create(cx_icProgram program, cx_uint32 line, cx_object return result; } -cx_icLocal cx_icLocal__create(cx_icProgram program, cx_uint32 line, cx_string name, cx_type type, cx_bool isParameter, cx_bool isReturn, cx_bool declare) { +cx_icLocal cx_icLocal__create( + cx_icProgram program, cx_uint32 line, cx_string name, cx_type type, cx_bool isParameter, cx_bool isReturn, cx_bool declare) { cx_icLocal result; if (!(result = (cx_icLocal)cx_icProgram_lookupStorage(program, name, !declare))) { @@ -786,7 +770,8 @@ void cx_icProgram__free(cx_icProgram _this) { } cx_icAccumulator cx_icProgram_accumulatorPush(cx_icProgram _this, cx_uint32 line, cx_type type, cx_bool isReference) { - _this->accumulatorStack[_this->accumulatorId] = cx_icAccumulator__create(_this, line, type ? type : cx_void_o, _this->accumulatorId); + _this->accumulatorStack[_this->accumulatorId] = + cx_icAccumulator__create(_this, line, type ? type : cx_void_o, _this->accumulatorId); ((cx_icStorage)_this->accumulatorStack[_this->accumulatorId])->isReference = isReference; _this->accumulatorId++; return _this->accumulatorStack[_this->accumulatorId-1]; diff --git a/dev/src/cx_ic_assemble.c b/dev/src/cx_ic_assemble.c index b3d0b5fe..2223e09c 100644 --- a/dev/src/cx_ic_assemble.c +++ b/dev/src/cx_ic_assemble.c @@ -1570,6 +1570,16 @@ static cx_vmOpKind cx_ic_getVmPush(cx_icOp op, cx_type t, cx_ic_vmType typeKind, }\ } +static cx_vmOpKind cx_ic_getVmInc(cx_icOp op, cx_type t, cx_ic_vmType typeKind, cx_ic_vmOperand op1, cx_ic_vmOperand op2) { + cx_vmOpKind result = CX_VM_STOP; + + if (((cx_icStorage)op->s1)->type->kind == CX_ITERATOR) { + result = cx_ic_getVmITER_NEXT(t, CX_IC_VMTYPE_W, op2, op1, 0); + } else { + result = cx_ic_getVmINC(t, typeKind, op1, 0, 0); + } + return result; +} static cx_vmOpKind cx_ic_getVmOpKind(cx_ic_vmProgram *program, cx_icOp op, cx_icValue storage, cx_type t, cx_ic_vmType typeKind, cx_ic_vmOperand op1, cx_ic_vmOperand op2, cx_icDerefMode deref1, cx_icDerefMode deref2) { cx_vmOpKind result = CX_VM_STOP; @@ -1592,7 +1602,7 @@ static cx_vmOpKind cx_ic_getVmOpKind(cx_ic_vmProgram *program, cx_icOp op, cx_ic case CX_IC_MUL: cx_ic_getVmArith(MUL, t, typeKind, op1, op2); break; case CX_IC_DIV: cx_ic_getVmArith(DIV, t, typeKind, op1, op2); break; case CX_IC_MOD: result = cx_ic_getVmMODI(t, typeKind, op1, op2, 0); break; - case CX_IC_INC: result = cx_ic_getVmINC(t, typeKind, op1, 0, 0); break; + case CX_IC_INC: result = cx_ic_getVmInc(op, t, typeKind, op1, op2); break; case CX_IC_DEC: result = cx_ic_getVmDEC(t, typeKind, op1, 0, 0); break; case CX_IC_XOR: result = cx_ic_getVmXOR(t, typeKind, op1, op2, 0); break; case CX_IC_OR: result = cx_ic_getVmOR(t, typeKind, op1, op2, 0); break; @@ -1941,8 +1951,18 @@ static void cx_ic_getVmOp(cx_ic_vmProgram *program, cx_icOp op) { opDeref2 = op->s2Deref; } /* no break */ + case CX_IC_INC: { + cx_type t = ((cx_icStorage)op->s1)->type; + if (t->kind == CX_ITERATOR) { + op2 = op->s2; + op1 = op->s1; + opDeref2 = op->s2Deref; + opDeref1 = CX_IC_DEREF_ADDRESS; + storage = NULL; + break; + } + } case CX_IC_DEFINE: - case CX_IC_INC: case CX_IC_DEC: case CX_IC_RET: case CX_IC_FREE: @@ -2020,7 +2040,7 @@ static void cx_ic_getVmOp(cx_ic_vmProgram *program, cx_icOp op) { op1 = op->s1; storage = NULL; vmOp->hi.w = (cx_word)((cx_icObject)op->s2)->ptr; - opDeref1 = op->s1Deref; + opDeref1 = op->s1Deref; } break; @@ -2056,7 +2076,6 @@ static void cx_ic_getVmOp(cx_ic_vmProgram *program, cx_icOp op) { if (op1) { /* Operation has two operands */ if (op2) { - if (op3) { cx_vmOp3(program, vmOp, op, op1, op2, op3, opDeref1, opDeref2, opDeref3); } else if (storage && (storage != op1)) { diff --git a/interface/fast/src/Fast_PostFix.c b/interface/fast/src/Fast_PostFix.c index f1e5d554..e7e92a0e 100644 --- a/interface/fast/src/Fast_PostFix.c +++ b/interface/fast/src/Fast_PostFix.c @@ -47,8 +47,8 @@ cx_int16 Fast_PostFix_construct(Fast_PostFix _this) { goto error; break; } - break; Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(lvalueType)); + break; case CX_ITERATOR: if (_this->operator == CX_INC) { @@ -82,6 +82,7 @@ cx_ic Fast_PostFix_toIc_v(Fast_PostFix _this, cx_icProgram program, cx_icStorage cx_icStorage result; cx_ic lvalue; cx_icOp op = NULL; + cx_type lvalueType = Fast_Expression_getType(_this->lvalue); CX_UNUSED(stored); if (storage) { @@ -95,12 +96,13 @@ cx_ic Fast_PostFix_toIc_v(Fast_PostFix _this, cx_icProgram program, cx_icStorage } lvalue = Fast_Node_toIc(Fast_Node(_this->lvalue), program, result, TRUE); - - op = cx_icOp__create(program, Fast_Node(_this)->line, cx_icOpKindFromOperator(_this->operator), (cx_icValue)lvalue, NULL, NULL); + op = cx_icOp__create(program, Fast_Node(_this)->line, cx_icOpKindFromOperator(_this->operator), (cx_icValue)lvalue, (cx_icValue)result, NULL); cx_icProgram_addIc(program, (cx_ic)op); if (!storage) { cx_icProgram_accumulatorPop(program, Fast_Node(_this)->line); + } else if ((lvalueType->kind == CX_ITERATOR) && (_this->operator == CX_INC)) { + lvalue = (cx_ic)storage; } return (cx_ic)lvalue; diff --git a/interface/fast/src/Fast_Unary.c b/interface/fast/src/Fast_Unary.c index f17343bb..fc2cb144 100644 --- a/interface/fast/src/Fast_Unary.c +++ b/interface/fast/src/Fast_Unary.c @@ -34,6 +34,7 @@ cx_int16 Fast_Unary_construct(Fast_Unary _this) { if (_this->operator == CX_MUL) { cx_type iterType = cx_iterator(lvalueType)->elementType; Fast_Expression(_this)->type = Fast_Variable(Fast_Object__create(iterType)); + Fast_Expression(_this)->isReference = TRUE; } else { Fast_Parser_error(yparser(), "invalid operator for iterator"); goto error; @@ -78,12 +79,24 @@ cx_ic Fast_Unary_toIc_v(Fast_Unary _this, cx_icProgram program, cx_icStorage sto switch(_this->operator) { case CX_INC: case CX_DEC: - op = cx_icOp__create(program, Fast_Node(_this)->line, cx_icOpKindFromOperator(_this->operator), (cx_icValue)lvalue, NULL, NULL); + op = cx_icOp__create( + program, Fast_Node(_this)->line, cx_icOpKindFromOperator(_this->operator), + (cx_icValue)lvalue, NULL, NULL); cx_icProgram_addIc(program, (cx_ic)op); result = (cx_icStorage)lvalue; break; + case CX_MUL: + op = cx_icOp__create( + program, Fast_Node(_this)->line, CX_IC_SET, + NULL, (cx_icValue)result, (cx_icValue)lvalue); + cx_icProgram_addIc(program, (cx_ic)op); + op->s2Deref = CX_IC_DEREF_ADDRESS; + ((cx_icStorage)result)->isReference = TRUE; + break; default: - op = cx_icOp__create(program, Fast_Node(_this)->line, cx_icOpKindFromOperator(_this->operator), (cx_icValue)result, (cx_icValue)lvalue, NULL); + op = cx_icOp__create( + program, Fast_Node(_this)->line, cx_icOpKindFromOperator(_this->operator), + (cx_icValue)result, (cx_icValue)lvalue, NULL); cx_icProgram_addIc(program, (cx_ic)op); break; } From acfb9e68f90557152a4f2d2ac422296d048b21a6 Mon Sep 17 00:00:00 2001 From: SanderMertens Date: Sun, 22 Mar 2015 14:01:08 -0400 Subject: [PATCH 3/4] #14 Fixed iterators for lists --- cx/include/cx_def.h | 2 +- cx/src/cx_iterator.c | 77 +++++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/cx/include/cx_def.h b/cx/include/cx_def.h index 6b766785..d3f2d730 100644 --- a/cx/include/cx_def.h +++ b/cx/include/cx_def.h @@ -66,6 +66,7 @@ typedef struct cx_ll_s* cx_ll; #define CX_ITERATOR(__type) typedef struct __type {\ void *current;\ cx_collection type;\ + cx_bool (*next)(void* iterator);\ union {\ struct { /* CX_ARRAY and CX_SEQUENCE */\ void *array;\ @@ -73,7 +74,6 @@ typedef struct cx_ll_s* cx_ll; void* max;\ } array;\ struct {\ - cx_ll *ll;\ cx_iter iter;\ } ll;\ } is;\ diff --git a/cx/src/cx_iterator.c b/cx/src/cx_iterator.c index 7d348821..c6980f24 100644 --- a/cx/src/cx_iterator.c +++ b/cx/src/cx_iterator.c @@ -13,33 +13,6 @@ CX_ITERATOR(iteratorType); CX_SEQUENCE(seqType, cx_object, ); -cx_int16 cx_iterator_set(void* _this, void* collection, cx_collection collectionType) { - iteratorType *iter = _this; - iter->type = collectionType; - - switch (collectionType->kind) { - case CX_ARRAY: - iter->is.array.array = collection; - iter->is.array.elementSize = cx_type_sizeof(collectionType->elementType); - iter->is.array.max = CX_OFFSET(iter->is.array.array, collectionType->max * iter->is.array.elementSize); - iter->current = CX_OFFSET(collection, -iter->is.array.elementSize); - break; - case CX_SEQUENCE: - iter->is.array.array = ((seqType*)collection)->buffer; - iter->is.array.elementSize = cx_type_sizeof(collectionType->elementType); - iter->is.array.max = CX_OFFSET(iter->is.array.array, ((seqType*)collection)->length * iter->is.array.elementSize); - iter->current = CX_OFFSET(iter->is.array.array, -iter->is.array.elementSize); - break; - case CX_LIST: - iter->is.ll.ll = collection; - iter->is.ll.iter = cx_llIter(collection); - break; - case CX_MAP: - break; - } - return 0; -} - /* Combined hasNext and next */ static cx_bool cx_iterator_next_array(void* iterator) { iteratorType *iter = iterator; @@ -54,7 +27,17 @@ static cx_bool cx_iterator_next_array(void* iterator) { return result; } -static cx_bool cx_iterator_next_ll(void* iterator) { +static cx_bool cx_iterator_next_listPtr(void* iterator) { + iteratorType *iter = iterator; + cx_bool result = FALSE; + if ((result = cx_iterHasNext(&iter->is.ll.iter))) { + iter->current = cx_iterNextPtr(&iter->is.ll.iter); + result = TRUE; + } + return result; +} + +static cx_bool cx_iterator_next_list(void* iterator) { iteratorType *iter = iterator; cx_bool result = FALSE; if ((result = cx_iterHasNext(&iter->is.ll.iter))) { @@ -75,22 +58,44 @@ cx_bool cx_iterator_next(void* _this) { iteratorType *iterator = _this; cx_bool result = FALSE; - switch (iterator->type->kind) { + result = iterator->next(iterator); + + return result; +} + +cx_int16 cx_iterator_set(void* _this, void* collection, cx_collection collectionType) { + iteratorType *iter = _this; + iter->type = collectionType; + + switch (collectionType->kind) { case CX_ARRAY: + iter->is.array.array = collection; + iter->is.array.elementSize = cx_type_sizeof(collectionType->elementType); + iter->is.array.max = CX_OFFSET(iter->is.array.array, collectionType->max * iter->is.array.elementSize); + iter->current = CX_OFFSET(collection, -iter->is.array.elementSize); + iter->next = cx_iterator_next_array; + break; case CX_SEQUENCE: - result = cx_iterator_next_array(iterator); + iter->is.array.array = ((seqType*)collection)->buffer; + iter->is.array.elementSize = cx_type_sizeof(collectionType->elementType); + iter->is.array.max = CX_OFFSET(iter->is.array.array, ((seqType*)collection)->length * iter->is.array.elementSize); + iter->current = CX_OFFSET(iter->is.array.array, -iter->is.array.elementSize); + iter->next = cx_iterator_next_array; break; case CX_LIST: - result = cx_iterator_next_ll(iterator); + iter->is.ll.iter = cx_llIter(*(cx_ll*)collection); + if (cx_collection_elementRequiresAlloc(collectionType)) { + iter->next = cx_iterator_next_list; + } else { + iter->next = cx_iterator_next_listPtr; + } + break; case CX_MAP: - result = cx_iterator_next_map(iterator); - break; - default: + iter->next = cx_iterator_next_map; break; } - - return result; + return 0; } /* $end */ From a1ae49a4e268ebb553e2a9d474b93560a6896cda Mon Sep 17 00:00:00 2001 From: SanderMertens Date: Sun, 22 Mar 2015 23:41:23 -0400 Subject: [PATCH 4/4] #14 Iterator support for collections of references Fixes #14 --- dev/src/cx_ic.c | 16 ++- dev/src/cx_ic_assemble.c | 131 +++++++++++-------- interface/fast/src/Fast_DynamicInitializer.c | 3 + interface/fast/src/Fast_Initializer.c | 16 ++- interface/fast/src/Fast_Object.c | 5 +- interface/fast/src/Fast_StaticInitializer.c | 3 + interface/fast/src/Fast_Unary.c | 14 +- test/language/tc_iterator01.cx | 35 +++-- test/language/tc_iterator02.cx | 34 +++++ 9 files changed, 171 insertions(+), 86 deletions(-) create mode 100644 test/language/tc_iterator02.cx diff --git a/dev/src/cx_ic.c b/dev/src/cx_ic.c index 5cda261a..af1c444b 100644 --- a/dev/src/cx_ic.c +++ b/dev/src/cx_ic.c @@ -570,12 +570,14 @@ cx_icAccumulator cx_icAccumulator__create(cx_icProgram program, cx_uint32 line, cx_icMember cx_icMember__create(cx_icProgram program, cx_uint32 line, cx_icStorage base, cx_member member) { cx_icMember result; cx_id name; + cx_type t; sprintf(name, "%s.%s", base->name, cx_nameof(member)); + t = member->type; if (!(result = (cx_icMember)cx_icProgram_lookupStorage(program, name, TRUE))) { result = cx_calloc(sizeof(cx_icMember_s)); - cx_icStorage_init((cx_icStorage)result, program, line, CX_STORAGE_MEMBER, name, member->type); + cx_icStorage_init((cx_icStorage)result, program, line, CX_STORAGE_MEMBER, name, t); result->base = base; result->member = member; cx_llAppend(program->scope->storages, result); @@ -589,9 +591,13 @@ cx_icElement cx_icElement__create(cx_icProgram program, cx_uint32 line, cx_type cx_id name; cx_string elemStr; - elemStr = cx_icValue_toString(index, NULL); - sprintf(name, "%s[%s]", base->name, elemStr); - cx_dealloc(elemStr); + if (index) { + elemStr = cx_icValue_toString(index, NULL); + sprintf(name, "%s[%s]", base->name, elemStr); + cx_dealloc(elemStr); + } else { + sprintf(name, "*%s", base->name); + } if (!(result = (cx_icElement)cx_icProgram_lookupStorage(program, name, TRUE))) { result = cx_calloc(sizeof(cx_icElement_s)); @@ -599,7 +605,7 @@ cx_icElement cx_icElement__create(cx_icProgram program, cx_uint32 line, cx_type result->base = base; result->index = index; result->collectionType = (cx_collection)base->type; - result->dynamic = !(index->_parent.kind == CX_IC_LITERAL); + result->dynamic = !index || !(index->_parent.kind == CX_IC_LITERAL); cx_llAppend(program->scope->storages, result); } diff --git a/dev/src/cx_ic_assemble.c b/dev/src/cx_ic_assemble.c index 2223e09c..f02c761b 100644 --- a/dev/src/cx_ic_assemble.c +++ b/dev/src/cx_ic_assemble.c @@ -444,8 +444,13 @@ static cx_ic_vmStorage *cx_ic_vmStorageNew(cx_ic_vmProgram *program, cx_icStorag if (element->base) { result->base = cx_ic_vmStorageGet(program, element->base); + /* Iterator elements are a special case throuhg which access to the current member + * is granted */ + if (element->base->type->kind == CX_ITERATOR) { + result->dynamic = TRUE; + /* If element is an array and index-expression is a literal, offset is determined at compile-time. */ - if (element->index->_parent.kind == CX_IC_LITERAL) { + } else if (element->index->_parent.kind == CX_IC_LITERAL) { if (element->collectionType->kind == CX_ARRAY) { cx_uint32 index = ((cx_icLiteral)element->index)->value.is.literal.v._unsigned_integer; result->offset = index * cx_type_sizeof(element->collectionType->elementType); @@ -464,7 +469,7 @@ static cx_ic_vmStorage *cx_ic_vmStorageNew(cx_ic_vmProgram *program, cx_icStorag result->offset += result->base->offset; - if (!result->base->dynamic && result->base->base) { + if (!result->base->dynamic && result->base->base) { result->base = result->base->base; } } @@ -1154,45 +1159,53 @@ OPS_EXP_EXT(GETOP, TYPE,) static cx_vmOp *cx_ic_vmStorageAssembleElement(cx_icStorage storage, cx_ic_vmProgram *program, cx_vmOp *vmOp, cx_icStorage topLevelStorage) { - cx_ic_vmOperand indexKind; - cx_icValue icElementSize; - cx_collection type = cx_collection(((cx_icElement)storage)->base->type); /* Obtain collectiontype */ - cx_value elementSizeValue; - cx_uint64 elementSize; + cx_type type = ((cx_icElement)storage)->base->type; /* Obtain kind for index */ - indexKind = cx_ic_getVmOperand(program, CX_IC_DEREF_VALUE, ((cx_icElement)storage)->index); - - /* Create value for elementSize */ - elementSize = cx_type_sizeof(type->elementType); - cx_valueLiteralInit(&elementSizeValue, CX_LITERAL_UNSIGNED_INTEGER, &elementSize); - icElementSize = (cx_icValue)cx_icLiteral__create(program->icProgram, ((cx_ic)storage)->line, elementSizeValue, (cx_type)cx_uint32_o); - - switch(type->kind) { - case CX_ARRAY: - vmOp->op = cx_ic_getVmELEMA(cx_type(type), CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); - cx_ic_vmSetOp3Addr(program, vmOp, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, CX_IC_VMOPERAND_V, (cx_icValue)topLevelStorage, ((cx_icElement)storage)->index, icElementSize); - break; - case CX_SEQUENCE: - vmOp->op = cx_ic_getVmELEMS(cx_type(type), CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); - cx_ic_vmSetOp3Addr(program, vmOp, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, CX_IC_VMOPERAND_V, (cx_icValue)topLevelStorage, ((cx_icElement)storage)->index, icElementSize); - break; - case CX_LIST: - if (cx_collection_elementRequiresAlloc(type)) { - vmOp->op = cx_ic_getVmELEML(cx_type(type), CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); - } else { - vmOp->op = cx_ic_getVmELEMLX(cx_type(type), CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); - } - cx_ic_vmSetOp2Addr(program, vmOp, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, (cx_icValue)topLevelStorage, ((cx_icElement)storage)->index); - break; - case CX_MAP: - if (cx_collection_elementRequiresAlloc(type)) { - vmOp->op = cx_ic_getVmELEMM(cx_type(type), CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); - } else { - vmOp->op = cx_ic_getVmELEMMX(cx_type(type), CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); + if (type->kind == CX_ITERATOR) { + cx_ic_vmOperand baseKind = cx_ic_getVmOperand(program, CX_IC_DEREF_VALUE, (cx_icValue)((cx_icElement)storage)->base); + vmOp->op = cx_ic_getVmSET(type, CX_IC_VMTYPE_D, CX_IC_VMOPERAND_R, baseKind, 0); + cx_ic_vmSetOp2Addr(program, vmOp, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, baseKind, + (cx_icValue)topLevelStorage, (cx_icValue)((cx_icElement)storage)->base); + + }else if (type->kind == CX_COLLECTION) { + cx_icValue icElementSize; + cx_value elementSizeValue; + cx_uint64 elementSize; + cx_collection collection = cx_collection(type); + cx_ic_vmOperand indexKind = cx_ic_getVmOperand(program, CX_IC_DEREF_VALUE, ((cx_icElement)storage)->index); + + /* Create value for elementSize */ + elementSize = cx_type_sizeof(collection->elementType); + cx_valueLiteralInit(&elementSizeValue, CX_LITERAL_UNSIGNED_INTEGER, &elementSize); + icElementSize = (cx_icValue)cx_icLiteral__create(program->icProgram, ((cx_ic)storage)->line, elementSizeValue, (cx_type)cx_uint32_o); + + switch(collection->kind) { + case CX_ARRAY: + vmOp->op = cx_ic_getVmELEMA(type, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); + cx_ic_vmSetOp3Addr(program, vmOp, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, CX_IC_VMOPERAND_V, (cx_icValue)topLevelStorage, ((cx_icElement)storage)->index, icElementSize); + break; + case CX_SEQUENCE: + vmOp->op = cx_ic_getVmELEMS(type, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); + cx_ic_vmSetOp3Addr(program, vmOp, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, CX_IC_VMOPERAND_V, (cx_icValue)topLevelStorage, ((cx_icElement)storage)->index, icElementSize); + break; + case CX_LIST: + if (cx_collection_elementRequiresAlloc(collection)) { + vmOp->op = cx_ic_getVmELEML(type, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); + } else { + vmOp->op = cx_ic_getVmELEMLX(type, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); + } + cx_ic_vmSetOp2Addr(program, vmOp, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, (cx_icValue)topLevelStorage, ((cx_icElement)storage)->index); + break; + case CX_MAP: + if (cx_collection_elementRequiresAlloc(collection)) { + vmOp->op = cx_ic_getVmELEMM(type, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); + } else { + vmOp->op = cx_ic_getVmELEMMX(type, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, 0); + } + cx_ic_vmSetOp2Addr(program, vmOp, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, (cx_icValue)topLevelStorage, ((cx_icElement)storage)->index); + break; } - cx_ic_vmSetOp2Addr(program, vmOp, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, indexKind, (cx_icValue)topLevelStorage, ((cx_icElement)storage)->index); - break; } return cx_vmProgram_addOp(program->program, ((cx_ic)storage)->line); @@ -1257,30 +1270,32 @@ static cx_vmOp *cx_ic_vmStorageAssembleNested(cx_icStorage icStorage, cx_ic_vmPr * is dynamic the address will be calculated at runtime. */ if (storage->dynamic || cx_ic_isReference(storage->base->accumulator)) { /* If the base is an object store the address in the accumulator */ - if (base->kind == CX_STORAGE_OBJECT) { - vmOp->op = sizeof(intptr_t) == 4 ? CX_VM_SET_LRV : CX_VM_SET_DRV; - cx_ic_vmStorageAddReferee(program, topLevelStorage, &vmOp->ic.b._1); - vmOp->lo.w = (intptr_t)((cx_icObject)base)->ptr; - if (storage->offset) { - vmOp->lo.w += storage->offset; - } - vmOp = cx_vmProgram_addOp(program->program, ((cx_ic)icStorage)->line); - - /* If the base is a local store the address of the local in the accumulator */ - } else if (base->kind == CX_STORAGE_LOCAL) { - if (!cx_ic_isReference(storage->base->accumulator)) { - vmOp->op = cx_ic_getVmSETX(NULL, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, CX_IC_VMOPERAND_R, 0); + if (base->type->kind != CX_ITERATOR) { + if (base->kind == CX_STORAGE_OBJECT) { + vmOp->op = sizeof(intptr_t) == 4 ? CX_VM_SET_LRV : CX_VM_SET_DRV; cx_ic_vmStorageAddReferee(program, topLevelStorage, &vmOp->ic.b._1); - vmOp->ic.b._2 = storage->base->addr; + vmOp->lo.w = (intptr_t)((cx_icObject)base)->ptr; if (storage->offset) { - vmOp->ic.b._2 += storage->offset; + vmOp->lo.w += storage->offset; } vmOp = cx_vmProgram_addOp(program->program, ((cx_ic)icStorage)->line); - } else { - vmOp->op = sizeof(intptr_t) == 4 ? CX_VM_SET_LRR : CX_VM_SET_DRR; - cx_ic_vmStorageAddReferee(program, topLevelStorage, &vmOp->ic.b._1); - vmOp->ic.b._2 = storage->base->addr; - vmOp = cx_vmProgram_addOp(program->program, ((cx_ic)icStorage)->line); + + /* If the base is a local store the address of the local in the accumulator */ + } else if (base->kind == CX_STORAGE_LOCAL) { + if (!cx_ic_isReference(storage->base->accumulator)) { + vmOp->op = cx_ic_getVmSETX(NULL, CX_IC_VMTYPE_W, CX_IC_VMOPERAND_R, CX_IC_VMOPERAND_R, 0); + cx_ic_vmStorageAddReferee(program, topLevelStorage, &vmOp->ic.b._1); + vmOp->ic.b._2 = storage->base->addr; + if (storage->offset) { + vmOp->ic.b._2 += storage->offset; + } + vmOp = cx_vmProgram_addOp(program->program, ((cx_ic)icStorage)->line); + } else { + vmOp->op = sizeof(intptr_t) == 4 ? CX_VM_SET_LRR : CX_VM_SET_DRR; + cx_ic_vmStorageAddReferee(program, topLevelStorage, &vmOp->ic.b._1); + vmOp->ic.b._2 = storage->base->addr; + vmOp = cx_vmProgram_addOp(program->program, ((cx_ic)icStorage)->line); + } } } diff --git a/interface/fast/src/Fast_DynamicInitializer.c b/interface/fast/src/Fast_DynamicInitializer.c index 486b7194..9da8a885 100644 --- a/interface/fast/src/Fast_DynamicInitializer.c +++ b/interface/fast/src/Fast_DynamicInitializer.c @@ -49,6 +49,9 @@ Fast_Expression Fast_Initializer_expr(Fast_DynamicInitializer _this, cx_uint8 va case CX_PRIMITIVE: result = base; break; + case CX_ITERATOR: + result = base; + break; case CX_COMPOSITE: if (fp) { Fast_String memberString = Fast_String__create(cx_nameof(thisFrame->member)); diff --git a/interface/fast/src/Fast_Initializer.c b/interface/fast/src/Fast_Initializer.c index 15fce50a..558482fe 100644 --- a/interface/fast/src/Fast_Initializer.c +++ b/interface/fast/src/Fast_Initializer.c @@ -130,7 +130,8 @@ cx_type Fast_Parser_initGetType(Fast_Initializer _this, cx_member *m_out) { } else { if (m_out) { cx_id id; - Fast_Parser_error(yparser(), "too many elements for non-composite\\collection type '%s'", Fast_Parser_id(t, id)); + Fast_Parser_error(yparser(), + "too many elements for non-composite\\collection type '%s'", Fast_Parser_id(t, id)); result = NULL; } } @@ -181,7 +182,8 @@ cx_int16 Fast_Initializer_construct(Fast_Initializer _this) { #ifdef CX_INIT_DEBUG { cx_id id, id2; - printf("%*s%d[%s %p]: construct (type=%s)\n", indent, " ", yparser()->line, Fast_Parser_id(cx_typeof(_this), id), _this, Fast_Parser_id(t, id2)); + printf("%*s%d[%s %p]: construct (type=%s)\n", + indent, " ", yparser()->line, Fast_Parser_id(cx_typeof(_this), id), _this, Fast_Parser_id(t, id2)); indent++; } #endif @@ -319,7 +321,8 @@ cx_int16 Fast_Initializer_next_v(Fast_Initializer _this) { { cx_id id, id2; printf("%*s%d[%s %p]: next(fp=%d, location=%d, type=%s, member=%s)\n", - indent, " ", yparser()->line, Fast_Parser_id(cx_typeof(_this), id), _this, _this->fp, _this->frames[_this->fp].location, + indent, " ", yparser()->line, Fast_Parser_id(cx_typeof(_this), id), _this, _this->fp, + _this->frames[_this->fp].location, _this->frames[_this->fp].type?Fast_Parser_id(_this->frames[_this->fp].type, id2):NULL, _this->frames[_this->fp].member?cx_nameof(_this->frames[_this->fp].member):NULL); } @@ -340,7 +343,9 @@ cx_int8 Fast_Initializer_pop_v(Fast_Initializer _this) { { cx_id id; indent--; - printf("%*s%d[%s %p]: pop(fp=%d, location=%d)\n", indent, " ", yparser()->line, Fast_Parser_id(cx_typeof(_this), id), _this, _this->fp, _this->frames[_this->fp].location); + printf("%*s%d[%s %p]: pop(fp=%d, location=%d)\n", + indent, " ", yparser()->line, + Fast_Parser_id(cx_typeof(_this), id), _this, _this->fp, _this->frames[_this->fp].location); } #endif Fast_Initializer_next(_this); @@ -373,7 +378,8 @@ cx_int16 Fast_Initializer_push_v(Fast_Initializer _this) { cx_id id, id2; printf("%*s%d[%s %p]: push(fp=%d, location=%d, type=%s, member=%s)\n", indent, " ", yparser()->line, Fast_Parser_id(cx_typeof(_this), id), _this, _this->fp, - _this->frames[_this->fp].location, _this->frames[_this->fp].type?Fast_Parser_id(_this->frames[_this->fp].type, id2):NULL, + _this->frames[_this->fp].location, + _this->frames[_this->fp].type ? Fast_Parser_id(_this->frames[_this->fp].type, id2) : NULL, _this->frames[_this->fp].member?cx_nameof(_this->frames[_this->fp].member):NULL); indent++; } diff --git a/interface/fast/src/Fast_Object.c b/interface/fast/src/Fast_Object.c index 3027ecff..84f08ba0 100644 --- a/interface/fast/src/Fast_Object.c +++ b/interface/fast/src/Fast_Object.c @@ -66,7 +66,10 @@ cx_int16 Fast_Object_serialize(Fast_Object _this, cx_type dstType, cx_word dst) dstIsDelegate = TRUE; } - if (dstIsDelegate) { + /* Handle iterators */ + if ((dstType->kind == CX_ITERATOR) && (srcType->kind == CX_COLLECTION)) { + cx_iterator_set((void*)dst, obj, cx_collection(srcType)); + } else if (dstIsDelegate) { if (srcIsDelegate) { cx_value vDst, vSrc; cx_valueValueInit(&vDst, NULL, cx_type(dstType), (void *)dst); diff --git a/interface/fast/src/Fast_StaticInitializer.c b/interface/fast/src/Fast_StaticInitializer.c index c2bb3e5d..38b240cd 100644 --- a/interface/fast/src/Fast_StaticInitializer.c +++ b/interface/fast/src/Fast_StaticInitializer.c @@ -46,6 +46,9 @@ cx_word Fast_Initializer_offset(Fast_StaticInitializer _this, cx_uint32 variable result = base; } break; + case CX_ITERATOR: + result = base; + break; case CX_COLLECTION: { if (fp) { cx_uint32 elementSize = cx_type_sizeof(cx_collection(frame->type)->elementType); diff --git a/interface/fast/src/Fast_Unary.c b/interface/fast/src/Fast_Unary.c index fc2cb144..aacf8151 100644 --- a/interface/fast/src/Fast_Unary.c +++ b/interface/fast/src/Fast_Unary.c @@ -62,6 +62,7 @@ cx_ic Fast_Unary_toIc_v(Fast_Unary _this, cx_icProgram program, cx_icStorage sto cx_icStorage result; cx_ic lvalue; cx_icOp op; + cx_type lvalueType = Fast_Expression_getType(_this->lvalue); CX_UNUSED(stored); if (storage) { @@ -85,14 +86,13 @@ cx_ic Fast_Unary_toIc_v(Fast_Unary _this, cx_icProgram program, cx_icStorage sto cx_icProgram_addIc(program, (cx_ic)op); result = (cx_icStorage)lvalue; break; - case CX_MUL: - op = cx_icOp__create( - program, Fast_Node(_this)->line, CX_IC_SET, - NULL, (cx_icValue)result, (cx_icValue)lvalue); - cx_icProgram_addIc(program, (cx_ic)op); - op->s2Deref = CX_IC_DEREF_ADDRESS; - ((cx_icStorage)result)->isReference = TRUE; + case CX_MUL: { + /* Create an element with the iterator as base */ + result = + (cx_icStorage)cx_icElement__create( + program, Fast_Node(_this)->line, cx_iterator(lvalueType)->elementType, (cx_icStorage)lvalue, NULL); break; + } default: op = cx_icOp__create( program, Fast_Node(_this)->line, cx_icOpKindFromOperator(_this->operator), diff --git a/test/language/tc_iterator01.cx b/test/language/tc_iterator01.cx index 02edcc7d..06309067 100644 --- a/test/language/tc_iterator01.cx +++ b/test/language/tc_iterator01.cx @@ -1,17 +1,32 @@ -// Iterator assignments - -bool result : true +bool result: true void fail(string msg): "tc_iterator01: FAIL: $msg" result = false -array sarray: string, 1 -sarray array1: "a" +array{int32, 3} intArray: 1, 2, 3 +sequence{int32} intSeq: 2, 3, 4 +list{int32} intList: 3, 4, 5 + +iterator{int32} a : intArray +iterator{int32} b : intSeq +iterator{int32} c : intList + +var int32 total +while a++: total += *a +if total != 6: fail("total != 6 (array)") + +total = 0 +while b++: total += *b +if total != 9: fail("total != 9 (sequence)") -iterator siter: string -siter iter1 -iter1 = array1 +total = 0 +while c++: total += *c +if total != 12: fail("total != 12 (list)") -iter1++ +// Reassign iterator +a = intSeq +total = 0 +while a++: total += *a +if total != 9: fail("total != 6 (sequence #2)") -if result: "$testname: OK" +if result: "tc_iterator01: OK" diff --git a/test/language/tc_iterator02.cx b/test/language/tc_iterator02.cx new file mode 100644 index 00000000..3a1ac603 --- /dev/null +++ b/test/language/tc_iterator02.cx @@ -0,0 +1,34 @@ +bool result: true +void fail(string msg): + "tc_iterator02: FAIL: $msg" + result = false + +struct Point:: x, y: int32 + +array{Point, 3} pArray: {1, 2}, {3, 4}, {5, 6} +sequence{Point} pSeq: {3, 4}, {5, 6}, {7, 8} +list{Point} pList: {5, 6}, {7, 8}, {9, 10} + +iterator{Point} a : pArray +iterator{Point} b : pSeq +iterator{Point} c : pList + +var Point total +while a++: total[x, y] += *a[x, y] +if total[x, y] != (9, 12): fail("total[x, y] != (9, 12) (array)") + +total = {0, 0} +while b++: total[x, y] += *b[x, y] +if total[x, y] != (15, 18): fail("total[x, y] != (15, 18) (sequence)") + +total = {0, 0} +while c++: total[x, y] += *c[x, y] +if total[x, y] != (21, 24): fail("total[x, y] != (21, 24) (list)") + +// Reassign iterator +a = pSeq +total = {0, 0} +while a++: total[x, y] += *a[x, y] +if total[x, y] != (15, 18): fail("total[x, y] != (15, 18) (sequence #2)") + +if result: "tc_iterator02: OK"