Strings and Unicode
ASPL 0.7.0 · Current release
Current 0.7.0 operations, host support, examples, and failure rules.
On this page
Exact string values
ASPL 0.7.0 supports these operations in the browser and on the native host. A نص/string is an immutable, strict UTF-8 value. It preserves BOM, NUL, line endings, direction controls, whitespace, and normalization. matches compares exact bytes. "é" and "e\u{301}" are different strings even when they look alike.
Unicode scalar positions
Positions start at zero and count Unicode scalar values, not UTF-8 bytes, UTF-16 code units, or displayed graphemes. A combining mark counts separately; an emoji sequence can contain several scalars. length("aمرحبا😀") is 7.
| Operation | Signature | Meaning |
|---|---|---|
طول/length |
(string) -> i64 |
Scalar count |
محرف_عند/char_at |
(string, i64) -> string |
One scalar as a string |
رمز_عند/codepoint_at |
(string, i64) -> i64 |
Scalar's numeric value |
من_رمز/from_codepoint |
(i64) -> string |
String from a valid scalar |
اقتطع/slice |
(string, i64, i64) -> string |
Start inclusive, end exclusive |
An index must satisfy 0 <= index < length(text). A slice must satisfy 0 <= start <= end <= length(text). Empty slices, including at the end, succeed. Invalid indexes trap with string-index-out-of-bounds; invalid slices trap with string-slice-out-of-bounds. from_codepoint accepts zero through 1114111 except surrogate values 55296 through 57343; invalid values trap with invalid-unicode-scalar.
Concatenation and joining
+ concatenates two strings and has the usual addition precedence. Format a number explicitly before concatenating it. اجمع_نصوص/join: (list<string>, string) -> string puts the separator between elements only. An empty list produces ""; one element gets no separator. Neither operation changes the inputs or normalizes text.
Execution: Browser and native · ASPL 0.7.0
- No prior knowledge is required to open and check it.
Input: No input lines are required.
fn start_main() -> i64 {
let text = "aمرحبا😀";
if (length(text) not match 7) { return 1; }
if (char_at(text, 1) not match "م") { return 2; }
if (codepoint_at(text, 1) not match 1605) { return 3; }
if (from_codepoint(65) not match "A") { return 4; }
if (slice(text, 1, 3) not match "مر") { return 5; }
let escapes = "\n\t\r\0\u{0645}\"\\";
if (length(escapes) not match 7) { return 6; }
if (codepoint_at(escapes, 0) not match 10 or codepoint_at(escapes, 1) not match 9 or codepoint_at(escapes, 2) not match 13) { return 7; }
if (codepoint_at(escapes, 3) not match 0 or char_at(escapes, 4) not match "م") { return 8; }
if (char_at(escapes, 5) not match "\"" or char_at(escapes, 6) not match "\\") { return 9; }
let message = text + "!";
print(message);
return 0;
}
Expected outcomes
{
"browser": {
"check": "success",
"class": "success",
"output": "aمرحبا😀!",
"processStatus": 0
},
"native": {
"check": 0,
"status": 0,
"output": "aمرحبا😀!"
}
}Execution: Browser and native · ASPL 0.7.0
- No prior knowledge is required to open and check it.
Input: No input lines are required.
fn start_main() -> i64 {
let empty: list<string> = [];
if (join(empty, ",") not match "") { return 1; }
let one: list<string> = ["مرحبا"];
if (join(one, ",") not match "مرحبا") { return 2; }
let parts: list<string> = ["a", "b", "c"];
if (join(parts, ",") not match "a,b,c") { return 3; }
if (join(parts, "") not match "abc") { return 4; }
print(join(parts, ","));
return 0;
}
Expected outcomes
{
"browser": {
"check": "success",
"class": "success",
"output": "a,b,c",
"processStatus": 0
},
"native": {
"check": 0,
"status": 0,
"output": "a,b,c"
}
}Strict numeric text
The numeric reference lists every exact-width parser and formatter. Parsing returns a recoverable result, not a trap for ordinary bad text. Integer text accepts an optional ASCII sign and decimal ASCII digits, including leading zeroes. Decimal float text accepts an optional ASCII sign, digits, an optional fraction with digits after the point, and an optional exponent, or exactly nan, inf, +inf, -inf.
Whitespace, non-ASCII digits such as ٢, NUL, radix prefixes, separators, suffixes, and trailing text produce invalid-number. .5 and 1. also fail. Well-formed text outside the target range produces number-out-of-range. The editor's source-digit conversion does not convert text sent through program input or imported files.
The integer example needs two input lines, 256 then 41. The float example needs 12x then 41. Both handle the first failed result and continue to print 42 for the second line.
Execution: Browser and native · ASPL 0.7.0
- No prior knowledge is required to open and check it.
Input lines: ["256","41"]
fn start_main() -> i64 {
print("first: ");
let invalid: result<u8> = parse_u8(read_line());
if (invalid::ok) {
return 1;
}
print(invalid::error::code);
print("\nsecond: ");
let valid: result<i64> = parse_i64(read_line());
if (valid::ok) {
if (format_i64(-9223372036854775808) not match "-9223372036854775808") { return 2; }
print(format_i64(valid::value + 1));
print("\n");
return 0;
}
return 3;
}
Expected outcomes
{
"browser": {
"check": "success",
"class": "success",
"output": "first: number-out-of-range\nsecond: 42\n",
"processStatus": 0
},
"native": {
"check": 0,
"status": 0,
"output": "first: number-out-of-range\nsecond: 42\n"
}
}Execution: Browser and native · ASPL 0.7.0
- No prior knowledge is required to open and check it.
Input lines: ["12x","41"]
fn start_main() -> i64 {
print("first: ");
let invalid: result<f32> = parse_f32(read_line());
if (invalid::ok) {
return 1;
}
print(invalid::error::code);
print("\nsecond: ");
let valid: result<f64> = parse_f64(read_line());
if (valid::ok) {
if (format_f64(0.5) not match "0.5") { return 2; }
if (format_f32(1.0000000596046448) not match "1.00000012") { return 3; }
print(format_f64(valid::value + 1.0));
print("\n");
return 0;
}
return 4;
}
Expected outcomes
{
"browser": {
"check": "success",
"class": "success",
"output": "first: invalid-number\nsecond: 42\n",
"processStatus": 0
},
"native": {
"check": 0,
"status": 0,
"output": "first: invalid-number\nsecond: 42\n"
}
}Scope and complete examples
These current operations extend the historical MVP's string rules. The archived specification remains a record of that earlier scope. Complete supplied variants are available in strings, join, integer parsing, and float parsing.