3 Copyright (C) 2008 Lutz Mueller
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 extern SYMBOL
* starSymbol
;
26 extern SYMBOL
* plusSymbol
;
27 extern SYMBOL
* sysSymbol
[];
29 extern CELL
* firstFreeCell
;
31 /* following used in count, difference, intersect, uniwue and sort 8.6.2 */
32 CELL
* * listToSortedVector(CELL
* list
, ssize_t
* length
, CELL
* func
, int indexFlag
);
33 CELL
* resortVectorToList(CELL
* * vector
, ssize_t length
);
34 void binsort(CELL
* * x
, ssize_t n
, CELL
* pCell
);
37 CELL
* p_map(CELL
* params
)
49 sPtr
= evaluateExpression(params
);
51 /* get first of argument lists */
52 params
= params
->next
;
53 argsPtr
= cell
= copyCell(evaluateExpression(params
));
54 if(!isList(cell
->type
))
55 return(errorProcExt(ERR_LIST_EXPECTED
, params
));
57 while ((params
= params
->next
) != nilCell
)
59 cell
->next
= copyCell(evaluateExpression(params
));
62 if(!isList(cell
->type
))
63 return(errorProcExt(ERR_LIST_EXPECTED
, params
));
66 results
= getCell(CELL_EXPRESSION
);
68 resultIdxSave
= resultStackIdx
;
69 while(argsPtr
->contents
!= (UINT
)nilCell
) /* for all instances of a arg */
71 expr
= getCell(CELL_EXPRESSION
);
72 cell
= copyCell(sPtr
);
73 expr
->contents
= (UINT
)cell
;
75 while(arg
!= nilCell
) /* for all args */
77 qCell
= getCell(CELL_QUOTE
);
79 cell
= (CELL
*)arg
->contents
; /* pop out first */
80 arg
->contents
= (UINT
)cell
->next
;
81 qCell
->contents
= (UINT
)cell
;
86 cell
= copyCell(evaluateExpression(expr
));
88 cleanupResults(resultIdxSave
);
90 results
->contents
= (UINT
)cell
;
100 CELL
* explodeList(CELL
* list
, CELL
* params
)
106 CELL
* result
= NULL
;
107 CELL
* * lastChunk
= NULL
;
110 if(params
!= nilCell
)
112 params
= getInteger(params
, (UINT
*)&len
);
113 flag
= getFlag(params
);
116 result
= getCell(CELL_EXPRESSION
);
118 if(len
<= 0) return(result
);
120 while(list
!= nilCell
)
122 if(result
->contents
== (UINT
)nilCell
)
124 cell
= getCell(CELL_EXPRESSION
);
125 lastChunk
= (CELL
* *)&result
->contents
;
126 result
->contents
= (UINT
)cell
;
127 cell
->contents
= (UINT
)copyCell(list
);
128 last
= (CELL
*)cell
->contents
;
134 last
->next
= copyCell(list
);
140 cell
->next
= getCell(CELL_EXPRESSION
);
141 lastChunk
= (CELL
* *)&cell
->next
;
143 cell
->contents
= (UINT
)copyCell(list
);
144 last
= (CELL
*)cell
->contents
;
152 if(flag
&& count
< len
)
156 deleteList(*lastChunk
);
157 *lastChunk
= nilCell
;
165 /* ---------------------- set primitives --------------------------------- */
167 CELL
* setInterDiff(CELL
* params
, int mode
);
174 CELL
* p_intersect(CELL
* params
)
176 if(params
->next
== nilCell
)
177 return(setInterDiff(params
, SET_UNIQUE
));
179 return(setInterDiff(params
, SET_INTER
));
182 CELL
* p_difference(CELL
* params
)
184 return(setInterDiff(params
, SET_DIFF
));
188 CELL
* p_unique(CELL
* params
)
190 return(setInterDiff(params
, SET_UNIQUE
));
194 /* new very fast version in 8.6.2 */
196 CELL
* setInterDiff(CELL
* params
, int mode
)
201 CELL
* * vectorB
= NULL
;
202 CELL
* * vectorResult
;
203 ssize_t lengthA
, lengthB
;
204 ssize_t i
= 0, j
= 0, k
= 0, top
= 0;
207 int listMode
= FALSE
;
208 int cmp
, flag
= FALSE
;
210 params
= getListHead(params
, &listA
);
212 return(getCell(CELL_EXPRESSION
));
214 if(mode
!= SET_UNIQUE
)
216 params
= getListHead(params
, &listB
);
217 listMode
= getFlag(params
);
222 listA
= copyList(listB
);
227 if(mode
== SET_INTER
)
228 return(getCell(CELL_EXPRESSION
));
233 vectorA
= listToSortedVector(listA
, &lengthA
, NULL
, TRUE
);
235 vectorResult
= callocMemory(lengthA
* sizeof(CELL
*));
238 vectorB
= listToSortedVector(listB
, &lengthB
, NULL
, 0);
240 result
= getCell(CELL_EXPRESSION
);
244 if(listB
) switch(mode
)
247 cmp
= compareCells(vectorA
[i
], vectorB
[j
]);
254 if(j
< (lengthB
- 1)) ++j
;
259 cmp
= compareCells(vectorA
[i
], vectorB
[j
]);
266 if(j
< (lengthB
- 1)) ++j
;
276 /* if not in result or if list mode is specified */
277 if( (k
== 0) || (compareCells(vectorA
[i
], vectorResult
[top
]) != 0) || (listMode
== TRUE
) )
280 vectorResult
[k
++] = vectorA
[i
];
289 binsort(vectorResult
, k
, (CELL
*)0xFFFFFFFF);
290 cell
= copyCell(vectorResult
[0]);
291 result
->contents
= (UINT
)cell
;
294 for(i
= 1; i
< k
; i
++)
296 cell
->next
= copyCell(vectorResult
[i
]);
299 cell
->next
= nilCell
;
304 cell
= resortVectorToList(vectorA
, lengthA
);
306 if(vectorB
) free(vectorB
);
308 if(flag
) deleteList(listA
);
313 /* ----------------------------------------------------------------------- */
315 CELL
* p_match(CELL
* params
)
321 cell
= evaluateExpression(params
);
322 if(!isList(cell
->type
)) return(nilCell
);
323 params
= params
->next
;
324 next
= evaluateExpression(params
);
325 if(!isList(next
->type
)) return(nilCell
);
327 result
= patternMatchL((CELL
*)cell
->contents
, (CELL
*)next
->contents
, getFlag(params
->next
));
328 if(result
) return(result
);
329 return(getCell(CELL_EXPRESSION
));
333 CELL
* linkMatches(CELL
* * matchList
, CELL
* matchPtr
, CELL
* elmnt
)
335 if(*matchList
== NULL
)
337 *matchList
= getCell(CELL_EXPRESSION
);
338 (*matchList
)->contents
= (UINT
)elmnt
;
339 matchPtr
= (CELL
*)(*matchList
)->contents
;
343 matchPtr
->next
= elmnt
;
346 while(matchPtr
->next
!= nilCell
)
347 matchPtr
= matchPtr
->next
;
353 CELL
* patternMatchL(CELL
* pattern
, CELL
* list
, int flag
)
356 CELL
* matchList
= NULL
;
357 CELL
* matches
= NULL
;
358 CELL
* starList
= NULL
;
362 switch(pattern
->type
)
365 /* end of pattern and list */
366 if(list
->type
== CELL_NIL
)
368 if(starList
) deleteList(starList
);
372 goto NO_MATCH_RETURN
;
375 case CELL_EXPRESSION
:
378 /* compare subexpressions */
379 if(list
->type
== pattern
->type
)
381 if((match
= patternMatchL((CELL
*)pattern
->contents
, (CELL
*)list
->contents
, flag
)) != nilCell
)
386 matches
= linkMatches(&matchList
, matches
, match
);
389 matches
= linkMatches(&matchList
, matches
, (CELL
*)match
->contents
);
390 match
->contents
= (UINT
)nilCell
;
394 pattern
= pattern
->next
;
400 goto NO_MATCH_RETURN
;
403 if(pattern
->contents
== (UINT
)questionSymbol
) /* '?' */
405 if(list
== nilCell
) goto NO_MATCH_RETURN
;
406 if(!flag
) matches
= linkMatches(&matchList
, matches
, copyCell(list
));
410 if(pattern
->contents
== (UINT
)starSymbol
||
411 pattern
->contents
== (UINT
)plusSymbol
) /* '*' and '+' */
415 starList
= getCell(CELL_EXPRESSION
);
418 if(stars
== NULL
&& pattern
->contents
== (UINT
)plusSymbol
)
421 if(pattern
->next
== nilCell
)
424 starList
->contents
= (UINT
)copyList(list
);
426 stars
->next
= copyList(list
);
428 linkMatches(&matchList
, matches
, starList
);
432 if((match
= patternMatchL(pattern
->next
, list
, flag
)) != nilCell
)
434 matches
= linkMatches(&matchList
, matches
, starList
);
437 matches
->next
= (CELL
*)match
->contents
;
438 match
->contents
= (UINT
)nilCell
;
444 if(list
->next
== nilCell
)
445 goto NO_MATCH_RETURN
;
448 if(pattern
->contents
== (UINT
)plusSymbol
)
449 if(list
== nilCell
) goto NO_MATCH_RETURN
;
453 starList
->contents
= (UINT
)copyCell(list
);
454 stars
= (CELL
*)starList
->contents
;
458 stars
->next
= copyCell(list
);
466 if(compareCells(pattern
, list
) != 0)
467 goto NO_MATCH_RETURN
;
472 if(flag
) matches
= linkMatches(&matchList
, matches
, copyCell(list
));
475 pattern
= pattern
->next
;
480 if(starList
!= NULL
) deleteList(starList
);
481 if(matchList
!= NULL
) deleteList(matchList
);
486 CELL
* p_assoc(CELL
* params
)
492 if(params
->type
== CELL_EXPRESSION
&& params
->next
== nilCell
)
494 key
= getList(params
, &list
, FALSE
);
495 list
= (CELL
*)list
->contents
;
497 while(key
!= nilCell
)
499 eKey
= evaluateExpression(key
);
500 while(list
!= nilCell
)
502 if(isList(list
->type
))
503 if(compareCells(eKey
, (CELL
*)list
->contents
) == 0) break;
507 if((key
= key
->next
) == nilCell
) break;
508 list
= ((CELL
*)list
->contents
)->next
;
513 key
= evaluateExpression(params
);
514 getListHead(params
->next
, &list
);
515 while(list
!= nilCell
)
517 if(isList(list
->type
))
518 if(compareCells(key
, (CELL
*)list
->contents
) == 0) break;
523 if(list
== nilCell
) return(nilCell
);
524 return(copyCell(list
));
528 CELL
* p_lookup(CELL
* params
)
534 key
= evaluateExpression(params
);
535 params
= getListHead(params
->next
, &list
);
537 while(list
!= nilCell
)
539 if(isList(list
->type
))
540 if(compareCells(key
, (CELL
*)list
->contents
) == 0) break;
544 if(list
== nilCell
) return(nilCell
);
546 list
= (CELL
*)list
->contents
;
548 if(params
!= nilCell
)
549 getInteger(params
, (UINT
*)&index
);
552 if(index
< 0) index
= convertNegativeOffset(index
, list
);
556 if(list
->next
== nilCell
) break;
560 return(copyCell(list
));
563 /* bind and association list, works like:
564 (define (bind L) (dolist (i L) (apply set i)))
565 L => ((x 1) (y 2) (z 3))
568 CELL
* p_bind(CELL
* params
)
570 SYMBOL
* lref
= NULL
;
575 params
= getListHead(params
, &list
);
576 evalFlag
= getFlag(params
);
578 while(list
!= nilCell
)
580 if(list
->type
!= CELL_EXPRESSION
)
581 return(errorProcExt(ERR_LIST_EXPECTED
, list
));
583 cell
= (CELL
*)list
->contents
;
584 lref
= getSymbolCheckProtected(cell
);
585 deleteList((CELL
*)lref
->contents
);
587 lref
->contents
= (UINT
)copyCell(evaluateExpression(cell
->next
));
589 lref
->contents
= (UINT
)copyCell(cell
->next
);
596 return(copyCell((CELL
*)lref
->contents
));
600 CELL
* p_count(CELL
* params
)
605 CELL
* * vectorItems
;
607 ssize_t lengthItems
, lengthList
;
608 ssize_t i
= 0, j
= 0, idx
;
614 params
= getListHead(params
, &items
);
615 getListHead(params
, &list
);
617 result
= getCell(CELL_EXPRESSION
);
625 items
= copyList(list
);
628 vectorItems
= listToSortedVector(items
, &lengthItems
, NULL
, TRUE
);
629 vectorList
= listToSortedVector(list
, &lengthList
, NULL
, TRUE
);
631 counts
= (ssize_t
*)callocMemory(lengthItems
* sizeof(ssize_t
));
634 while(i
< lengthList
)
636 cmp
= compareCells(vectorList
[i
], vectorItems
[j
]);
639 idx
= (ssize_t
)vectorItems
[j
]->next
;
649 if(j
< (lengthItems
- 1)) j
++;
654 cell
= stuffInteger(counts
[0]);
655 result
->contents
= (UINT
)cell
;
656 for(i
= 1; i
< lengthItems
; i
++)
658 cell
->next
= stuffInteger(counts
[i
]);
663 cell
= resortVectorToList(vectorItems
, lengthItems
);
664 if(vectorList
) cell
= resortVectorToList(vectorList
, lengthList
);
666 if(flag
) deleteList(items
);
671 #else /* Mac OS X and other UNIX */
681 CELL
* p_count(CELL
* params
)
695 params
= getListHead(params
, &items
);
696 getListHead(params
, &list
);
698 result
= getCell(CELL_EXPRESSION
);
706 items
= copyList(list
);
709 lengthItems
= listlen(items
);
710 counts
= (CELL
* *)callocMemory(lengthItems
* sizeof(CELL
*));
713 for(i
= 0; i
< lengthItems
; i
++)
715 counts
[i
] = copyCell(cell
);
716 counts
[i
]->next
= NULL
;
717 key
= tsearch(counts
[i
], &root
, (int (*)(const void *, const void *))compareCells
);
719 errorProc(ERR_NOT_ENOUGH_MEMORY
);
724 while(cell
!= nilCell
)
726 key
= tfind(cell
, &root
, (int (*)(const void *, const void *))compareCells
);
729 count
= (COUNTCELL
*)*(CELL
* *)key
;
735 cell
= stuffInteger((UINT
)counts
[0]->next
);
736 result
->contents
= (UINT
)cell
;
737 for(i
= 1; i
< lengthItems
; i
++)
739 cell
->next
= stuffInteger((UINT
)counts
[i
]->next
);
743 for(i
= 0; i
< lengthItems
; i
++)
745 counts
[i
]->next
= nilCell
;
746 deleteList(counts
[i
]);
750 if(flag
) deleteList(items
);
758 CELL
* p_replaceAssoc(CELL
* params
)
764 CELL
* previous
= NULL
;
766 key
= evaluateExpression(params
);
767 params
= params
->next
;
769 cell
= evalCheckProtected(params
, NULL
);
771 if(!isList(cell
->type
))
772 return(errorProcExt(ERR_LIST_EXPECTED
, cell
));
774 cell
->aux
= (UINT
)nilCell
; /* undo last element optimization */
776 if(isList(cell
->type
))
778 list
= (CELL
*)cell
->contents
;
780 while(list
!= nilCell
)
782 if(isList(list
->type
))
783 if(compareCells(key
, (CELL
*)list
->contents
) == 0)
785 deleteList((CELL
*)sysSymbol
[0]->contents
);
786 sysSymbol
[0]->contents
= (UINT
)copyCell(list
);
787 /* deleteList((CELL *)list->contents); */
788 if(params
->next
!= nilCell
)
790 getListHead(params
->next
, &repList
);
791 deleteList((CELL
*)list
->contents
);
792 list
->contents
= (UINT
)copyList(repList
);
794 else /* if no replacement given, remove association found */
796 deleteList((CELL
*)list
->contents
);
797 list
->contents
= (UINT
)nilCell
;
799 cell
->contents
= (UINT
)list
->next
;
801 previous
->next
= list
->next
;
802 list
->next
= nilCell
;
805 return(copyCell(cell
));
820 CELL
* setAssoc(CELL
* params
, int mode
)
826 CELL
* original
= NULL
;
827 CELL
* previous
= NULL
;
829 if(params
->type
!= CELL_EXPRESSION
)
830 return(errorProcExt(ERR_SYNTAX_WRONG
, params
));
832 key
= getList(params
, &list
, TRUE
);
833 list
->aux
= (UINT
)nilCell
; /* undo last element optimization */
835 list
= (CELL
*)list
->contents
;
837 while(key
!= nilCell
)
839 eKey
= evaluateExpression(key
);
840 while(list
!= nilCell
)
842 if(isList(list
->type
))
843 if(compareCells(eKey
, (CELL
*)list
->contents
) == 0) break;
848 if((key
= key
->next
) == nilCell
) break;
849 previous
= (CELL
*)list
->contents
;
850 list
= ((CELL
*)list
->contents
)->next
;
853 if(list
== nilCell
) return(nilCell
); /* key not found */
855 if(mode
== POP_ASSOC
)
858 original
->contents
= (UINT
)list
->next
;
860 previous
->next
= list
->next
;
861 list
->next
= nilCell
;
865 deleteList((CELL
*)sysSymbol
[0]->contents
);
866 sysSymbol
[0]->contents
= (UINT
)copyCell(list
);
868 if(params
->next
!= nilCell
)
870 getListHead(params
->next
, &repList
);
871 deleteList((CELL
*)list
->contents
);
872 list
->contents
= (UINT
)copyList(repList
);
875 if(mode
== SET_ASSOC
)
876 return(copyCell(original
));
878 return(copyCell((CELL
*)sysSymbol
[0]->contents
));
882 CELL
* p_setAssoc(CELL
* params
)
884 return(setAssoc(params
, SET_ASSOC
));
888 CELL
* p_assocSet(CELL
* params
)
890 return(setAssoc(params
, ASSOC_SET
));
893 CELL
* p_popAssoc(CELL
* params
)
895 return(setAssoc(params
, POP_ASSOC
));
899 void binsort(CELL
* * x
, ssize_t n
, CELL
* pCell
)
901 ssize_t i
,j
,k
,l
,m
,kf
,lf
;
905 jmp_buf errorJumpSave
;
909 y
= allocMemory(n
* sizeof(CELL
*));
914 for(i
= 0; i
< n
; i
+= 2*m
)
928 if(lf
>= n
) lf
= n
- 1;
930 for(j
= i
; j
<= lf
; j
++)
945 if(compareCells((CELL
*)x
[k
], (CELL
*)x
[l
]) <= 0)
951 if(pCell
== (CELL
*)0xFFFFFFFF)
953 if(((CELL
*)x
[k
])->next
<= ((CELL
*)x
[l
])->next
)
960 resultIndexSave
= resultStackIdx
;
961 expr
= getCell(CELL_EXPRESSION
);
962 expr
->contents
= (UINT
)copyCell(pCell
);
963 cell
= (CELL
*)expr
->contents
;
964 cell
->next
= getCell(CELL_QUOTE
);
965 ((CELL
*)cell
->next
)->contents
= (UINT
)copyCell((CELL
*)x
[k
]);
967 cell
->next
= getCell(CELL_QUOTE
);
968 ((CELL
*)cell
->next
)->contents
= (UINT
)copyCell((CELL
*)x
[l
]);
970 /* do result stack cleanup, and free memory under
972 memcpy(errorJumpSave
, errorJump
, sizeof(jmp_buf));
973 if((errNo
= setjmp(errorJump
)) != 0)
975 memcpy(errorJump
, errorJumpSave
, (sizeof(jmp_buf)));
977 cleanupResults(resultIndexSave
);
978 free(x
); /* allocates by parent routine */
980 longjmp(errorJump
, errNo
);
983 cell
= evaluateExpression(expr
);
985 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
986 if(!isNil(cell
) && !isEmpty(cell
))
992 cleanupResults(resultIndexSave
);
996 for(i
= 0; i
< n
; i
++) x
[i
] = y
[i
];
1003 CELL
* * listToSortedVector(CELL
* list
, ssize_t
* length
, CELL
* func
, int indexFlag
);
1005 CELL
* p_sort(CELL
* params
)
1013 params
= evalCheckProtected(params
, NULL
);
1015 if(isList(params
->type
))
1017 if(params
->contents
== (UINT
)nilCell
)
1018 return(getCell(CELL_EXPRESSION
));
1020 params
->aux
= (UINT
)nilCell
; /* undo last element optimization */
1022 vector
= listToSortedVector((CELL
*)params
->contents
, &length
, list
->next
, 0);
1030 list
->next
= vector
[i
];
1034 list
->next
= nilCell
;
1036 params
->contents
= (UINT
)vector
[0];
1039 else if(isArray(params
->type
))
1041 vector
= (CELL
**)params
->contents
;
1042 length
= (params
->aux
- 1) / sizeof(UINT
);
1043 if(list
->next
== nilCell
)
1044 binsort(vector
, length
, NULL
);
1046 binsort(vector
, length
, list
->next
);
1049 return(errorProcExt(ERR_LIST_OR_ARRAY_EXPECTED
, list
));
1051 return(copyCell(params
));
1055 CELL
* * listToSortedVector(CELL
* list
, ssize_t
* length
, CELL
* func
, int indexFlag
)
1061 if((*length
= listlen(list
)) == 0) return(NULL
);
1064 vector
= allocMemory(*length
* sizeof(CELL
*));
1065 for(i
= 0; i
< *length
; i
++)
1067 vector
[i
] = prev
= list
;
1069 if(indexFlag
) prev
->next
= (void *)i
;
1072 if(func
!= nilCell
&& func
!= NULL
)
1074 func
= evaluateExpression(func
);
1075 if(func
->type
== CELL_SYMBOL
)
1076 func
= (CELL
*)((SYMBOL
*)func
->contents
)->contents
;
1077 binsort(vector
, *length
, func
);
1080 binsort(vector
, *length
, NULL
);
1086 CELL
* resortVectorToList(CELL
* * vector
, ssize_t length
)
1091 binsort(vector
, length
, (CELL
*)0xFFFFFFFF);
1093 for(i
= 1; i
< length
; i
++)
1095 list
->next
= vector
[i
];
1098 list
->next
= nilCell
;
1105 /* called with params containing the indices
1106 or list of indices */
1108 CELL
* implicitIndexList (CELL
* list
, CELL
* params
)
1114 cell
= evaluateExpression(params
);
1115 if(isNumber(cell
->type
))
1117 getIntegerExt(cell
, (UINT
*)&index
, FALSE
);
1118 params
= params
->next
;
1121 else if(isList(cell
->type
))
1123 params
= (CELL
*)cell
->contents
;
1124 params
= getIntegerExt(params
, (UINT
*)&index
, FALSE
);
1127 else return(errorProcExt(ERR_LIST_OR_NUMBER_EXPECTED
, params
));
1129 while(isList(list
->type
))
1131 /* last element optimization */
1132 if(index
== -1 && list
->aux
!= (UINT
)nilCell
)
1133 list
= (CELL
*)list
->aux
;
1136 list
= (CELL
*)list
->contents
;
1138 index
= convertNegativeOffset(index
, list
);
1140 while(index
--) list
= list
->next
;
1143 errorProc(ERR_LIST_INDEX_OUTOF_BOUNDS
);
1146 if(params
== nilCell
|| !isList(list
->type
)) break;
1147 params
= getIntegerExt(params
, (UINT
*)&index
, evalFlag
);
1154 CELL
* p_sequence(CELL
* params
)
1156 double fromFlt
, toFlt
, interval
, step
, cntFlt
;
1157 INT64 fromInt64
, toInt64
, stepCnt
, i
;
1162 if((intFlag
= (((CELL
*)params
->next
)->next
== nilCell
)))
1164 params
= getInteger64(params
, &fromInt64
);
1165 getInteger64(params
, &toInt64
);
1166 stepCnt
= (fromInt64
> toInt64
) ? fromInt64
- toInt64
: toInt64
- fromInt64
;
1167 cell
= stuffInteger64(fromInt64
);
1171 params
= getFloat(params
, &fromFlt
);
1172 params
= getFloat(params
, &toFlt
);
1173 getFloat(params
, &step
);
1175 if(isnan(fromFlt
) || isnan(toFlt
) || isnan(step
))
1176 return(errorProc(ERR_INVALID_PARAMETER_NAN
));
1178 step
= (step
< 0) ? -step
: step
;
1179 step
= (fromFlt
> toFlt
) ? -step
: step
;
1180 cntFlt
= (fromFlt
< toFlt
) ? (toFlt
- fromFlt
)/step
: (fromFlt
- toFlt
)/step
;
1181 stepCnt
= (cntFlt
> 0.0) ? floor(cntFlt
+ 0.0000000001) : floor(-cntFlt
+ 0.0000000001);
1182 cell
= stuffFloat(&fromFlt
);
1185 sequence
= getCell(CELL_EXPRESSION
);
1186 sequence
->contents
= (UINT
)cell
;
1188 for(i
= 1; i
<= stepCnt
; i
++)
1192 if(fromInt64
> toInt64
)
1193 cell
->next
= stuffInteger(fromInt64
- i
);
1195 cell
->next
= stuffInteger(fromInt64
+ i
);
1199 interval
= fromFlt
+ i
* step
;
1200 cell
->next
= stuffFloat(&interval
);
1209 #define FILTER_FILTER 0
1210 #define FILTER_INDEX 1
1211 #define FILTER_CLEAN 2
1212 #define FILTER_FOR_ALL 3
1213 #define FILTER_EXISTS 4
1215 CELL
* filterIndex(CELL
* params
, int mode
);
1217 CELL
* p_filter(CELL
* params
)
1219 return filterIndex(params
, FILTER_FILTER
);
1222 CELL
* p_index(CELL
* params
)
1224 return filterIndex(params
, FILTER_INDEX
);
1227 CELL
* p_clean(CELL
* params
)
1229 return filterIndex(params
, FILTER_CLEAN
);
1232 CELL
* p_exists(CELL
* params
)
1234 return filterIndex(params
, FILTER_EXISTS
);
1237 CELL
* p_forAll(CELL
* params
)
1239 return filterIndex(params
, FILTER_FOR_ALL
);
1242 CELL
* filterIndex(CELL
* params
, int mode
)
1247 CELL
* resultList
= NULL
;
1251 int resultIndexSave
;
1252 int errNo
, trueFlag
;
1254 args
= evaluateExpression(params
->next
);
1255 pCell
= evaluateExpression(params
);
1257 if(!isList(args
->type
))
1258 return(errorProcExt(ERR_LIST_EXPECTED
, params
->next
));
1259 args
= (CELL
*)args
->contents
;
1263 resultIndexSave
= resultStackIdx
;
1264 while(args
!= nilCell
)
1266 expr
= getCell(CELL_EXPRESSION
);
1267 expr
->contents
= (UINT
)copyCell(pCell
);
1268 cell
= (CELL
*)expr
->contents
;
1269 cell
->next
= getCell(CELL_QUOTE
);
1271 cell
->contents
= (UINT
)copyCell(args
);
1274 if(!(cell
= evaluateExpressionSafe(expr
, &errNo
)))
1276 if(resultList
) deleteList(resultList
);
1277 longjmp(errorJump
, errNo
);
1280 trueFlag
= !isNil(cell
);
1282 cleanupResults(resultIndexSave
);
1284 if(mode
== FILTER_EXISTS
&& trueFlag
)
1285 return(copyCell(args
));
1287 else if (mode
== FILTER_FOR_ALL
)
1289 if(trueFlag
) goto CONTINUE_FOR_ALL
;
1290 else return(nilCell
);
1293 if((trueFlag
&& mode
!= FILTER_CLEAN
) || (!trueFlag
&& mode
== FILTER_CLEAN
))
1297 resultList
= getCell(CELL_EXPRESSION
);
1298 resultList
->contents
= (mode
== FILTER_INDEX
) ?
1299 (UINT
)stuffInteger((UINT
)count
): (UINT
)copyCell(args
) ;
1300 result
= (CELL
*)resultList
->contents
;
1304 result
->next
= (mode
== FILTER_INDEX
) ?
1305 stuffInteger(count
): copyCell(args
);
1306 result
= result
->next
;
1315 if(mode
== FILTER_EXISTS
)
1318 if(mode
== FILTER_FOR_ALL
)
1321 if(resultList
== NULL
)
1322 return(getCell(CELL_EXPRESSION
));
1328 #define MAX_REF_STACK 256
1334 #define pushRef(A) (refStack->base[refStack->idx++] = (UINT)(A))
1335 #define popRef() (--refStack->idx)
1337 CELL
* makeIndexVector(REFSTACK
* refStack
)
1343 vector
= getCell(CELL_EXPRESSION
);
1344 next
= stuffInteger(refStack
->base
[0]);
1345 vector
->contents
= (UINT
)next
;
1347 for(i
= 1; i
< refStack
->idx
; i
++)
1349 next
->next
= stuffInteger(refStack
->base
[i
]);
1356 #define REF_SINGLE 0
1359 void ref(CELL
* keyCell
, CELL
* list
, CELL
* funcCell
, CELL
* result
,
1360 CELL
* * next
, REFSTACK
* refStack
, int mode
)
1363 int resultIdxSave
= resultStackIdx
;
1365 while(list
!= nilCell
)
1367 if(compareFunc(keyCell
, list
, funcCell
) == 0)
1371 deleteList((CELL
*)sysSymbol
[0]->contents
);
1372 sysSymbol
[0]->contents
= (UINT
)copyCell(list
);
1374 if(refStack
->idx
< MAX_REF_STACK
) pushRef(idx
);
1375 else errorProc(ERR_NESTING_TOO_DEEP
);
1378 *next
= makeIndexVector(refStack
);
1379 result
->contents
= (UINT
)*next
;
1383 (*next
)->next
= makeIndexVector(refStack
);
1384 *next
= (*next
)->next
;
1387 if(mode
== REF_SINGLE
) return;
1389 if(isList(list
->type
))
1391 if(refStack
->idx
< MAX_REF_STACK
) pushRef(idx
);
1392 else errorProc(ERR_NESTING_TOO_DEEP
);
1393 ref(keyCell
, (CELL
*)list
->contents
, funcCell
, result
, next
, refStack
, mode
);
1398 cleanupResults(resultIdxSave
);
1404 CELL
* reference(CELL
* params
, int mode
)
1409 CELL
* funcCell
= NULL
;
1413 refStack
.base
= alloca((MAX_REF_STACK
+ 2) * sizeof(size_t));
1416 if(params
->type
== CELL_EXPRESSION
)
1418 cell
= getList(params
, &list
, FALSE
);
1419 keyCell
= evaluateExpression(cell
);
1423 keyCell
= evaluateExpression(params
);
1424 params
= params
->next
;
1425 list
= evaluateExpression(params
);
1428 if(params
->next
!= nilCell
)
1429 funcCell
= evaluateExpression(params
->next
);
1431 if(!isList(list
->type
))
1432 return(errorProcExt(ERR_LIST_EXPECTED
, list
));
1434 cell
= getCell(CELL_EXPRESSION
);
1436 ref(keyCell
, (CELL
*)list
->contents
, funcCell
, cell
, &next
, &refStack
, mode
);
1438 if(mode
== REF_SINGLE
)
1440 next
= (CELL
*)cell
->contents
;
1441 if(next
== nilCell
) return(cell
);
1442 cell
->contents
= (UINT
)nilCell
;
1450 CELL
* p_ref(CELL
* params
)
1452 return(reference(params
, REF_SINGLE
));
1455 CELL
* p_refAll(CELL
* params
)
1457 return(reference(params
, REF_ALL
));
1461 #define SETREF_ELMNT 0
1462 #define SETREF_LIST 1
1463 #define SETREF_ALL 2
1465 CELL
* modRef(CELL
* key
, CELL
* list
, CELL
* func
, CELL
* new, int mode
, int * count
)
1468 int resultIdxSave
= resultStackIdx
;
1470 while(list
!= nilCell
)
1472 if(compareFunc(key
, list
, func
) == 0)
1475 if(mode
== SETREF_ELMNT
)
1477 return(updateCell(list
, new));
1481 deleteList(updateCell(list
, new));
1482 if(mode
== SETREF_LIST
) return(list
);
1488 else if(isList(list
->type
))
1490 result
= modRef(key
, (CELL
*)list
->contents
, func
, new, mode
, count
);
1491 if(result
!= nilCell
) return(result
);
1494 cleanupResults(resultIdxSave
);
1502 CELL
* setRef(CELL
* params
, int mode
)
1507 CELL
* funcCell
= NULL
;
1512 if(params
->type
!= CELL_EXPRESSION
)
1513 return(errorProcExt(ERR_SYNTAX_WRONG
, params
));
1515 params
= getList(params
, &list
, TRUE
);
1516 key
= evaluateExpression(params
);
1518 if(new->next
!= nilCell
)
1519 funcCell
= evaluateExpression(new->next
);
1521 result
= modRef(key
, (CELL
*)list
->contents
, funcCell
, new, mode
, &count
);
1526 if(mode
== SETREF_ELMNT
)
1529 return(copyCell(list
));
1534 CELL
* p_setRef(CELL
* params
)
1536 return(setRef(params
, SETREF_LIST
));
1539 CELL
* p_setRefAll(CELL
* params
)
1541 return(setRef(params
, SETREF_ALL
));
1544 CELL
* p_refSet(CELL
* params
)
1546 return(setRef(params
, SETREF_ELMNT
));
1550 /* update a cell in-place and put a copy of previous content
1551 in $0 to be used in replacement expressions.
1552 this function is used in set-nth/nth-set
1554 CELL
* updateCell(CELL
* cell
, CELL
* val
)
1559 if(cell
== nilCell
) return(nilCell
);
1561 deleteList((CELL
*)sysSymbol
[0]->contents
);
1562 sysSymbol
[0]->contents
= (UINT
)copyCell(cell
);
1566 new = copyCell(evaluateExpression(val
));
1568 /* save previous content */
1569 prev
= getCell(cell
->type
);
1570 prev
->aux
= cell
->aux
;
1571 prev
->contents
= cell
->contents
;
1573 cell
->type
= new->type
;
1574 cell
->aux
= new->aux
;
1575 cell
->contents
= new->contents
;
1578 new->type
= CELL_FREE
;
1581 new->next
= firstFreeCell
;
1582 firstFreeCell
= new;
1586 return(copyCell(cell
));
1591 void flat(CELL
* list
, CELL
* result
, CELL
* * next
)
1593 while(list
!= nilCell
)
1595 if(isList(list
->type
))
1596 flat((CELL
*)list
->contents
, result
, next
);
1601 *next
= copyCell(list
);
1602 result
->contents
= (UINT
)*next
;
1606 (*next
)->next
= copyCell(list
);
1607 *next
= (*next
)->next
;
1616 CELL
* p_flat(CELL
* params
)
1622 getListHead(params
, &list
);
1624 result
= getCell(CELL_EXPRESSION
);
1628 flat(list
, result
, &next
);
1636 /* --------------------------------- array routines ------------------------- */
1639 CELL
* initArray(CELL
* array
, CELL
* list
, CELL
* * next
);
1641 CELL
* p_array(CELL
* params
)
1645 CELL
* array
= NULL
;
1646 CELL
* list
= nilCell
;
1649 while(params
!= nilCell
&& p
< 17)
1651 list
= evaluateExpression(params
);
1652 if(isNumber(list
->type
))
1654 getIntegerExt(list
, (UINT
*)&index
[p
], FALSE
);
1656 return(errorProcExt(ERR_WRONG_DIMENSIONS
, list
));
1659 else if(isList(list
->type
)) break;
1660 else return(errorProcExt(ERR_NUMBER_EXPECTED
, list
));
1661 params
= params
->next
;
1665 return(errorProc(ERR_MISSING_ARGUMENT
));
1668 if(!isList(list
->type
)) list
= nilCell
;
1670 array
= makeArray(index
, 0);
1673 array
= initArray(array
, list
, &next
);
1679 CELL
* makeArray(ssize_t
* index
, int p
)
1686 array
= getCell(CELL_ARRAY
);
1688 array
->contents
= (UINT
)callocMemory(size
* sizeof(UINT
) + 1);
1689 array
->aux
= size
* sizeof(UINT
) + 1;
1690 addr
= (CELL
* *)array
->contents
;
1695 list
= makeArray(index
, p
);
1696 while(size
--) *(addr
++) = copyCell(list
);
1701 while(size
--) *(addr
++) = nilCell
;
1707 CELL
* initArray(CELL
* array
, CELL
* list
, CELL
* * next
)
1712 size
= (array
->aux
- 1) / sizeof(UINT
);
1713 addr
= (CELL
* *)array
->contents
;
1717 if((*addr
)->type
== CELL_ARRAY
)
1719 *(addr
) = initArray(*addr
, list
, next
);
1724 if(*next
== NULL
|| *next
== nilCell
)
1727 *(addr
++) = copyCell((CELL
*)list
->contents
);
1728 *next
= (CELL
*)list
->contents
;
1729 *next
= (*next
)->next
;
1734 *(addr
++) = copyCell(*next
);
1735 *next
= (*next
)->next
;
1745 CELL
* p_arrayList(CELL
* params
)
1749 array
= evaluateExpression(params
);
1751 if(array
->type
!= CELL_ARRAY
)
1752 return(errorProcExt(ERR_ARRAY_EXPECTED
, params
));
1754 return(arrayList(array
));
1759 CELL
* arrayList(CELL
* array
)
1767 addr
= (CELL
* *)array
->contents
;
1768 size
= (array
->aux
- 1) / sizeof(UINT
);
1773 if(cell
->type
== CELL_ARRAY
)
1774 new = arrayList(cell
);
1776 new = copyCell(cell
);
1779 array
= list
= getCell(CELL_EXPRESSION
);
1780 list
->contents
= (UINT
)new;
1793 CELL
* arrayTranspose(CELL
* array
)
1803 addr
= (CELL
* *)array
->contents
;
1804 n
= (array
->aux
- 1) / sizeof(CELL
*);
1807 if(cell
->type
!= CELL_ARRAY
)
1808 return(errorProcExt(ERR_WRONG_DIMENSIONS
, array
));
1809 m
= (cell
->aux
- 1) / sizeof(CELL
*);
1811 newArray
= getCell(CELL_ARRAY
);
1812 newArray
->aux
= m
* sizeof(CELL
*) + 1;
1813 newAddr
= (CELL
* *)callocMemory(newArray
->aux
);
1814 newArray
->contents
= (UINT
)newAddr
;
1816 for(j
= 0; j
< m
; j
++)
1818 /* create new row vector */
1819 cell
= getCell(CELL_ARRAY
);
1820 cell
->aux
= n
* sizeof(CELL
*) + 1;
1821 newRow
= (CELL
* *)callocMemory(cell
->aux
);
1822 cell
->contents
= (UINT
)newRow
;
1823 *(newAddr
+ j
) = cell
;
1824 for( i
= 0; i
< n
; i
++)
1827 if(cell
->type
!= CELL_ARRAY
)
1828 *(newRow
+ i
) = copyCell(cell
);
1831 row
= (CELL
* *)cell
->contents
;
1832 if( (cell
->aux
- 1) / sizeof(CELL
*) < (j
+ 1))
1833 *(newRow
+ i
) = nilCell
;
1835 *(newRow
+ i
) = copyCell(*(row
+ j
));
1844 CELL
* subarray(CELL
* array
, ssize_t offset
, ssize_t length
)
1851 size
= (array
->aux
- 1) / sizeof(CELL
*);
1852 if(offset
< 0) offset
= offset
+ size
;
1853 if(offset
>= size
|| offset
< 0)
1854 return(errorProcExt2(ERR_ARRAY_INDEX_OUTOF_BOUNDS
, stuffInteger(offset
)));
1858 length
= size
- offset
+ length
;
1859 if(length
< 0) length
= 0;
1862 if(length
== MAX_LONG
&& length
> (size
- offset
))
1863 length
= size
- offset
;
1865 if(length
== 0 || length
> (size
- offset
))
1866 return(errorProcExt2(ERR_ARRAY_INDEX_OUTOF_BOUNDS
, stuffInteger(length
)));
1868 addr
= (CELL
* *)array
->contents
;
1869 newArray
= getCell(CELL_ARRAY
);
1870 newArray
->aux
= length
* sizeof(CELL
*) + 1;
1871 newAddr
= (CELL
* *)callocMemory(newArray
->aux
);
1872 newArray
->contents
= (UINT
)newAddr
;
1874 for(i
= 0; i
< length
; i
++)
1875 *(newAddr
+ i
) = copyCell(*(addr
+ offset
+ i
));
1881 /* copies an array */
1882 UINT
* copyArray(CELL
* array
)
1889 addr
= newAddr
= (CELL
* *)callocMemory(array
->aux
);
1891 size
= (array
->aux
- 1) / sizeof(UINT
);
1892 orgAddr
= (CELL
* *)array
->contents
;
1895 *(newAddr
++) = copyCell(*(orgAddr
++));
1897 return((UINT
*)addr
);
1901 CELL
* appendArray(CELL
* array
, CELL
* params
)
1905 ssize_t size
, sizeCell
;
1910 if(params
== nilCell
)
1911 return(copyCell(array
));
1913 START_APPEND_ARRAYS
:
1914 size
= (array
->aux
- 1) / sizeof(CELL
*);
1915 addr
= (CELL
* *)array
->contents
;
1916 cell
= evaluateExpression(params
);
1917 if(cell
->type
!= CELL_ARRAY
)
1918 return(errorProcExt(ERR_ARRAY_EXPECTED
, params
));
1919 sizeCell
= (cell
->aux
- 1) / sizeof(CELL
*);
1921 newAddr
= allocMemory(array
->aux
+ cell
->aux
-1);
1923 for(i
= 0; i
< size
; i
++)
1924 *(newAddr
+ i
) = copyCell(*(addr
+ i
));
1926 addr
= (CELL
* *)cell
->contents
;
1928 for(i
= 0; i
< sizeCell
; i
++)
1929 *(newAddr
+ size
+ i
) = copyCell(*(addr
+ i
));
1931 cell
= getCell(CELL_ARRAY
);
1932 cell
->aux
= (size
+ sizeCell
) * sizeof(CELL
*) + 1;
1933 cell
->contents
= (UINT
)newAddr
;
1935 if( (params
= params
->next
) != nilCell
)
1941 goto START_APPEND_ARRAYS
;
1951 void deleteArray(CELL
* array
)
1957 mem
= addr
= (CELL
* *)array
->contents
;
1958 size
= (array
->aux
- 1) / sizeof(UINT
);
1960 deleteList(*(addr
++));
1962 freeMemory((char *)mem
);
1966 void markArray(CELL
* array
)
1971 addr
= (CELL
* *)array
->contents
;
1972 size
= (array
->aux
- 1) / sizeof(UINT
);
1974 while(size
--) markList(*(addr
++));
1979 void printArray(CELL
* array
, UINT device
)
1983 list
= arrayList(array
);
1985 printExpression(list
, device
);
1991 void printArrayDimensions(CELL
* array
, UINT device
)
1995 while(array
->type
== CELL_ARRAY
)
1997 varPrintf(device
, "%d ", (array
->aux
- 1)/sizeof(CELL
*));
1998 addr
= (CELL
**)array
->contents
;
2004 CELL
* implicitIndexArray(CELL
* cell
, CELL
* params
)
2008 ssize_t size
, index
;
2011 list
= evaluateExpression(params
);
2012 if(isNumber(list
->type
))
2014 getIntegerExt(list
, (UINT
*)&index
, FALSE
);
2015 params
= params
->next
;
2018 else if(isList(list
->type
))
2020 params
= (CELL
*)list
->contents
;
2021 params
= getIntegerExt(params
, (UINT
*)&index
, FALSE
);
2024 else return(errorProcExt(ERR_LIST_OR_NUMBER_EXPECTED
, params
));
2026 while(cell
->type
== CELL_ARRAY
)
2028 addr
= (CELL
* *)cell
->contents
;
2029 size
= (cell
->aux
- 1) / sizeof(UINT
);
2030 if(index
< 0) index
= index
+ size
;
2031 if(index
>= size
|| index
< 0)
2032 return(errorProcExt2(ERR_ARRAY_INDEX_OUTOF_BOUNDS
, stuffInteger(index
)));
2033 cell
= *(addr
+ index
);
2034 if(params
== nilCell
|| cell
->type
!= CELL_ARRAY
) break;
2035 params
= getIntegerExt(params
, (UINT
*)&index
, evalFlag
);
2042 int compareArrays(CELL
* left
, CELL
* right
)
2046 ssize_t leftS
, rightS
;
2049 leftAddr
= (CELL
* *)left
->contents
;
2050 rightAddr
= (CELL
* *)right
->contents
;
2051 leftS
= (left
->aux
- 1) / sizeof(UINT
);
2052 rightS
= (right
->aux
- 1) / sizeof(UINT
);
2054 if(leftS
< rightS
) return(-1);
2055 if(leftS
> rightS
) return(1);
2058 while(leftS
&& result
== 0)
2060 result
= compareCells(*(leftAddr
++), *(rightAddr
++));
2068 int compareFunc(CELL
* left
, CELL
* right
, CELL
* func
)
2074 return(compareCells(left
, right
));
2076 expr
= getCell(CELL_EXPRESSION
);
2078 expr
->contents
= (UINT
)copyCell(func
);
2079 cell
= (CELL
*)expr
->contents
;
2080 cell
->next
= getCell(CELL_QUOTE
);
2081 ((CELL
*)cell
->next
)->contents
= (UINT
)copyCell((CELL
*)left
);
2083 cell
->next
= getCell(CELL_QUOTE
);
2084 ((CELL
*)cell
->next
)->contents
= (UINT
)copyCell((CELL
*)right
);
2086 cell
= evaluateExpression(expr
);
2088 return(isNil(cell
));