Skip to content

Commit

Permalink
Merge pull request #2054 from actonlang/iterator_exceptions3
Browse files Browse the repository at this point in the history
Replace C NULL for iter stop with StopIteration
  • Loading branch information
nordlander authored Jan 8, 2025
2 parents 98b4bfd + a6e67c1 commit 0331f53
Show file tree
Hide file tree
Showing 23 changed files with 388 additions and 189 deletions.
2 changes: 1 addition & 1 deletion base/builtin/builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ typedef struct $Catcher *$Catcher;
#include "class_hierarchy.h"
#include "serialize.h"
#include "registration.h"
#include "exceptions.h"
#include "Iterator.h"
#include "complx.h"
#include "box.h"
Expand All @@ -105,7 +106,6 @@ typedef struct $Catcher *$Catcher;
#include "u32.h"
#include "u16.h"
#include "range.h"
#include "exceptions.h"
#include "function.h"
#include "builtin_functions.h"
#include "env.h"
Expand Down
155 changes: 101 additions & 54 deletions base/builtin/builtin_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,7 @@ B_IteratorD_enumerate B_IteratorD_enumerate$_deserialize(B_IteratorD_enumerate r

$WORD B_IteratorD_enumerate_next(B_IteratorD_enumerate it) {
$WORD w = it->it->$class->__next__(it->it);
if (w)
return $NEWTUPLE(2,to$int(it->nxt++),w);
else
return NULL;
return $NEWTUPLE(2,to$int(it->nxt++),w);
}

struct B_IteratorD_enumerateG_class B_IteratorD_enumerateG_methods = {"B_IteratorD_enumerate",UNASSIGNED,($SuperG_class)&B_IteratorG_methods,B_IteratorD_enumerate_init,
Expand Down Expand Up @@ -170,7 +167,7 @@ B_IteratorD_filter B_IteratorD_filter$_deserialize(B_IteratorD_filter res, $Seri
$WORD w;
do
w = it->it->$class->__next__(it->it);
while (w && !fromB_bool(it->f->$class->__eval__(it->f, w)));
while (!fromB_bool(it->f->$class->__eval__(it->f, w)));
return w;
}

Expand Down Expand Up @@ -215,10 +212,7 @@ B_IteratorD_map B_IteratorD_map$_deserialize(B_IteratorD_map res, $Serial$state

$WORD B_IteratorD_map_next(B_IteratorD_map it) {
$WORD w = it->it->$class->__next__(it->it);
if (w)
return it->f->$class->__eval__(it->f, w);
else
return NULL;
return it->f->$class->__eval__(it->f, w);
}

struct B_IteratorD_mapG_class B_IteratorD_mapG_methods = {"B_IteratorD_map",UNASSIGNED,($SuperG_class)&B_IteratorG_methods,B_IteratorD_map_init,
Expand All @@ -237,64 +231,106 @@ B_Iterator B_map(B_Iterable wit, $pure f, $WORD iter) {

// max, min ///////////////////////////////////////////////////////////////////////////////////

$WORD B_max(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt) {
$WORD B_max(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD dflt) {
$WORD res = dflt;
B_Iterator it = wit2->$class->__iter__(wit2,iter);
$WORD res, nxt;
res = it->$class->__next__(it);
if (res) {
while ((nxt = it->$class->__next__(it))) {
if (wit->$class->__lt__(wit,res,nxt)->val)
while(1) {
if ($PUSH()) {
$WORD nxt = it->$class->__next__(it);
if (!res || fromB_bool(wit->$class->__lt__(wit,res,nxt)))
res = nxt;
$DROP();
} else {
B_BaseException ex = $POP();
if ($ISINSTANCE0(ex, B_StopIteration))
break;
else
$RAISE(ex);
}
}

// If no value was found in the iterable
if (!res) {
if (dflt) {
return dflt; // Return the provided default value
} else {
$RAISE(((B_BaseException)B_ValueErrorG_new($FORMAT("max() arg is an empty sequence"))));
}
return res;
} else
return deflt;
}

$WORD B_max_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt) {
B_Iterator it = wit2->$class->__iter__(wit2, iter);
$WORD res, nxt;
res = it->$class->__next__(it);
if (res) {
while ((nxt = it->$class->__next__(it))) {
if (wit->$class->__lt__(wit, res, nxt)->val)
}

return res;
}

$WORD B_max_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD dflt) {
$WORD res = dflt;
B_Iterator it = wit2->$class->__iter__(wit2,iter);
while(1) {
if ($PUSH()) {
$WORD nxt = it->$class->__next__(it);
if (fromB_bool(wit->$class->__lt__(wit,res,nxt)))
res = nxt;
$DROP();
} else {
B_BaseException ex = $POP();
if ($ISINSTANCE0(ex, B_StopIteration))
break;
else
$RAISE(ex);
}
return res;
} else {
return deflt; // Return default if iterable is empty
}
return res;
}

$WORD B_min(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt) {
$WORD B_min(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD dflt) {
$WORD res = NULL;
B_Iterator it = wit2->$class->__iter__(wit2,iter);
$WORD res, nxt;
res = it->$class->__next__(it);
if (res) {
while ((nxt = it->$class->__next__(it))) {
if (wit->$class->__gt__(wit,res,nxt)->val)
while(1) {
if ($PUSH()) {
$WORD nxt = it->$class->__next__(it);
if (!res || fromB_bool(wit->$class->__gt__(wit,res,nxt)))
res = nxt;
$DROP();
} else {
B_BaseException ex = $POP();
if ($ISINSTANCE0(ex, B_StopIteration))
break;
else
$RAISE(ex);
}
return res;
} else
return deflt;
}

$WORD B_min_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt) {
B_Iterator it = wit2->$class->__iter__(wit2, iter);
$WORD res, nxt;
res = it->$class->__next__(it);
if (res) {
while ((nxt = it->$class->__next__(it))) {
if (wit->$class->__gt__(wit, res, nxt)->val)
}

// If no value was found in the iterable
if (!res) {
if (dflt) {
return dflt; // Return the provided default value
} else {
$RAISE((B_BaseException)B_ValueErrorG_new($FORMAT("min() arg is an empty sequence")));
}
}

return res;
}

$WORD B_min_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD dflt) {
$WORD res = dflt;
B_Iterator it = wit2->$class->__iter__(wit2,iter);
while(1) {
if ($PUSH()) {
$WORD nxt = it->$class->__next__(it);
if (fromB_bool(wit->$class->__gt__(wit,res,nxt)))
res = nxt;
$DROP();
} else {
B_BaseException ex = $POP();
if ($ISINSTANCE0(ex, B_StopIteration))
break;
else
$RAISE(ex);
}
return res;
} else {
return deflt; // Return default if iterable is empty
}
return res;
}

B_list B_sorted(B_Ord wit, B_Iterable wit2, $WORD iter) {
B_CollectionD_SequenceD_list w = B_CollectionD_SequenceD_listG_witness;
B_list res = w->$class->__fromiter__(w, wit2, iter);
Expand All @@ -312,8 +348,19 @@ B_list B_sorted(B_Ord wit, B_Iterable wit2, $WORD iter) {
}

$WORD nxt;
while ((nxt = it->$class->__next__(it)))
res = wit->$class->__add__(wit, res, nxt);
while(1) {
if ($PUSH()) {
nxt = it->$class->__next__(it);
res = wit->$class->__add__(wit,res,nxt);
$DROP();
} else {
B_BaseException ex = $POP();
if ($ISINSTANCE0(ex, B_StopIteration))
break;
else
$RAISE(ex);
}
}
return res;
}

Expand Down
2 changes: 1 addition & 1 deletion base/builtin/builtin_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ struct $IdentityActor {

$WORD B_min(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt);
$WORD B_max(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt);
$WORD B_max_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt);
$WORD B_min_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt);
$WORD B_max_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt);

// Signatures generated by actonc

Expand Down
69 changes: 51 additions & 18 deletions base/builtin/dict.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,18 @@ B_NoneType B_dictD___init__(B_dict dict, B_Hashable hashwit, B_Iterable wit, $WO
dict->table = NULL;
if (wit && iterable) {
B_Iterator it = wit->$class->__iter__(wit,iterable);
B_tuple nxt;
while((nxt = (B_tuple)it->$class->__next__(it))) {
B_dictD_setitem(dict,hashwit,nxt->components[0],nxt->components[1]);
while(1) {
if ($PUSH()) {
B_tuple nxt = (B_tuple)it->$class->__next__(it);
B_dictD_setitem(dict,hashwit,nxt->components[0],nxt->components[1]);
$DROP();
} else {
B_BaseException ex = $POP();
if ($ISINSTANCE0(ex, B_StopIteration))
break;
else
$RAISE(ex);
}
}
}
return B_None;
Expand Down Expand Up @@ -337,13 +346,23 @@ B_bool B_dictrel(bool directfalse,B_OrdD_dict w, B_dict a, B_dict b) {
B_MappingD_dict m = B_MappingD_dictG_new(wH);
B_Iterator it = m->$class->keys(m,a);
$WORD x,resa,resb;
while ((x = $next(it))) {
long h = 0;
if (a->table->tb_size > INIT_SIZE)
h = from$int(wH->$class->__hash__(wH,x));
int ixa = $lookdict(a, wH, h, x, &resa);
int ixb = $lookdict(b, wH, h, x ,&resb);
if (ixb<0 || wB->$class->__ne__(wB,resa,resb)->val) return B_False;
while(1) {
if ($PUSH()) {
x = it->$class->__next__(it);
long h = 0;
if (a->table->tb_size > INIT_SIZE)
h = from$int(wH->$class->__hash__(wH,x));
int ixa = $lookdict(a, wH, h, x, &resa);
int ixb = $lookdict(b, wH, h, x ,&resb);
if (ixb<0 || wB->$class->__ne__(wB,resa,resb)->val) return B_False;
$DROP();
} else {
B_BaseException ex = $POP();
if ($ISINSTANCE0(ex, B_StopIteration))
break;
else
$RAISE(ex);
}
}
return B_True;
}
Expand Down Expand Up @@ -378,7 +397,7 @@ B_bool B_OrdD_dictD___ge__ (B_OrdD_dict w, B_dict a, B_dict b) {

static $WORD B_IteratorD_dictD_next(B_IteratorD_dict self) {
if (!self->src->table)
return NULL;
$RAISE ((B_BaseException)$NEW(B_StopIteration, to$str("dict keys iterator terminated")));
int i = self->nxt;
$table table = self->src->table;
int n = table->tb_nentries;
Expand All @@ -390,6 +409,7 @@ static $WORD B_IteratorD_dictD_next(B_IteratorD_dict self) {
}
i++;
}
$RAISE ((B_BaseException)$NEW(B_StopIteration, to$str("dict keys iterator terminated")));
return NULL;
}

Expand Down Expand Up @@ -435,6 +455,8 @@ B_Iterator B_MappingD_dictD___iter__ (B_MappingD_dict wit, B_dict dict) {
}

B_dict B_MappingD_dictD___fromiter__ (B_MappingD_dict wit, B_Iterable wit2, $WORD iter) {
return B_dictG_new(wit->W_HashableD_AD_MappingD_dict, wit2, iter);
/*
B_Iterator it = wit2->$class->__iter__(wit2,iter);
B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;
B_dict dict = $NEW(B_dict,hashwit,NULL,NULL);
Expand All @@ -443,6 +465,7 @@ B_dict B_MappingD_dictD___fromiter__ (B_MappingD_dict wit, B_Iterable wit2, $WOR
B_dictD_setitem(dict,hashwit,nxt->components[0],nxt->components[1]);
}
return dict;
*/
}

B_int B_MappingD_dictD___len__ (B_MappingD_dict wit, B_dict dict) {
Expand Down Expand Up @@ -558,7 +581,7 @@ static $WORD B_IteratorD_dict_values_next(B_IteratorD_dict_values self) {
int i = self->nxt;
$table table = self->src->table;
if(!table)
return NULL;
$RAISE ((B_BaseException)$NEW(B_StopIteration, to$str("dict values iterator terminated")));
int n = table->tb_nentries;
while (i < n) {
$entry_t entry = &TB_ENTRIES(table)[i];
Expand All @@ -568,7 +591,7 @@ static $WORD B_IteratorD_dict_values_next(B_IteratorD_dict_values self) {
}
i++;
}
return NULL;
$RAISE ((B_BaseException)$NEW(B_StopIteration, to$str("dict values iterator terminated")));
}

B_IteratorD_dict_values B_IteratorD_dict_valuesG_new(B_dict dict) {
Expand Down Expand Up @@ -612,7 +635,7 @@ static $WORD B_IteratorD_dict_items_next(B_IteratorD_dict_items self) {
int i = self->nxt;
$table table = self->src->table;
if(!table)
return NULL;
$RAISE ((B_BaseException)$NEW(B_StopIteration, to$str("dict items iterator terminated")));
int n = table->tb_nentries;
while (i < n) {
$entry_t entry = &TB_ENTRIES(table)[i];
Expand All @@ -622,7 +645,7 @@ static $WORD B_IteratorD_dict_items_next(B_IteratorD_dict_items self) {
}
i++;
}
return NULL;
$RAISE ((B_BaseException)$NEW(B_StopIteration, to$str("dict items iterator terminated")));
}

B_IteratorD_dict_items B_IteratorD_dict_itemsG_new(B_dict dict) {
Expand Down Expand Up @@ -673,9 +696,19 @@ B_Iterator B_MappingD_dictD_items (B_MappingD_dict wit, B_dict dict) {
B_NoneType B_MappingD_dictD_update (B_MappingD_dict wit, B_dict dict, B_Iterable wit2, $WORD other) {
B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;
B_Iterator it = wit2->$class->__iter__(wit2,other);
B_tuple item;
while ((item = (B_tuple)it->$class->__next__(it)))
B_dictD_setitem(dict,hashwit,item->components[0],item->components[1]);
while(1) {
if ($PUSH()) {
B_tuple item = it->$class->__next__(it);
B_dictD_setitem(dict,hashwit,item->components[0],item->components[1]);
$DROP();
} else {
B_BaseException ex = $POP();
if ($ISINSTANCE0(ex, B_StopIteration))
break;
else
$RAISE(ex);
}
}
return B_None;
}

Expand Down
14 changes: 14 additions & 0 deletions base/builtin/exceptions.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
#include <setjmp.h>

struct JumpBuf;
typedef struct JumpBuf *JumpBuf;
struct JumpBuf {
jmp_buf buf;
B_BaseException xval;
JumpBuf prev;
};

void $RAISE(B_BaseException e);
JumpBuf $PUSH_BUF();
void $DROP();
B_BaseException $POP();
#define $PUSH() (!setjmp($PUSH_BUF()->buf))


/*
Exceptions hierarchy in Python 3.8 according to
Expand Down
Loading

0 comments on commit 0331f53

Please sign in to comment.