String operators
Text operations.
Every program can use these operators. No import is necessary.
| Operator | Arguments | Gives |
|---|---|---|
!= |
left: string, right: string | boolean |
!null? |
arg: <optional>string | boolean |
+ |
left: string, right: double | string |
+ |
left: string, right: enum | string |
+ |
left: string, right: int | string |
+ |
left: string, right: string | string |
== |
left: string, right: string | boolean |
|| |
left: string, right: string | string |
async_read_file |
path: string, filename: string | <optional>string |
at |
text: string, position: int | string |
buffer_from_string |
str: string | buffer |
buffer_read_file |
path: string, filename: string | buffer |
ccode |
text: string | char |
char_length |
text: string | int |
charAt |
text: string, position: int | int |
charcode |
text: string | char |
contains |
str: string, sub: string | boolean |
dir_exists |
path: string | boolean |
endsWith |
str: string, suffix: string | boolean |
env_var |
name: string | <optional>string |
file_exists |
path: string, filename: string | boolean |
file_mtime |
path: string, filename: string | int |
find_process |
path: string | RangerProcessBase |
first |
str: string | string |
get_option |
name: string | string |
get_required_option |
n: string | string |
has |
str: string | boolean |
has_option |
name: string | boolean |
indexOf |
str: string, key: string | int |
indexOfFrom |
str: string, key: string, startPos: int | int |
iso_add_days |
iso: string, days: int | string |
iso_between |
d: string, start: string, end: string | boolean |
iso_compare |
a: string, b: string | int |
lastIndexOf |
str: string, key: string | int |
length |
text: string | int |
md5 |
input: string | string |
normalize |
arg: string | string |
null? |
arg: <optional>string | boolean |
path_dirname |
arg: string | string |
read_file |
path: string, filename: string | <optional>string |
read_file_sync |
path: string, filename: string | <optional>string |
regex_test |
pattern: string, haystack: string | boolean |
replace |
str: string, oldStr: string, newStr: string | string |
run_process_result |
program: string, args: [string], cwd: string, capture: boolean, env: [string] | [string] |
sha256 |
input: string | string |
startsWith |
str: string, prefix: string | boolean |
str2double |
value: string | <optional>double |
str2int |
value: string | <optional>int |
strlen |
text: string | int |
strsplit |
strToSplit: string, delimiter: string | [string] |
substring |
text: string, position: int | string |
substring |
text: string, start: int, end: int | string |
to_charbuffer |
text: string | charbuffer |
to_chars |
text: string | [int] |
to_double |
value: string | <optional>double |
to_int |
txt: string | <optional>int |
to_int |
value: string | int |
to_lowercase |
s: string | string |
to_uppercase |
s: string | string |
trim |
value: string | string |
trim_right |
value: string | string |
unwrap |
arg: <optional>string | string |
utf8_substring |
text: string, start: int, end: int | string |
Target support marks
- Own template
- Default template
- No template
The operator works for a target with an own template and for a target with the default template. The default template is the * entry of the definition: it writes the same code for every target that has no template of its own. A target with no template writes no code, and a program that uses the operator does not compile for that target.
!=
(!= left right) → boolean
!=(left: string, right: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: own template
- Python: default template
- Java: own template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: own template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 11461
!null?
(!null? arg) → boolean
!null?(arg: <optional>string)Target support
- JavaScript: no template
- TypeScript: no template
- Go: no template
- Rust: no template
- Python: no template
- Java: no template
- Kotlin: no template
- Dart: no template
- Swift: no template
- C#: no template
- C++: own template
- PHP: no template
- Scala: no template
Definition: compiler/Lang.rgr, line 5615
+
(+ left right) → string
+(left: string, right: double)A double reaches a string in its shortest form that reads back as the same value -- 1.5 is "1.5", not "1.500000". Go used 'f' with six digits and C++ used std::to_string, which also fixes six digits, so the same program printed a different number on those two targets than on every other one. See r_double_to_string below.
Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: default template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: default template
- C++: own template
- PHP: own template
- Scala: default template
Definition: compiler/Lang.rgr, line 4546
+
(+ left right) → string
+(left: string, right: enum)string + operations
Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 4507
+
(+ left right) → string
+(left: string, right: int)Go; strconv.Itoa
Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: default template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: default template
- C++: own template
- PHP: own template
- Scala: default template
Definition: compiler/Lang.rgr, line 4580
+
(+ left right) → string
+(left: string, right: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: own template
- Scala: default template
Definition: compiler/Lang.rgr, line 4531
==
(== left right) → boolean
==(left: string, right: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: own template
- Python: default template
- Java: own template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: own template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 11369
||
(|| left right) → string
||(left: string, right: string)selects the first string if length > 0, else the second...
Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 4873
async_read_file
(async_read_file path filename) → <optional>string
async_read_file(path: string, filename: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: no template
- Rust: no template
- Python: no template
- Java: no template
- Kotlin: no template
- Dart: no template
- Swift: no template
- C#: no template
- C++: no template
- PHP: no template
- Scala: no template
Definition: compiler/Lang.rgr, line 3821
at
(at text position) → string
at(text: string, position: int)Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: default template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 7436
buffer_from_string
(buffer_from_string str) → buffer
buffer_from_string(str: string)Convert string to buffer (UTF-8 encoded)
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: no template
Definition: compiler/Lang.rgr, line 6873
buffer_read_file
(buffer_read_file path filename) → buffer
buffer_read_file(path: string, filename: string)Read a binary file into a buffer
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: no template
Definition: compiler/Lang.rgr, line 7009
ccode
(ccode text) → char
ccode(text: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 8334
char_length
(char_length text) → int
char_length(text: string)How many CHARACTERS are in this string -- the same number on every target, whatever unit that target happens to index in. `strlen` counts the target's own unit: UTF-16 code units on JavaScript, Java, Kotlin, C#, Scala, Dart and Swift 6, UTF-8 bytes on Rust, Go, C++ and PHP, code points on Python. That is the right number for a scan -- `while (i < (strlen s))` with `charAt s i` reads the same string either way -- and the wrong one for anything a person sees: a column, a width, a padding count, a truncation point. Those differ per target the moment the text stops being ASCII, and they differ silently. `char_length` is the count that does not: Unicode code points, the length of `(to_chars s)` without building the array. def w:int (char_length line) ; a column def n:int (strlen line) ; a scan bound For ASCII the two are equal, so the cost of choosing the honest one is nothing on the input that dominates. docs/plans/PLAN_STRING_INDEXING.md 3.3.
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 6640
charAt
(charAt text position) → int
charAt(text: string, position: int)Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 7601
charcode
(charcode text) → char
charcode(text: string)(charcode "A")
Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 8217
contains
(contains str sub) → boolean
contains(str: string, sub: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 9754
dir_exists
(dir_exists path) → boolean
dir_exists(path: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 3303
endsWith
(endsWith str suffix) → boolean
endsWith(str: string, suffix: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 9725
env_var
(env_var name) → <optional>string
env_var(name: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: no template
Definition: compiler/Lang.rgr, line 1480
file_exists
(file_exists path filename) → boolean
file_exists(path: string, filename: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 3231
file_mtime
(file_mtime path filename) → int
file_mtime(path: string, filename: string)Returns the file modification time (ms on es6/cpp; seconds on go)
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 3410
find_process
(find_process path) → RangerProcessBase
find_process(path: string)Process lifecycle operators (distinct from HttpServer start/stop)
Target support
- JavaScript: own template
- TypeScript: own template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: own template
- Dart: default template
- Swift: own template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 11800
first
(first str) → string
first(str: string)first character of the string
Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 10158
get_option
(get_option name) → string
get_option(name: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 945
get_required_option
(get_required_option n) → string
get_required_option(n: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 951
has
(has str) → boolean
has(str: string)If string value is greater than > 0
Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 932
has_option
(has_option name) → boolean
has_option(name: string)compiler options...
Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 939
indexOf
(indexOf str key) → int
indexOf(str: string, key: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Position of a substring
class Main { sfn main:void () { def text "Ranger compiler" def position (indexOf text "compiler") print ("position " + position) }}const text = "Ranger compiler";const position = text.indexOf("compiler");console.log("position " + position);The complete file
class Main { constructor() { }}/* static JavaSript main routine at the end of the JS file */function __js_main() { const text = "Ranger compiler"; const position = text.indexOf("compiler"); console.log("position " + position);}__js_main();const text : string = "Ranger compiler";const position : number = text.indexOf("compiler");console.log("position " + position);The complete file
export class Main { constructor() { }}/* static JavaSript main routine at the end of the JS file */function __js_main() { const text : string = "Ranger compiler"; const position : number = text.indexOf("compiler"); console.log("position " + position);}__js_main();var text string= "Ranger compiler";var position int64= int64(strings.Index(text, "compiler"));fmt.Println( strings.Join([]string{ "position ",strconv.FormatInt(position, 10) }, "") )The complete file
package mainimport ( "strings" "strconv" "fmt")type Main struct {}
func CreateNew_Main() *Main { me := new(Main) return me;}func main() { var text string= "Ranger compiler"; var position int64= int64(strings.Index(text, "compiler")); fmt.Println( strings.Join([]string{ "position ",strconv.FormatInt(position, 10) }, "") )}let __rg_main_thread = std::thread::Builder::new().stack_size(512 * 1024 * 1024) .spawn(__rg_main_body).expect("could not start the main thread");__rg_main_thread.join().expect("main thread panicked");The complete file
#![allow(dead_code)]
fn rg_index_of(s: &str, key: &str) -> i64 { match s.find(key) { Some(b) => b as i64, None => -1 }}fn rg_index_of_from(s: &str, key: &str, start: i64) -> i64 { if start <= 0 { return rg_index_of(s, key); } let b0 = start as usize; if b0 > s.len() { return -1; } if !s.is_char_boundary(b0) { return -1; } match s[b0..].find(key) { Some(b) => (b0 + b) as i64, None => -1 }}fn rg_last_index_of(s: &str, key: &str) -> i64 { match s.rfind(key) { Some(b) => b as i64, None => -1 }}
#[derive(Clone)]struct Main {}impl Main { pub fn new() -> Self { Self { } }}fn main() { let __rg_main_thread = std::thread::Builder::new().stack_size(512 * 1024 * 1024) .spawn(__rg_main_body).expect("could not start the main thread"); __rg_main_thread.join().expect("main thread panicked");}fn __rg_main_body() { let text: &'static str = "Ranger compiler"; let position: i64 = rg_index_of(&text, "compiler"); println!("position {}", position);}text = "Ranger compiler"position = text.find("compiler")print("position " + str(position))The complete file
# -*- coding: utf-8 -*-from __future__ import annotationsfrom typing import Optional
class Main: def __init__(self) -> None: pass# Main entry pointdef main(): text = "Ranger compiler" position = text.find("compiler") print("position " + str(position))if __name__ == "__main__": main()RgArgs.args = args;final String text = "Ranger compiler";final Integer position = text.indexOf("compiler");System.out.println(String.valueOf( "position " + position ) );The complete file
import java.io.*;
public class Main {
public static void main(String [] args ) { RgArgs.args = args; final String text = "Ranger compiler"; final Integer position = text.indexOf("compiler"); System.out.println(String.valueOf( "position " + position ) ); }}
public class RgArgs { public static String[] args = new String[0];}__g_args = argsval text : String = "Ranger compiler";val position : Int = text.indexOf("compiler");println( "position " + (position).toString() )The complete file
class Main {
}
var __g_args : Array<String> = arrayOf()
fun main(args : Array<String>) { __g_args = args val text : String = "Ranger compiler"; val position : Int = text.indexOf("compiler"); println( "position " + (position).toString() )}__g_args = args;String text = "Ranger compiler";int position = text.indexOf("compiler");print( "position " + (position).toString() );The complete file
class Main {}
List<String> __g_args = <String>[];
void main(List<String> args) { __g_args = args; String text = "Ranger compiler"; int position = text.indexOf("compiler"); print( "position " + (position).toString() );}let text : String = "Ranger compiler"let position : Int = r_index_of(text, "compiler", 0)print("position " + String(position))The complete file
func ==(l: Main, r: Main) -> Bool { return l === r}final class Main : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }}
// Ranger's string is a sequence of UTF-16 CODE UNITS, indexed in O(1). That is// what `charAt`, `strlen` and `substring` mean on JavaScript, Kotlin, Java and// C#, and every scan EVG writes -- `while (i < (strlen s)) { charAt s i }` --// assumes it.//// Swift's String indexes by GRAPHEME CLUSTER instead, and every such operation// walks from startIndex, so those linear scans became quadratic: parsing a// 28 KB stylesheet walked 1.25 BILLION characters where Kotlin read 84 000,// and one frame of the page walked 4.6 million where Kotlin read 68 000.//// The UTF-16 view is both the model the other targets use and the one the// standard library keeps breadcrumbs for -- it exists so NSString bridging can// offset in amortised constant time -- so this is the faster answer AND the// more consistent one.func r_utf16(_ s: String) -> String.UTF16View { s.utf16 }
func r_strlen(_ s: String) -> Int { s.utf16.count }
func r_char_at(_ s: String, _ at: Int) -> Int { if at < 0 { return 0 } let u = s.utf16 if at >= u.count { return 0 } return Int(u[u.index(u.startIndex, offsetBy: at)])}
func r_substring(_ s: String, _ from: Int, _ to: Int) -> String { let u = s.utf16 let n = u.count var a = from < 0 ? 0 : from var b = to > n ? n : to if a > n { a = n } if b < a { b = a } // A Swift String cannot hold half of a surrogate pair: a slice that cuts // one decodes to U+FFFD. Round the slice out to scalar boundaries instead, // so a walk that copies one UTF-16 unit at a time carries an emoji over // whole -- the unit that starts the pair takes both, the one that ends it // takes nothing. if a < n && a > 0 { let ua = u[u.index(u.startIndex, offsetBy: a)] if ua >= 0xDC00 && ua <= 0xDFFF { a += 1 } } if b > a && b < n { let ub = u[u.index(u.startIndex, offsetBy: b - 1)] if ub >= 0xD800 && ub <= 0xDBFF { b += 1 } } if b < a { b = a } let lo = u.index(u.startIndex, offsetBy: a) let hi = u.index(u.startIndex, offsetBy: b) return String(decoding: Array(u[lo..<hi]), as: UTF16.self)}
// An index answered in UTF-16 units, so it can be fed straight back to// r_char_at and r_substring.func r_index_of(_ s: String, _ needle: String, _ from: Int) -> Int { let u = s.utf16 let n = u.count let m = needle.utf16.count if m == 0 { return from <= n ? max(from, 0) : -1 } if m > n { return -1 } let hay = Array(u) let pin = Array(needle.utf16) var i = from < 0 ? 0 : from while i + m <= n { var k = 0 while k < m && hay[i + k] == pin[k] { k += 1 } if k == m { return i } i += 1 } return -1}
func r_last_index_of(_ s: String, _ needle: String) -> Int { let hay = Array(s.utf16) let pin = Array(needle.utf16) let n = hay.count let m = pin.count if m == 0 { return n } if m > n { return -1 } var i = n - m while i >= 0 { var k = 0 while k < m && hay[i + k] == pin[k] { k += 1 } if k == m { return i } i -= 1 } return -1}
// Main entry pointfunc __main__swift() { let text : String = "Ranger compiler" let position : Int = r_index_of(text, "compiler", 0) print("position " + String(position))}__main__swift()String text = "Ranger compiler";int position = text.IndexOf("compiler");Console.WriteLine("position " + position);The complete file
using System;class Main { static void Main( string [] args ) { String text = "Ranger compiler"; int position = text.IndexOf("compiler"); Console.WriteLine("position " + position); }}std::string text = std::string("Ranger compiler");int position = r_string_index_of(text , std::string("compiler"));std::cout << std::string("position ") + std::to_string(position) << std::endl;return 0;The complete file
#include <memory>#include <string>#include <iostream>
// define classes here to avoid compiler errorsclass Main;
int r_string_index_of( const std::string& str, const std::string& key ) { auto n = str.find( key ); if (n == std::string::npos) { return -1; } return n;}
// header definitionsclass Main { public : /* class constructor */ Main( ); /* static methods */ static void main();};
int __g_argc;char **__g_argv;Main::Main( ) {}int main(int argc, char* argv[]) { __g_argc = argc; __g_argv = argv; std::string text = std::string("Ranger compiler"); int position = r_string_index_of(text , std::string("compiler")); std::cout << std::string("position ") + std::to_string(position) << std::endl; return 0;}$text = "Ranger compiler";$position = (($p = strpos($text, "compiler")) !== false ? $p : -1);echo( "position " . $position . "\n");The complete file
<?php
class Main { function __construct( ) { }}/* static PHP main routine */$text = "Ranger compiler";$position = (($p = strpos($text, "compiler")) !== false ? $p : -1);echo( "position " . $position . "\n");val text : String = "Ranger compiler"val position : Int = text.indexOf("compiler")println( "position " + position )The complete file
case class ScalaReturnValue(value:Any) extends Exception
// application main function for Mainobject AppMain extends App { val text : String = "Ranger compiler" val position : Int = text.indexOf("compiler") println( "position " + position )}Definition: compiler/Lang.rgr, line 9337
indexOfFrom
(indexOfFrom str key startPos) → int
indexOfFrom(str: string, key: string, startPos: int)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 9459
iso_add_days
(iso_add_days iso days) → string
iso_add_days(iso: string, days: int)ISO calendar dates (YYYY-MM-DD). See lib/IsoDate/ and ai/ISO_DATE.md.
Target support
- JavaScript: own template
- TypeScript: own template
- Go: default template
- Rust: default template
- Python: default template
- Java: own template
- Kotlin: own template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 6170
iso_between
(iso_between d start end) → boolean
iso_between(d: string, start: string, end: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: default template
- Rust: default template
- Python: default template
- Java: own template
- Kotlin: own template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 6190
iso_compare
(iso_compare a b) → int
iso_compare(a: string, b: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: default template
- Rust: default template
- Python: default template
- Java: own template
- Kotlin: own template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 6180
lastIndexOf
(lastIndexOf str key) → int
lastIndexOf(str: string, key: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 9582
length
(length text) → int
length(text: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: default template
- Dart: default template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 10079
md5
(md5 input) → string
md5(input: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: no template
- Rust: no template
- Python: no template
- Java: no template
- Kotlin: no template
- Dart: no template
- Swift: no template
- C#: no template
- C++: no template
- PHP: no template
- Scala: no template
Definition: compiler/Lang.rgr, line 1280
normalize
(normalize arg) → string
normalize(arg: string)I/O
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: default template
- Kotlin: own template
- Dart: own template
- Swift: default template
- C#: own template
- C++: own template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 2250
null?
(null? arg) → boolean
null?(arg: <optional>string)Gives true when the optional text is empty.
Target support
- JavaScript: no template
- TypeScript: no template
- Go: no template
- Rust: no template
- Python: no template
- Java: no template
- Kotlin: no template
- Dart: no template
- Swift: no template
- C#: no template
- C++: own template
- PHP: no template
- Scala: no template
Optional values
class Main { sfn main:void () { def name@(optional):string def shown (?? name "unknown") print ("default " + shown) if (null? name) { print "the name is empty" } name = "Ada" def value (!! name) print ("value " + value) }}let name;const shown = (name ?? "unknown");console.log("default " + shown);if ( typeof(name) === "undefined" ) { console.log("the name is empty");}name = "Ada";const value = name;console.log("value " + value);The complete file
class Main { constructor() { }}/* static JavaSript main routine at the end of the JS file */function __js_main() { let name; const shown = (name ?? "unknown"); console.log("default " + shown); if ( typeof(name) === "undefined" ) { console.log("the name is empty"); } name = "Ada"; const value = name; console.log("value " + value);}__js_main();let name : string | undefined ;const shown : string = (name ?? "unknown");console.log("default " + shown);if ( typeof(name) === "undefined" ) { console.log("the name is empty");}name = "Ada";const value : string = name;console.log("value " + value);The complete file
export class Main { constructor() { }}/* static JavaSript main routine at the end of the JS file */function __js_main() { let name : string | undefined ; const shown : string = (name ?? "unknown"); console.log("default " + shown); if ( typeof(name) === "undefined" ) { console.log("the name is empty"); } name = "Ada"; const value : string = name; console.log("value " + value);}__js_main();var name *GoNullable = new(GoNullable);var shown string= (func() string { if name.has_value { return name.value.(string) } else { return "unknown"} }());fmt.Println( "default " + shown )if !name.has_value { fmt.Println( "the name is empty" )}name.value = "Ada";name.has_value = true; /* detected as non-optional */var value string= name.value.(string);fmt.Println( "value " + value )The complete file
package mainimport ( "fmt")
type GoNullable struct { value interface{} has_value bool}
type Main struct {}
func CreateNew_Main() *Main { me := new(Main) return me;}func main() { var name *GoNullable = new(GoNullable); var shown string= (func() string { if name.has_value { return name.value.(string) } else { return "unknown"} }()); fmt.Println( "default " + shown ) if !name.has_value { fmt.Println( "the name is empty" ) } name.value = "Ada"; name.has_value = true; /* detected as non-optional */ var value string= name.value.(string); fmt.Println( "value " + value )}let __rg_main_thread = std::thread::Builder::new().stack_size(512 * 1024 * 1024) .spawn(__rg_main_body).expect("could not start the main thread");__rg_main_thread.join().expect("main thread panicked");The complete file
#![allow(dead_code)]
#[derive(Clone)]struct Main {}impl Main { pub fn new() -> Self { Self { } }}fn main() { let __rg_main_thread = std::thread::Builder::new().stack_size(512 * 1024 * 1024) .spawn(__rg_main_body).expect("could not start the main thread"); __rg_main_thread.join().expect("main thread panicked");}fn __rg_main_body() { let mut name: Option<String> = None; let shown: String = if name.is_some() { name.clone().unwrap() } else { "unknown".to_string() }; println!("default {}", shown); if name.is_none() { println!("the name is empty"); } name = Some("Ada".to_string()); let value: String = name.unwrap(); println!("value {}", value);}name = Noneshown = (name if (name is not None) else "unknown")print("default " + shown)if name is None: print("the name is empty")name = "Ada";value = nameprint("value " + value)The complete file
# -*- coding: utf-8 -*-from __future__ import annotationsfrom typing import Optional
class Main: def __init__(self) -> None: pass# Main entry pointdef main(): name = None shown = (name if (name is not None) else "unknown") print("default " + shown) if name is None: print("the name is empty") name = "Ada"; value = name print("value " + value)if __name__ == "__main__": main()RgArgs.args = args;String name = null;final String shown = (name != null ) ? name : "unknown";System.out.println(String.valueOf( "default " + shown ) );if ( name == null ) { System.out.println(String.valueOf( "the name is empty" ) );}name = "Ada";final String value = name;System.out.println(String.valueOf( "value " + value ) );The complete file
import java.io.*;
public class Main {
public static void main(String [] args ) { RgArgs.args = args; String name = null; final String shown = (name != null ) ? name : "unknown"; System.out.println(String.valueOf( "default " + shown ) ); if ( name == null ) { System.out.println(String.valueOf( "the name is empty" ) ); } name = "Ada"; final String value = name; System.out.println(String.valueOf( "value " + value ) ); }}
public class RgArgs { public static String[] args = new String[0];}__g_args = argsvar name : String? = null;val shown : String = (name ?: "unknown");println( "default " + shown )if ( name== null ) { println( "the name is empty" )}name = "Ada";val value : String = name!!;println( "value " + value )The complete file
class Main {
}
var __g_args : Array<String> = arrayOf()
fun main(args : Array<String>) { __g_args = args var name : String? = null; val shown : String = (name ?: "unknown"); println( "default " + shown ) if ( name== null ) { println( "the name is empty" ) } name = "Ada"; val value : String = name!!; println( "value " + value )}__g_args = args;String? name = null;String shown = (name ?? "unknown");print( "default " + shown );if ( name == null ) { print( "the name is empty" );}name = "Ada";String value = name!;print( "value " + value );The complete file
class Main {}
List<String> __g_args = <String>[];
void main(List<String> args) { __g_args = args; String? name = null; String shown = (name ?? "unknown"); print( "default " + shown ); if ( name == null ) { print( "the name is empty" ); } name = "Ada"; String value = name!; print( "value " + value );}var name : String? = nillet shown : String = (name ?? "unknown")print("default " + shown)if ( name == nil ) { print("the name is empty")}name = "Ada";let value : String = name!print("value " + value)The complete file
func ==(l: Main, r: Main) -> Bool { return l === r}final class Main : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }}// Main entry pointfunc __main__swift() { var name : String? = nil let shown : String = (name ?? "unknown") print("default " + shown) if ( name == nil ) { print("the name is empty") } name = "Ada"; let value : String = name! print("value " + value)}__main__swift()String name = null;String shown = (name ?? "unknown");Console.WriteLine("default " + shown);if ( name == null ) { Console.WriteLine("the name is empty");}name = "Ada";String value = name;Console.WriteLine("value " + value);The complete file
using System;class Main { static void Main( string [] args ) { String name = null; String shown = (name ?? "unknown"); Console.WriteLine("default " + shown); if ( name == null ) { Console.WriteLine("the name is empty"); } name = "Ada"; String value = name; Console.WriteLine("value " + value); }}r_optional_primitive<std::string> name;std::string shown = (name.has_value ? name.value : std::string("unknown"));std::cout << std::string("default ") + shown << std::endl;if ( name.has_value == false ) { std::cout << std::string("the name is empty") << std::endl;}name = std::string("Ada");std::string value = name;std::cout << std::string("value ") + value << std::endl;return 0;The complete file
#include <memory>#include <string>#include <iostream>
// define classes here to avoid compiler errorsclass Main;
template <class T>class r_optional_primitive { public: // has_value has to start false: cpp_str_to_int and its siblings leave the // field untouched when the conversion throws, and an indeterminate bool // made a failed str2int read back as a value on the C++ target. bool has_value = false; T value = T(); r_optional_primitive() {} // a plain value placed into an optional slot: returning a bare string // from a function declared @(optional):string arrives here. Declaring // any constructor takes the implicit default one away, hence the pair. r_optional_primitive(const T & a_value) : has_value(true), value(a_value) {} r_optional_primitive<T> & operator=(const r_optional_primitive<T> & rhs) { has_value = rhs.has_value; value = rhs.value; return *this; } r_optional_primitive<T> & operator=(const T a_value) { has_value = true; value = a_value; return *this; }};
// header definitionsclass Main { public : /* class constructor */ Main( ); /* static methods */ static void main();};
int __g_argc;char **__g_argv;Main::Main( ) {}int main(int argc, char* argv[]) { __g_argc = argc; __g_argv = argv; r_optional_primitive<std::string> name; std::string shown = (name.has_value ? name.value : std::string("unknown")); std::cout << std::string("default ") + shown << std::endl; if ( name.has_value == false ) { std::cout << std::string("the name is empty") << std::endl; } name = std::string("Ada"); std::string value = name; std::cout << std::string("value ") + value << std::endl; return 0;}$name = null;$shown = ($name ?? "unknown");echo( "default " . $shown . "\n");if ( (!isset($name)) ) { echo( "the name is empty" . "\n");}$name = "Ada";$value = $name;echo( "value " . $value . "\n");The complete file
<?php
class Main { function __construct( ) { }}/* static PHP main routine */$name = null;$shown = ($name ?? "unknown");echo( "default " . $shown . "\n");if ( (!isset($name)) ) { echo( "the name is empty" . "\n");}$name = "Ada";$value = $name;echo( "value " . $value . "\n");var name : Option[String] = Option.empty[String]val shown : String = (name).getOrElse("unknown")println( "default " + shown )if ( name.isDefined == false ) { println( "the name is empty" )}name = Some("Ada")val value : String = name.getprintln( "value " + value )The complete file
case class ScalaReturnValue(value:Any) extends Exception
// application main function for Mainobject AppMain extends App { var name : Option[String] = Option.empty[String] val shown : String = (name).getOrElse("unknown") println( "default " + shown ) if ( name.isDefined == false ) { println( "the name is empty" ) } name = Some("Ada") val value : String = name.get println( "value " + value )}Definition: compiler/Lang.rgr, line 5560
path_dirname
(path_dirname arg) → string
path_dirname(arg: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: default template
- Kotlin: own template
- Dart: own template
- Swift: default template
- C#: own template
- C++: own template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 2563
read_file
(read_file path filename) → <optional>string
read_file(path: string, filename: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 3828
read_file_sync
(read_file_sync path filename) → <optional>string
read_file_sync(path: string, filename: string)read_file, but not async on JavaScript. read_file awaits fs.readFile, so on JavaScript every function that reads a file, and every function that can reach one, is emitted async: in the compiler that was the whole import, analysis and writer chain, and each call then paid for a promise and a heap frame -- three seconds of a twelve second compile, all of it garbage. This one reads with readFileSync and answers absent on failure, as read_file does. The other targets read synchronously either way and share read_file's polyfills, which the writer emits once per text. Use it where blocking the event loop is fine: a command line tool, not a server.
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 4017
regex_test
(regex_test pattern haystack) → boolean
regex_test(pattern: string, haystack: string)Case-insensitive regex substring search. Pattern is a string (no /literal/). See lib/Regex/ and ai/REGEX.md.
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: no template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: no template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 6201
replace
(replace str oldStr newStr) → string
replace(str: string, oldStr: string, newStr: string)`replace` changes every occurrence. Half of the templates used to change only the first one -- JavaScript, Go, C++ and Python -- and the other half changed them all, so the same program gave two answers. The compiler itself wants every occurrence: the trigraph escaping of RangerCppClassWriter.rgr calls `(replace s "??=" ...)` on a whole generated file.
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 9780
run_process_result
(run_process_result program args cwd capture env) → [string]
run_process_result(program: string, args: [string], cwd: string, capture: boolean, env: [string])run a command line program and answer ([exit code, stdout, stderr]); capture=false streams its output to this program instead
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: no template
Definition: compiler/Lang.rgr, line 1642
sha256
(sha256 input) → string
sha256(input: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: no template
Definition: compiler/Lang.rgr, line 957
startsWith
(startsWith str prefix) → boolean
startsWith(str: string, prefix: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 9704
str2double
(str2double value) → <optional>double
str2double(value: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 8816
str2int
(str2int value) → <optional>int
str2int(value: string)note: this has now different value, it is optional int... the optionality of the return value should be preserved can not do just def x:int (10 + (str2int "hello")) --> optional return value here...
Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 8627
strlen
(strlen text) → int
strlen(text: string)Gives the number of characters in the text.
The count is a count of code points, not a count of bytes.
Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: default template
- Dart: default template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Text length and part
class Main { sfn main:void () { def text "Ranger compiler" print ("length " + (strlen text)) print ("part " + (substring text 0 6)) }}const text = "Ranger compiler";console.log("length " + text.length);console.log("part " + text.substring(0, 6 ));The complete file
class Main { constructor() { }}/* static JavaSript main routine at the end of the JS file */function __js_main() { const text = "Ranger compiler"; console.log("length " + text.length); console.log("part " + text.substring(0, 6 ));}__js_main();const text : string = "Ranger compiler";console.log("length " + text.length);console.log("part " + text.substring(0, 6 ));The complete file
export class Main { constructor() { }}/* static JavaSript main routine at the end of the JS file */function __js_main() { const text : string = "Ranger compiler"; console.log("length " + text.length); console.log("part " + text.substring(0, 6 ));}__js_main();var text string= "Ranger compiler";fmt.Println( strings.Join([]string{ "length ",strconv.FormatInt(int64(len(text)), 10) }, "") )fmt.Println( "part " + text[int64(0):int64(6)] )The complete file
package mainimport ( "strings" "strconv" "fmt")type Main struct {}
func CreateNew_Main() *Main { me := new(Main) return me;}func main() { var text string= "Ranger compiler"; fmt.Println( strings.Join([]string{ "length ",strconv.FormatInt(int64(len(text)), 10) }, "") ) fmt.Println( "part " + text[int64(0):int64(6)] )}let __rg_main_thread = std::thread::Builder::new().stack_size(512 * 1024 * 1024) .spawn(__rg_main_body).expect("could not start the main thread");__rg_main_thread.join().expect("main thread panicked");The complete file
#![allow(dead_code)]
#[derive(Clone)]struct Main {}impl Main { pub fn new() -> Self { Self { } }}fn main() { let __rg_main_thread = std::thread::Builder::new().stack_size(512 * 1024 * 1024) .spawn(__rg_main_body).expect("could not start the main thread"); __rg_main_thread.join().expect("main thread panicked");}fn __rg_main_body() { let text: &'static str = "Ranger compiler"; println!("length {}", (text.len() as i64)); println!("part {}", rg_substring(&text, 0, 6));}
// A Ranger string index is the TARGET'S OWN unit, and on Rust that unit is// the UTF-8 byte -- what a String is actually made of, and the only one it// indexes in constant time. It used to be the char: strlen counted chars(),// charAt was chars().nth(i) and substring was chars().skip().take(), so the// ordinary `while (i < (strlen s)) { charAt s i }` scan walked the string// once per character and was quadratic -- 120 000 characters took 8.8 s// where C++ took 11 ms. It also disagreed with charcode, which has read// as_bytes()[0] all along.//// Both helpers are TOTAL, because the forms they replace were: an index past// the end answered a zero rather than panicking, and scanners here rely on// reading one past the last character.fn rg_char_at(s: &str, at: i64) -> i64 { let b = s.as_bytes(); if at < 0 { return 0; } let i = at as usize; if i >= b.len() { return 0; } b[i] as i64}
// A byte slice of a String has to be valid UTF-8, and a slice that cuts a// multi byte character is not. Measured over the compiler compiling itself// and the markdown gallery -- 78 012 slices -- not one cut a character:// a scanner slices at a delimiter it found, every delimiter here is ASCII,// and an ASCII byte is always a character boundary in UTF-8. So// from_utf8_lossy is the backstop for what the measurement did not cover,// not the expected path. docs/plans/PLAN_STRING_INDEXING.md 4.1.fn rg_substring(s: &str, from: i64, to: i64) -> String { let b = s.as_bytes(); let n = b.len() as i64; let mut a = if from < 0 { 0 } else { from }; if a > n { a = n; } let mut e = if to > n { n } else { to }; if e < a { e = a; } // A Rust String cannot hold half a character, so a slice that cuts one // has to be rounded to a boundary rather than returned as bytes -- which // is what C++, PHP and Go can do and Rust cannot. The rule is Swift's, // for the same reason (see r_substring): the unit that STARTS a character // carries the whole of it and the units inside it carry nothing, so a // walk that copies one unit at a time still reproduces the text. while a < n && (b[a as usize] & 0xC0) == 0x80 { a += 1; } if e < a { e = a; } while e < n && (b[e as usize] & 0xC0) == 0x80 { e += 1; } String::from_utf8_lossy(&b[a as usize..e as usize]).to_string()}text = "Ranger compiler"print("length " + str(len(text)))print("part " + text[0:6])The complete file
# -*- coding: utf-8 -*-from __future__ import annotationsfrom typing import Optional
class Main: def __init__(self) -> None: pass# Main entry pointdef main(): text = "Ranger compiler" print("length " + str(len(text))) print("part " + text[0:6])if __name__ == "__main__": main()RgArgs.args = args;final String text = "Ranger compiler";System.out.println(String.valueOf( "length " + text.length() ) );System.out.println(String.valueOf( "part " + text.substring(0, 6 ) ) );The complete file
import java.io.*;
public class Main {
public static void main(String [] args ) { RgArgs.args = args; final String text = "Ranger compiler"; System.out.println(String.valueOf( "length " + text.length() ) ); System.out.println(String.valueOf( "part " + text.substring(0, 6 ) ) ); }}
public class RgArgs { public static String[] args = new String[0];}__g_args = argsval text : String = "Ranger compiler";println( "length " + (text.length).toString() )println( "part " + text.substring(0, 6 ) )The complete file
class Main {
}
var __g_args : Array<String> = arrayOf()
fun main(args : Array<String>) { __g_args = args val text : String = "Ranger compiler"; println( "length " + (text.length).toString() ) println( "part " + text.substring(0, 6 ) )}__g_args = args;String text = "Ranger compiler";print( "length " + (text.length).toString() );print( "part " + text.substring(0, 6 ) );The complete file
class Main {}
List<String> __g_args = <String>[];
void main(List<String> args) { __g_args = args; String text = "Ranger compiler"; print( "length " + (text.length).toString() ); print( "part " + text.substring(0, 6 ) );}let text : String = "Ranger compiler"print("length " + String(r_strlen(text)))print("part " + r_substring(text, 0, 6))The complete file
func ==(l: Main, r: Main) -> Bool { return l === r}final class Main : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }}
// Ranger's string is a sequence of UTF-16 CODE UNITS, indexed in O(1). That is// what `charAt`, `strlen` and `substring` mean on JavaScript, Kotlin, Java and// C#, and every scan EVG writes -- `while (i < (strlen s)) { charAt s i }` --// assumes it.//// Swift's String indexes by GRAPHEME CLUSTER instead, and every such operation// walks from startIndex, so those linear scans became quadratic: parsing a// 28 KB stylesheet walked 1.25 BILLION characters where Kotlin read 84 000,// and one frame of the page walked 4.6 million where Kotlin read 68 000.//// The UTF-16 view is both the model the other targets use and the one the// standard library keeps breadcrumbs for -- it exists so NSString bridging can// offset in amortised constant time -- so this is the faster answer AND the// more consistent one.func r_utf16(_ s: String) -> String.UTF16View { s.utf16 }
func r_strlen(_ s: String) -> Int { s.utf16.count }
func r_char_at(_ s: String, _ at: Int) -> Int { if at < 0 { return 0 } let u = s.utf16 if at >= u.count { return 0 } return Int(u[u.index(u.startIndex, offsetBy: at)])}
func r_substring(_ s: String, _ from: Int, _ to: Int) -> String { let u = s.utf16 let n = u.count var a = from < 0 ? 0 : from var b = to > n ? n : to if a > n { a = n } if b < a { b = a } // A Swift String cannot hold half of a surrogate pair: a slice that cuts // one decodes to U+FFFD. Round the slice out to scalar boundaries instead, // so a walk that copies one UTF-16 unit at a time carries an emoji over // whole -- the unit that starts the pair takes both, the one that ends it // takes nothing. if a < n && a > 0 { let ua = u[u.index(u.startIndex, offsetBy: a)] if ua >= 0xDC00 && ua <= 0xDFFF { a += 1 } } if b > a && b < n { let ub = u[u.index(u.startIndex, offsetBy: b - 1)] if ub >= 0xD800 && ub <= 0xDBFF { b += 1 } } if b < a { b = a } let lo = u.index(u.startIndex, offsetBy: a) let hi = u.index(u.startIndex, offsetBy: b) return String(decoding: Array(u[lo..<hi]), as: UTF16.self)}
// An index answered in UTF-16 units, so it can be fed straight back to// r_char_at and r_substring.func r_index_of(_ s: String, _ needle: String, _ from: Int) -> Int { let u = s.utf16 let n = u.count let m = needle.utf16.count if m == 0 { return from <= n ? max(from, 0) : -1 } if m > n { return -1 } let hay = Array(u) let pin = Array(needle.utf16) var i = from < 0 ? 0 : from while i + m <= n { var k = 0 while k < m && hay[i + k] == pin[k] { k += 1 } if k == m { return i } i += 1 } return -1}
func r_last_index_of(_ s: String, _ needle: String) -> Int { let hay = Array(s.utf16) let pin = Array(needle.utf16) let n = hay.count let m = pin.count if m == 0 { return n } if m > n { return -1 } var i = n - m while i >= 0 { var k = 0 while k < m && hay[i + k] == pin[k] { k += 1 } if k == m { return i } i -= 1 } return -1}
// Main entry pointfunc __main__swift() { let text : String = "Ranger compiler" print("length " + String(r_strlen(text))) print("part " + r_substring(text, 0, 6))}__main__swift()String text = "Ranger compiler";Console.WriteLine("length " + text.Length);Console.WriteLine("part " + text.Substring(0, 6 - 0 ));The complete file
using System;class Main { static void Main( string [] args ) { String text = "Ranger compiler"; Console.WriteLine("length " + text.Length); Console.WriteLine("part " + text.Substring(0, 6 - 0 )); }}std::string text = std::string("Ranger compiler");std::cout << std::string("length ") + std::to_string((int)(text.length())) << std::endl;std::cout << std::string("part ") + text.substr(0, 6 - 0) << std::endl;return 0;The complete file
#include <memory>#include <string>#include <iostream>
// define classes here to avoid compiler errorsclass Main;
// header definitionsclass Main { public : /* class constructor */ Main( ); /* static methods */ static void main();};
int __g_argc;char **__g_argv;Main::Main( ) {}int main(int argc, char* argv[]) { __g_argc = argc; __g_argv = argv; std::string text = std::string("Ranger compiler"); std::cout << std::string("length ") + std::to_string((int)(text.length())) << std::endl; std::cout << std::string("part ") + text.substr(0, 6 - 0) << std::endl; return 0;}$text = "Ranger compiler";echo( "length " . strlen($text) . "\n");echo( "part " . substr($text, 0, 6 - 0) . "\n");The complete file
<?php
class Main { function __construct( ) { }}/* static PHP main routine */$text = "Ranger compiler";echo( "length " . strlen($text) . "\n");echo( "part " . substr($text, 0, 6 - 0) . "\n");val text : String = "Ranger compiler"println( "length " + text.length() )println( "part " + text.substring(0, 6 ) )The complete file
case class ScalaReturnValue(value:Any) extends Exception
// application main function for Mainobject AppMain extends App { val text : String = "Ranger compiler" println( "length " + text.length() ) println( "part " + text.substring(0, 6 ) )}Definition: compiler/Lang.rgr, line 6060
strsplit
(strsplit strToSplit delimiter) → [string]
strsplit(strToSplit: string, delimiter: string)wr.out (").to[collection.mutable.ArrayBuffer]" false kotlin could use also something like: .split(Regex("(?<=[!?])|(?=[!?])")) swift : .components(separatedBy:
Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: default template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 5991
substring
(substring text position) → string
substring(text: string, position: int)Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 7422
substring
(substring text start end) → string
substring(text: string, start: int, end: int)Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: default template
Text length and part
class Main { sfn main:void () { def text "Ranger compiler" print ("length " + (strlen text)) print ("part " + (substring text 0 6)) }}const text = "Ranger compiler";console.log("length " + text.length);console.log("part " + text.substring(0, 6 ));The complete file
class Main { constructor() { }}/* static JavaSript main routine at the end of the JS file */function __js_main() { const text = "Ranger compiler"; console.log("length " + text.length); console.log("part " + text.substring(0, 6 ));}__js_main();const text : string = "Ranger compiler";console.log("length " + text.length);console.log("part " + text.substring(0, 6 ));The complete file
export class Main { constructor() { }}/* static JavaSript main routine at the end of the JS file */function __js_main() { const text : string = "Ranger compiler"; console.log("length " + text.length); console.log("part " + text.substring(0, 6 ));}__js_main();var text string= "Ranger compiler";fmt.Println( strings.Join([]string{ "length ",strconv.FormatInt(int64(len(text)), 10) }, "") )fmt.Println( "part " + text[int64(0):int64(6)] )The complete file
package mainimport ( "strings" "strconv" "fmt")type Main struct {}
func CreateNew_Main() *Main { me := new(Main) return me;}func main() { var text string= "Ranger compiler"; fmt.Println( strings.Join([]string{ "length ",strconv.FormatInt(int64(len(text)), 10) }, "") ) fmt.Println( "part " + text[int64(0):int64(6)] )}let __rg_main_thread = std::thread::Builder::new().stack_size(512 * 1024 * 1024) .spawn(__rg_main_body).expect("could not start the main thread");__rg_main_thread.join().expect("main thread panicked");The complete file
#![allow(dead_code)]
#[derive(Clone)]struct Main {}impl Main { pub fn new() -> Self { Self { } }}fn main() { let __rg_main_thread = std::thread::Builder::new().stack_size(512 * 1024 * 1024) .spawn(__rg_main_body).expect("could not start the main thread"); __rg_main_thread.join().expect("main thread panicked");}fn __rg_main_body() { let text: &'static str = "Ranger compiler"; println!("length {}", (text.len() as i64)); println!("part {}", rg_substring(&text, 0, 6));}
// A Ranger string index is the TARGET'S OWN unit, and on Rust that unit is// the UTF-8 byte -- what a String is actually made of, and the only one it// indexes in constant time. It used to be the char: strlen counted chars(),// charAt was chars().nth(i) and substring was chars().skip().take(), so the// ordinary `while (i < (strlen s)) { charAt s i }` scan walked the string// once per character and was quadratic -- 120 000 characters took 8.8 s// where C++ took 11 ms. It also disagreed with charcode, which has read// as_bytes()[0] all along.//// Both helpers are TOTAL, because the forms they replace were: an index past// the end answered a zero rather than panicking, and scanners here rely on// reading one past the last character.fn rg_char_at(s: &str, at: i64) -> i64 { let b = s.as_bytes(); if at < 0 { return 0; } let i = at as usize; if i >= b.len() { return 0; } b[i] as i64}
// A byte slice of a String has to be valid UTF-8, and a slice that cuts a// multi byte character is not. Measured over the compiler compiling itself// and the markdown gallery -- 78 012 slices -- not one cut a character:// a scanner slices at a delimiter it found, every delimiter here is ASCII,// and an ASCII byte is always a character boundary in UTF-8. So// from_utf8_lossy is the backstop for what the measurement did not cover,// not the expected path. docs/plans/PLAN_STRING_INDEXING.md 4.1.fn rg_substring(s: &str, from: i64, to: i64) -> String { let b = s.as_bytes(); let n = b.len() as i64; let mut a = if from < 0 { 0 } else { from }; if a > n { a = n; } let mut e = if to > n { n } else { to }; if e < a { e = a; } // A Rust String cannot hold half a character, so a slice that cuts one // has to be rounded to a boundary rather than returned as bytes -- which // is what C++, PHP and Go can do and Rust cannot. The rule is Swift's, // for the same reason (see r_substring): the unit that STARTS a character // carries the whole of it and the units inside it carry nothing, so a // walk that copies one unit at a time still reproduces the text. while a < n && (b[a as usize] & 0xC0) == 0x80 { a += 1; } if e < a { e = a; } while e < n && (b[e as usize] & 0xC0) == 0x80 { e += 1; } String::from_utf8_lossy(&b[a as usize..e as usize]).to_string()}text = "Ranger compiler"print("length " + str(len(text)))print("part " + text[0:6])The complete file
# -*- coding: utf-8 -*-from __future__ import annotationsfrom typing import Optional
class Main: def __init__(self) -> None: pass# Main entry pointdef main(): text = "Ranger compiler" print("length " + str(len(text))) print("part " + text[0:6])if __name__ == "__main__": main()RgArgs.args = args;final String text = "Ranger compiler";System.out.println(String.valueOf( "length " + text.length() ) );System.out.println(String.valueOf( "part " + text.substring(0, 6 ) ) );The complete file
import java.io.*;
public class Main {
public static void main(String [] args ) { RgArgs.args = args; final String text = "Ranger compiler"; System.out.println(String.valueOf( "length " + text.length() ) ); System.out.println(String.valueOf( "part " + text.substring(0, 6 ) ) ); }}
public class RgArgs { public static String[] args = new String[0];}__g_args = argsval text : String = "Ranger compiler";println( "length " + (text.length).toString() )println( "part " + text.substring(0, 6 ) )The complete file
class Main {
}
var __g_args : Array<String> = arrayOf()
fun main(args : Array<String>) { __g_args = args val text : String = "Ranger compiler"; println( "length " + (text.length).toString() ) println( "part " + text.substring(0, 6 ) )}__g_args = args;String text = "Ranger compiler";print( "length " + (text.length).toString() );print( "part " + text.substring(0, 6 ) );The complete file
class Main {}
List<String> __g_args = <String>[];
void main(List<String> args) { __g_args = args; String text = "Ranger compiler"; print( "length " + (text.length).toString() ); print( "part " + text.substring(0, 6 ) );}let text : String = "Ranger compiler"print("length " + String(r_strlen(text)))print("part " + r_substring(text, 0, 6))The complete file
func ==(l: Main, r: Main) -> Bool { return l === r}final class Main : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }}
// Ranger's string is a sequence of UTF-16 CODE UNITS, indexed in O(1). That is// what `charAt`, `strlen` and `substring` mean on JavaScript, Kotlin, Java and// C#, and every scan EVG writes -- `while (i < (strlen s)) { charAt s i }` --// assumes it.//// Swift's String indexes by GRAPHEME CLUSTER instead, and every such operation// walks from startIndex, so those linear scans became quadratic: parsing a// 28 KB stylesheet walked 1.25 BILLION characters where Kotlin read 84 000,// and one frame of the page walked 4.6 million where Kotlin read 68 000.//// The UTF-16 view is both the model the other targets use and the one the// standard library keeps breadcrumbs for -- it exists so NSString bridging can// offset in amortised constant time -- so this is the faster answer AND the// more consistent one.func r_utf16(_ s: String) -> String.UTF16View { s.utf16 }
func r_strlen(_ s: String) -> Int { s.utf16.count }
func r_char_at(_ s: String, _ at: Int) -> Int { if at < 0 { return 0 } let u = s.utf16 if at >= u.count { return 0 } return Int(u[u.index(u.startIndex, offsetBy: at)])}
func r_substring(_ s: String, _ from: Int, _ to: Int) -> String { let u = s.utf16 let n = u.count var a = from < 0 ? 0 : from var b = to > n ? n : to if a > n { a = n } if b < a { b = a } // A Swift String cannot hold half of a surrogate pair: a slice that cuts // one decodes to U+FFFD. Round the slice out to scalar boundaries instead, // so a walk that copies one UTF-16 unit at a time carries an emoji over // whole -- the unit that starts the pair takes both, the one that ends it // takes nothing. if a < n && a > 0 { let ua = u[u.index(u.startIndex, offsetBy: a)] if ua >= 0xDC00 && ua <= 0xDFFF { a += 1 } } if b > a && b < n { let ub = u[u.index(u.startIndex, offsetBy: b - 1)] if ub >= 0xD800 && ub <= 0xDBFF { b += 1 } } if b < a { b = a } let lo = u.index(u.startIndex, offsetBy: a) let hi = u.index(u.startIndex, offsetBy: b) return String(decoding: Array(u[lo..<hi]), as: UTF16.self)}
// An index answered in UTF-16 units, so it can be fed straight back to// r_char_at and r_substring.func r_index_of(_ s: String, _ needle: String, _ from: Int) -> Int { let u = s.utf16 let n = u.count let m = needle.utf16.count if m == 0 { return from <= n ? max(from, 0) : -1 } if m > n { return -1 } let hay = Array(u) let pin = Array(needle.utf16) var i = from < 0 ? 0 : from while i + m <= n { var k = 0 while k < m && hay[i + k] == pin[k] { k += 1 } if k == m { return i } i += 1 } return -1}
func r_last_index_of(_ s: String, _ needle: String) -> Int { let hay = Array(s.utf16) let pin = Array(needle.utf16) let n = hay.count let m = pin.count if m == 0 { return n } if m > n { return -1 } var i = n - m while i >= 0 { var k = 0 while k < m && hay[i + k] == pin[k] { k += 1 } if k == m { return i } i -= 1 } return -1}
// Main entry pointfunc __main__swift() { let text : String = "Ranger compiler" print("length " + String(r_strlen(text))) print("part " + r_substring(text, 0, 6))}__main__swift()String text = "Ranger compiler";Console.WriteLine("length " + text.Length);Console.WriteLine("part " + text.Substring(0, 6 - 0 ));The complete file
using System;class Main { static void Main( string [] args ) { String text = "Ranger compiler"; Console.WriteLine("length " + text.Length); Console.WriteLine("part " + text.Substring(0, 6 - 0 )); }}std::string text = std::string("Ranger compiler");std::cout << std::string("length ") + std::to_string((int)(text.length())) << std::endl;std::cout << std::string("part ") + text.substr(0, 6 - 0) << std::endl;return 0;The complete file
#include <memory>#include <string>#include <iostream>
// define classes here to avoid compiler errorsclass Main;
// header definitionsclass Main { public : /* class constructor */ Main( ); /* static methods */ static void main();};
int __g_argc;char **__g_argv;Main::Main( ) {}int main(int argc, char* argv[]) { __g_argc = argc; __g_argv = argv; std::string text = std::string("Ranger compiler"); std::cout << std::string("length ") + std::to_string((int)(text.length())) << std::endl; std::cout << std::string("part ") + text.substr(0, 6 - 0) << std::endl; return 0;}$text = "Ranger compiler";echo( "length " . strlen($text) . "\n");echo( "part " . substr($text, 0, 6 - 0) . "\n");The complete file
<?php
class Main { function __construct( ) { }}/* static PHP main routine */$text = "Ranger compiler";echo( "length " . strlen($text) . "\n");echo( "part " . substr($text, 0, 6 - 0) . "\n");val text : String = "Ranger compiler"println( "length " + text.length() )println( "part " + text.substring(0, 6 ) )The complete file
case class ScalaReturnValue(value:Any) extends Exception
// application main function for Mainobject AppMain extends App { val text : String = "Ranger compiler" println( "length " + text.length() ) println( "part " + text.substring(0, 6 ) )}Definition: compiler/Lang.rgr, line 7865
to_charbuffer
(to_charbuffer text) → charbuffer
to_charbuffer(text: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 6724
to_chars
(to_chars text) → [int]
to_chars(text: string)A `charbuffer` is a buffer of BYTES -- see the block above the charbuffer overloads for what that does and does not mean. This operator is one of the two places the line between text and bytes is crossed, so it is the place that names the encoding: the bytes are the UTF-8 of the text, on every target. docs/plans/PLAN_STRING_INDEXING.md 2.3. The portable indexable view of text: Unicode CODE POINTS, the same sequence on every target, built once in O(n) and read in O(1). `charAt` on a `string` is the target's own unit -- a UTF-16 code unit, a code point or a UTF-8 byte, depending on where it runs -- and that is what makes it O(1) there. It is right for a scanner over ASCII structure and wrong for anything a human wrote. `to_chars` is the conversion that makes an index mean one thing everywhere, and because the program names it, the allocation is asked for rather than hidden. def cs:[int] (to_chars s) def n:int (array_length cs) def c:int (itemAt cs 0) Above the Basic Multilingual Plane this is the only view that agrees with itself: an emoji is ONE element here and two UTF-16 units or four UTF-8 bytes in the other views. docs/plans/PLAN_STRING_INDEXING.md 2.2.
Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 6496
to_double
(to_double value) → <optional>double
to_double(value: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 8951
to_int
(to_int txt) → <optional>int
to_int(txt: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: default template
- Rust: default template
- Python: default template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: default template
- C#: default template
- C++: default template
- PHP: default template
- Scala: default template
Definition: compiler/Lang.rgr, line 7391
to_int
(to_int value) → int
to_int(value: string)Target support
- JavaScript: no template
- TypeScript: no template
- Go: no template
- Rust: no template
- Python: no template
- Java: no template
- Kotlin: no template
- Dart: no template
- Swift: no template
- C#: no template
- C++: no template
- PHP: own template
- Scala: no template
Definition: compiler/Lang.rgr, line 11361
to_lowercase
(to_lowercase s) → string
to_lowercase(s: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 11272
to_uppercase
(to_uppercase s) → string
to_uppercase(s: string)Target support
- JavaScript: own template
- TypeScript: own template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 11303
trim
(trim value) → string
trim(value: string)Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: default template
- Kotlin: default template
- Dart: default template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 5936
trim_right
(trim_right value) → string
trim_right(value: string)trim_right - removes whitespace from the right side of string
Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 5962
unwrap
(unwrap arg) → string
unwrap(arg: <optional>string)see the null? overload: an optional string carries its own presence bit on C++, so reading the value out of one is not a no-op.
Target support
- JavaScript: no template
- TypeScript: no template
- Go: no template
- Rust: no template
- Python: no template
- Java: no template
- Kotlin: no template
- Dart: no template
- Swift: no template
- C#: no template
- C++: own template
- PHP: no template
- Scala: no template
Definition: compiler/Lang.rgr, line 4323
utf8_substring
(utf8_substring text start end) → string
utf8_substring(text: string, start: int, end: int)The code point slice. `substring` counts whatever unit its target's strlen and charAt count, so that scanning and slicing agree; this one always counts characters, for text being measured rather than scanned -- truncating a label to twenty characters, say, without cutting a multi byte character in half. Targets whose strings are UTF-16 (Java, Kotlin, Scala, C#, and the JavaScript family) count code points here, except that a character outside the basic plane still occupies two units in the `*` fallback -- Array.from is the code point split, so the fallback below uses it.
Target support
- JavaScript: default template
- TypeScript: default template
- Go: own template
- Rust: own template
- Python: own template
- Java: own template
- Kotlin: own template
- Dart: own template
- Swift: own template
- C#: own template
- C++: own template
- PHP: own template
- Scala: own template
Definition: compiler/Lang.rgr, line 8049
Ranger 3.5.1 · commit f323fd4 · development build