@@ -74,6 +74,7 @@ heavy::ExternFunction newline;
7474heavy::ExternFunction string_append;
7575heavy::ExternFunction string_copy;
7676heavy::ExternFunction string_length;
77+ heavy::ExternFunction string_ref;
7778heavy::ExternFunction number_to_string;
7879heavy::ExternFunction eq;
7980heavy::ExternFunction equal;
@@ -518,10 +519,43 @@ void string_append(Context& C, ValueRefs Args) {
518519void string_length (Context& C, ValueRefs Args) {
519520 if (Args.size () != 1 || !isa<String, Symbol>(Args[0 ]))
520521 return C.RaiseError (" expecting string-like object" );
521- int Size = static_cast <int >(Args[0 ].getStringRef ().size ());
522+
523+ auto Utf8View = detail::Utf8View (Args[0 ].getStringRef ());
524+
525+ int Size = 0 ;
526+ while (Utf8View.drop_front ())
527+ ++Size;
528+
522529 return C.Cont (Int (Size));
523530}
524531
532+ void string_ref (Context& C, ValueRefs Args) {
533+ size_t K = 0 ;
534+ if (Args.size () != 2 )
535+ return C.RaiseError (" invalid arity" );
536+ if (!isa<String, Symbol>(Args[0 ]))
537+ return C.RaiseError (" expecting string-like object" );
538+ if (Args.size () == 2 ) {
539+ if (isa<Int>(Args[1 ]) && cast<Int>(Args[1 ]) >= 0 )
540+ K = static_cast <size_t >(cast<Int>(Args[1 ]));
541+ else
542+ return C.RaiseError (" expecting positive integer" );
543+ }
544+
545+ auto Utf8View = detail::Utf8View (Args[0 ].getStringRef ());
546+
547+ Value V;
548+ for (size_t I = 0 ; I <= K; ++I) {
549+ V = Utf8View.drop_front ();
550+ if (!V) {
551+ return C.RaiseError (" invalid index for string: {0} {1}" ,
552+ {Args[1 ], Args[0 ]});
553+ }
554+ }
555+
556+ return C.Cont (V);
557+ }
558+
525559void string_copy (Context& C, ValueRefs Args) {
526560 if (Args.size () > 3 )
527561 return C.RaiseError (" invalid arity" );
@@ -532,20 +566,31 @@ void string_copy(Context& C, ValueRefs Args) {
532566 size_t EndPos = ~size_t (0 ); // npos
533567
534568 if (Args.size () >= 2 ) {
535- if (isa<Int>(Args[1 ]))
569+ if (isa<Int>(Args[1 ]) && cast<Int>(Args[ 1 ]) >= 0 )
536570 StartPos = static_cast <size_t >(cast<Int>(Args[1 ]));
537571 else
538- return C.RaiseError (" expecting integer" );
572+ return C.RaiseError (" expecting positive integer" );
539573 }
540574 if (Args.size () == 3 ) {
541- if (isa<Int>(Args[2 ]))
575+ if (isa<Int>(Args[2 ]) && cast<Int>(Args[ 2 ]) >= 0 )
542576 EndPos = static_cast <size_t >(cast<Int>(Args[2 ]));
543577 else
544- return C.RaiseError (" expecting integer" );
578+ return C.RaiseError (" expecting positive integer" );
579+ }
580+
581+ auto View = detail::Utf8View (Args[0 ].getStringRef ());
582+ size_t I = 0 ;
583+ for (; I < StartPos; ++I)
584+ View.drop_front ();
585+ auto Back = View;
586+ llvm::StringRef ViewStr = View.Range ;
587+ if (EndPos != ~size_t (0 )) {
588+ for (; I < EndPos; ++I)
589+ Back.drop_front ();
590+ ViewStr = ViewStr.drop_back (Back.Range .size ());
545591 }
546592
547- llvm::StringRef Substr = Args[0 ].getStringRef ().slice (StartPos, EndPos);
548- return C.Cont (C.CreateString (Substr));
593+ return C.Cont (C.CreateString (ViewStr));
549594}
550595
551596void number_to_string (Context& C, ValueRefs Args) {
@@ -742,7 +787,7 @@ Value append_rec(Context& C, Value List, Value Cdr) {
742787 return Cdr;
743788 if (Pair* P = dyn_cast<Pair>(List)) {
744789 if (Value V = append_rec (C, P->Cdr , Cdr))
745- return C.CreatePair (P->Car , V);
790+ return C.CreatePair (P->Car , V, P );
746791 }
747792 return Value ();
748793};
@@ -1201,6 +1246,7 @@ void HEAVY_BASE_INIT(heavy::Context& Context) {
12011246 HEAVY_BASE_VAR (string_append) = heavy::builtins::string_append;
12021247 HEAVY_BASE_VAR (string_copy) = heavy::builtins::string_copy;
12031248 HEAVY_BASE_VAR (string_length) = heavy::builtins::string_length;
1249+ HEAVY_BASE_VAR (string_ref) = heavy::builtins::string_ref;
12041250 HEAVY_BASE_VAR (number_to_string) = heavy::builtins::number_to_string;
12051251 HEAVY_BASE_VAR (eq) = heavy::builtins::eqv;
12061252 HEAVY_BASE_VAR (equal) = heavy::builtins::equal;
@@ -1295,6 +1341,7 @@ void HEAVY_BASE_LOAD_MODULE(heavy::Context& Context) {
12951341 {" string-append" , HEAVY_BASE_VAR (string_append)},
12961342 {" string-copy" , HEAVY_BASE_VAR (string_copy)},
12971343 {" string-length" , HEAVY_BASE_VAR (string_length)},
1344+ {" string-ref" , HEAVY_BASE_VAR (string_ref)},
12981345 {" number->string" , HEAVY_BASE_VAR (number_to_string)},
12991346 {" eq?" , HEAVY_BASE_VAR (eq)},
13001347 {" equal?" , HEAVY_BASE_VAR (equal)},
0 commit comments