1010from itertools import chain
1111
1212from mathics .builtin .box .layout import RowBox
13- from mathics .core .atoms import Integer , Integer0 , Integer1 , Integer3 , Integer4 , String
13+ from mathics .core .atoms import (
14+ ByteArray ,
15+ Integer ,
16+ Integer0 ,
17+ Integer1 ,
18+ Integer2 ,
19+ Integer3 ,
20+ Integer4 ,
21+ String ,
22+ )
1423from mathics .core .attributes import (
1524 A_HOLD_FIRST ,
1625 A_HOLD_REST ,
4049 SymbolByteArray ,
4150 SymbolDrop ,
4251 SymbolFailed ,
52+ SymbolFirst ,
4353 SymbolInfinity ,
4454 SymbolKey ,
55+ SymbolLast ,
4556 SymbolMakeBoxes ,
4657 SymbolMissing ,
4758 SymbolSelect ,
@@ -675,7 +686,6 @@ class First(Builtin):
675686
676687 attributes = A_HOLD_REST | A_PROTECTED
677688 messages = {
678- "argt" : "First called with `1` arguments; 1 or 2 arguments are expected." ,
679689 "nofirst" : "`1` has zero length and no first element." ,
680690 }
681691 summary_text = "first element of a list or expression"
@@ -685,14 +695,23 @@ def eval(self, expr, evaluation: Evaluation, expression: Expression):
685695 "expression: First[expr__]"
686696
687697 if isinstance (expr , Atom ):
688- evaluation .message ("First" , "normal" , Integer1 , expression )
689- return
690- expr_len = len (expr .elements )
698+ if not hasattr (expr , "items" ):
699+ evaluation .message ("First" , "normal" , Integer1 , expression )
700+ return
701+ expr_len = len (expr .items )
702+ else :
703+ expr_len = len (expr .elements )
691704 if expr_len == 0 :
692705 evaluation .message ("First" , "nofirst" , expr )
693706 return
707+
708+ if isinstance (expr , ByteArray ):
709+ return expr .items [0 ]
710+
694711 if expr_len > 2 and expr .head is SymbolSequence :
695- evaluation .message ("First" , "argt" , expr_len )
712+ evaluation .message (
713+ "First" , "argt" , SymbolFirst , Integer (expr_len ), Integer1 , Integer2
714+ )
696715 return
697716
698717 first_elem = expr .elements [0 ]
@@ -949,7 +968,6 @@ class Last(Builtin):
949968
950969 attributes = A_HOLD_REST | A_PROTECTED
951970 messages = {
952- "argt" : "Last called with `1` arguments; 1 or 2 arguments are expected." ,
953971 "nolast" : "`1` has zero length and no last element." ,
954972 }
955973 summary_text = "last element of a list or expression"
@@ -959,14 +977,24 @@ def eval(self, expression: Expression, expr, evaluation: Evaluation):
959977 "expression: Last[expr__]"
960978
961979 if isinstance (expr , Atom ):
962- evaluation .message ("Last" , "normal" , Integer1 , expression )
963- return
964- expr_len = len (expr .elements )
980+ if not hasattr (expr , "items" ):
981+ evaluation .message ("First" , "normal" , Integer1 , expression )
982+ return
983+ expr_len = len (expr .items )
984+ else :
985+ expr_len = len (expr .elements )
965986 if expr_len == 0 :
966987 evaluation .message ("Last" , "nolast" , expr )
967988 return
989+
990+ if isinstance (expr , ByteArray ):
991+ # ByteArray or NumericArray, ...
992+ return expr .items [- 1 ]
993+
968994 if expr_len > 2 and expr .head is SymbolSequence :
969- evaluation .message ("Last" , "argt" , expr_len )
995+ evaluation .message (
996+ "Last" , "argt" , SymbolLast , Integer (expr_len ), Integer1 , Integer2
997+ )
970998 return
971999
9721000 return expr .elements [- 1 ]
@@ -1172,19 +1200,18 @@ def eval(self, list, i, evaluation):
11721200 idx = idx .value
11731201 if idx == 0 :
11741202 return SymbolByteArray
1175- data = list .elements [0 ].value
1176- lendata = len (data )
1203+ n = len (list .items )
11771204 if idx < 0 :
1178- idx = data - idx
1205+ idx = n - idx
11791206 if idx < 0 :
11801207 evaluation .message ("Part" , "partw" , i , list )
11811208 return
11821209 else :
11831210 idx = idx - 1
1184- if idx > lendata :
1211+ if idx > n :
11851212 evaluation .message ("Part" , "partw" , i , list )
11861213 return
1187- return Integer ( data [idx ])
1214+ return list . items [idx ]
11881215 if idx is Symbol ("System`All" ):
11891216 return list
11901217 # TODO: handling ranges and lists...
0 commit comments