From 2bb2ff871fa1761478442bec5f6a32c9428360a1 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 6 Apr 2025 14:20:18 -0400 Subject: Change method calls to use `foo.baz()` instead of `foo:baz()` --- examples/base64/base64.tm | 16 ++++---- examples/colorful/README.md | 2 +- examples/colorful/colorful.tm | 62 +++++++++++++++--------------- examples/commands/commands.tm | 14 +++---- examples/game/game.tm | 8 ++-- examples/game/player.tm | 4 +- examples/game/raylib.tm | 42 ++++++++++---------- examples/game/world.tm | 20 +++++----- examples/http-server/connection-queue.tm | 18 ++++----- examples/http-server/http-server.tm | 52 ++++++++++++------------- examples/http-server/sample-site/random.tm | 2 +- examples/http/http.tm | 6 +-- examples/ini/ini.tm | 30 +++++++-------- examples/learnxiny.tm | 16 ++++---- examples/log/log.tm | 14 +++---- examples/patterns/README.md | 38 +++++++++--------- examples/pthreads/pthreads.tm | 32 +++++++-------- examples/random/README.md | 26 ++++++------- examples/random/random.tm | 26 ++++++------- examples/shell/shell.tm | 20 +++++----- examples/time/time.tm | 40 +++++++++---------- examples/tomo-install/tomo-install.tm | 36 ++++++++--------- examples/tomodeps/tomodeps.tm | 58 ++++++++++++++-------------- examples/vectors/vectors.tm | 30 +++++++-------- examples/wrap/wrap.tm | 34 ++++++++-------- 25 files changed, 323 insertions(+), 323 deletions(-) (limited to 'examples') diff --git a/examples/base64/base64.tm b/examples/base64/base64.tm index e2f5ea19..714e223b 100644 --- a/examples/base64/base64.tm +++ b/examples/base64/base64.tm @@ -1,6 +1,6 @@ # Base 64 encoding and decoding -_enc := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/":bytes() +_enc := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".bytes() _EQUAL_BYTE := Byte(0x3D) @@ -25,7 +25,7 @@ _dec : [Byte] = [ lang Base64: func parse(text:Text -> Base64?): - return Base64.from_bytes(text:bytes()) + return Base64.from_bytes(text.bytes()) func from_bytes(bytes:[Byte] -> Base64?): output := &[Byte(0) for _ in bytes.length * 4 / 3 + 4] @@ -61,10 +61,10 @@ lang Base64: return Base64.from_text(Text.from_bytes(output[]) or return none) func decode_text(b64:Base64 -> Text?): - return Text.from_bytes(b64:decode_bytes() or return none) + return Text.from_bytes(b64.decode_bytes() or return none) func decode_bytes(b64:Base64 -> [Byte]?): - bytes := b64.text:bytes() + bytes := b64.text.bytes() output := &[Byte(0) for _ in bytes.length/4 * 3] src := Int64(1) dest := Int64(1) @@ -83,14 +83,14 @@ lang Base64: dest += 3 while output[-1] == 0xFF: - output[] = output:to(-2) + output[] = output.to(-2) return output[] func main(input=(/dev/stdin), decode=no): if decode: - b := Base64.from_text(input:read()!) - say(b:decode_text()!) + b := Base64.from_text(input.read()!) + say(b.decode_text()!) else: - text := input:read()! + text := input.read()! say(Base64.parse(text)!.text) diff --git a/examples/colorful/README.md b/examples/colorful/README.md index b504a730..c03ace24 100644 --- a/examples/colorful/README.md +++ b/examples/colorful/README.md @@ -60,5 +60,5 @@ use colorful $Colorful" @(blue:Welcome to the @(bold:party)!) We have @(green,bold:colors)! -":print() +".print() ``` diff --git a/examples/colorful/colorful.tm b/examples/colorful/colorful.tm index 57a2a3d6..6769841d 100644 --- a/examples/colorful/colorful.tm +++ b/examples/colorful/colorful.tm @@ -11,7 +11,7 @@ use patterns lang Colorful: convert(text:Text -> Colorful): - text = text:translate({"@"="@(at)", "("="@(lparen)", ")"="@(rparen)"}) + text = text.translate({"@"="@(at)", "("="@(lparen)", ")"="@(rparen)"}) return Colorful.from_text(text) convert(i:Int -> Colorful): return Colorful.from_text("$i") @@ -21,13 +21,13 @@ lang Colorful: return CSI ++ "m" ++ _for_terminal(c, _TermState()) func print(c:Colorful, newline=yes): - say(c:for_terminal(), newline=newline) + say(c.for_terminal(), newline=newline) func main(texts:[Text], files:[Path]=[], by_line=no): for i,text in texts: colorful := Colorful.from_text(text) - colorful:print(newline=no) + colorful.print(newline=no) if i == texts.length: say("") else: say(" ", newline=no) @@ -36,27 +36,27 @@ func main(texts:[Text], files:[Path]=[], by_line=no): for file in files: if by_line: - for line in file:by_line() or exit("Could not read file: $file"): + for line in file.by_line() or exit("Could not read file: $file"): colorful := Colorful.from_text(line) - colorful:print() + colorful.print() else: - colorful := Colorful.from_text(file:read() or exit("Could not read file: $file")) - colorful:print(newline=no) + colorful := Colorful.from_text(file.read() or exit("Could not read file: $file")) + colorful.print(newline=no) func _for_terminal(c:Colorful, state:_TermState -> Text): - return c.text:map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch): _add_ansi_sequences(m.captures[1], state)) + return c.text.map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch): _add_ansi_sequences(m.captures[1], state)) enum _Color(Default, Bright(color:Int16), Color8Bit(color:Int16), Color24Bit(color:Int32)): func from_text(text:Text -> _Color?): - if text:matches_pattern($Pat/#{3-6 hex}/): - hex := text:from(2) + if text.matches_pattern($Pat/#{3-6 hex}/): + hex := text.from(2) return none unless hex.length == 3 or hex.length == 6 if hex.length == 3: hex = hex[1]++hex[1]++hex[2]++hex[2]++hex[3]++hex[3] n := Int32.parse("0x" ++ hex) or return none return Color24Bit(n) - else if text:matches_pattern($Pat/{1-3 digit}/): + else if text.matches_pattern($Pat/{1-3 digit}/): n := Int16.parse(text) or return none if n >= 0 and n <= 255: return Color8Bit(n) else if text == "black": return _Color.Color8Bit(0) @@ -118,20 +118,20 @@ enum _Color(Default, Bright(color:Int16), Color8Bit(color:Int16), Color24Bit(col func _toggle(sequences:&[Text], cur,new:Bool, apply,unapply:Text; inline): if new and not cur: - sequences:insert(apply) + sequences.insert(apply) else if cur and not new: - sequences:insert(unapply) + sequences.insert(unapply) func _toggle2(sequences:&[Text], cur1,cur2,new1,new2:Bool, apply1,apply2,unapply:Text; inline): return if new1 == cur1 and new2 == cur2 if (cur1 and not new1) or (cur2 and not new2): # Gotta wipe at least one - sequences:insert(unapply) + sequences.insert(unapply) cur1, cur2 = no, no # Wiped out if new1 and not cur1: - sequences:insert(apply1) + sequences.insert(apply1) if new2 and not cur2: - sequences:insert(apply2) + sequences.insert(apply2) struct _TermState( bold=no, dim=no, italic=no, underline=no, blink=no, @@ -154,35 +154,35 @@ struct _TermState( _toggle2(sequences, old.subscript, old.subscript, new.superscript, new.superscript, "73", "74", "75") if new.bg != old.bg: - sequences:insert(new.bg:bg()) + sequences.insert(new.bg.bg()) if new.fg != old.fg: - sequences:insert(new.fg:fg()) + sequences.insert(new.fg.fg()) if new.underline_color != old.underline_color: - sequences:insert(new.underline_color:underline()) + sequences.insert(new.underline_color.underline()) if sequences.length == 0: return "" - return CSI ++ ";":join(sequences) ++ "m" + return CSI ++ ";".join(sequences) ++ "m" func _add_ansi_sequences(text:Text, prev_state:_TermState -> Text): if text == "lparen": return "(" else if text == "rparen": return ")" else if text == "@" or text == "at": return "@" parts := ( - text:pattern_captures($Pat/{0+..}:{0+..}/) or + text.pattern_captures($Pat/{0+..}:{0+..}/) or return "@("++_for_terminal(Colorful.from_text(text), prev_state)++")" ) - attributes := parts[1]:split_pattern($Pat/{0+space},{0+space}/) + attributes := parts[1].split_pattern($Pat/{0+space},{0+space}/) new_state := prev_state for attr in attributes: - if attr:starts_with("fg="): - new_state.fg = _Color.from_text(attr:from(4))! - else if attr:starts_with("bg="): - new_state.bg = _Color.from_text(attr:from(4))! - else if attr:starts_with("ul="): - new_state.underline_color = _Color.from_text(attr:from(4))! + if attr.starts_with("fg="): + new_state.fg = _Color.from_text(attr.from(4))! + else if attr.starts_with("bg="): + new_state.bg = _Color.from_text(attr.from(4))! + else if attr.starts_with("ul="): + new_state.underline_color = _Color.from_text(attr.from(4))! else if color := _Color.from_text(attr): new_state.fg = color else if attr == "b" or attr == "bold": @@ -212,7 +212,7 @@ func _add_ansi_sequences(text:Text, prev_state:_TermState -> Text): else: fail("Invalid attribute: '$attr'") - result := prev_state:apply(new_state) - result ++= parts[2]:map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch): _add_ansi_sequences(m.captures[1], new_state)) - result ++= new_state:apply(prev_state) + result := prev_state.apply(new_state) + result ++= parts[2].map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch): _add_ansi_sequences(m.captures[1], new_state)) + result ++= new_state.apply(prev_state) return result diff --git a/examples/commands/commands.tm b/examples/commands/commands.tm index 170e45bc..6817fca1 100644 --- a/examples/commands/commands.tm +++ b/examples/commands/commands.tm @@ -3,8 +3,8 @@ use ./commands.c use -lunistring -extern run_command:func(exe:Text, args:[Text], env:{Text=Text}, input:[Byte]?, output:&[Byte]?, error:&[Byte]? -> Int32) -extern command_by_line:func(exe:Text, args:[Text], env:{Text=Text} -> func(->Text?)?) +extern run_command : func(exe:Text, args:[Text], env:{Text=Text}, input:[Byte]?, output:&[Byte]?, error:&[Byte]? -> Int32) +extern command_by_line : func(exe:Text, args:[Text], env:{Text=Text} -> func(->Text?)?) enum ExitType(Exited(status:Int32), Signaled(signal:Int32), Failed): func succeeded(e:ExitType -> Bool): @@ -12,7 +12,7 @@ enum ExitType(Exited(status:Int32), Signaled(signal:Int32), Failed): else: return no func or_fail(e:ExitType, message:Text?=none): - if not e:succeeded(): + if not e.succeeded(): fail(message or "Program failed: $e") struct ProgramResult(stdout:[Byte], stderr:[Byte], exit_type:ExitType): @@ -28,7 +28,7 @@ struct ProgramResult(stdout:[Byte], stderr:[Byte], exit_type:ExitType): if status == 0: if text := Text.from_bytes(r.stdout): if trim_newline: - text = text:without_suffix(\n) + text = text.without_suffix(\n) return text else: return none return none @@ -52,7 +52,7 @@ struct Command(command:Text, args:[Text]=[], env:{Text=Text}={}): func result(command:Command, input="", input_bytes:[Byte]=[] -> ProgramResult): if input.length > 0: - (&input_bytes):insert_all(input:bytes()) + (&input_bytes).insert_all(input.bytes()) stdout : [Byte] = [] stderr : [Byte] = [] @@ -78,10 +78,10 @@ struct Command(command:Text, args:[Text]=[], env:{Text=Text}={}): return ExitType.Failed func get_output(command:Command, input="", trim_newline=yes -> Text?): - return command:result(input=input):output_text(trim_newline=trim_newline) + return command.result(input=input).output_text(trim_newline=trim_newline) func get_output_bytes(command:Command, input="", input_bytes:[Byte]=[] -> [Byte]?): - result := command:result(input=input, input_bytes=input_bytes) + result := command.result(input=input, input_bytes=input_bytes) when result.exit_type is Exited(status): if status == 0: return result.stdout return none diff --git a/examples/game/game.tm b/examples/game/game.tm index 36ef14ff..ce08c329 100644 --- a/examples/game/game.tm +++ b/examples/game/game.tm @@ -5,24 +5,24 @@ use ./world.tm func main(map=(./map.txt)): InitWindow(1600, 900, CString("raylib [core] example - 2d camera")) - map_contents := map:read() or exit("Could not find the game map: $map") + map_contents := map.read() or exit("Could not find the game map: $map") world := @World( player=@Player(Vector2(0,0), Vector2(0,0)), goal=@Box(Vector2(0,0), Vector2(50,50), color=Color(0x10,0xa0,0x10)), boxes=@[], ) - world:load_map(map_contents) + world.load_map(map_contents) SetTargetFPS(60) while not WindowShouldClose(): dt := GetFrameTime() - world:update(dt) + world.update(dt) BeginDrawing() ClearBackground(Color(0xCC, 0xCC, 0xCC, 0xFF)) - world:draw() + world.draw() EndDrawing() CloseWindow() diff --git a/examples/game/player.tm b/examples/game/player.tm index f73dcf6a..7f14f51e 100644 --- a/examples/game/player.tm +++ b/examples/game/player.tm @@ -16,11 +16,11 @@ struct Player(pos,prev_pos:Vector2): target_y := inline C:Num32 { (Num32_t)((IsKeyDown(KEY_W) ? -1 : 0) + (IsKeyDown(KEY_S) ? 1 : 0)) } - target_vel := Vector2(target_x, target_y):norm() * Player.WALK_SPEED + target_vel := Vector2(target_x, target_y).norm() * Player.WALK_SPEED vel := (p.pos - p.prev_pos)/World.DT vel *= Player.FRICTION - vel = vel:mix(target_vel, Player.ACCEL) + vel = vel.mix(target_vel, Player.ACCEL) p.prev_pos, p.pos = p.pos, p.pos + World.DT*vel diff --git a/examples/game/raylib.tm b/examples/game/raylib.tm index ad248e4f..5e58e996 100644 --- a/examples/game/raylib.tm +++ b/examples/game/raylib.tm @@ -27,37 +27,37 @@ struct Vector2(x,y:Num32; extern): func divided_by(v:Vector2, divisor:Num32->Vector2; inline): return Vector2(v.x/divisor, v.y/divisor) func length(v:Vector2->Num32; inline): - return (v.x*v.x + v.y*v.y):sqrt() + return (v.x*v.x + v.y*v.y).sqrt() func dist(a,b:Vector2->Num32; inline): - return a:minus(b):length() + return a.minus(b).length() func angle(v:Vector2->Num32; inline): return Num32.atan2(v.y, v.x) func norm(v:Vector2->Vector2; inline): if v.x == 0 and v.y == 0: return v - len := v:length() + len := v.length() return Vector2(v.x/len, v.y/len) func rotated(v:Vector2, radians:Num32 -> Vector2): - cos := radians:cos() or return v - sin := radians:sin() or return v + cos := radians.cos() or return v + sin := radians.sin() or return v return Vector2(cos*v.x - sin*v.y, sin*v.x + cos*v.y) func mix(a,b:Vector2, amount:Num32 -> Vector2): return Vector2( - amount:mix(a.x, b.x), - amount:mix(a.y, b.y), + amount.mix(a.x, b.x), + amount.mix(a.y, b.y), ) -extern InitWindow:func(width:Int32, height:Int32, title:CString) -extern SetTargetFPS:func(fps:Int32) -extern WindowShouldClose:func(->Bool) -extern GetFrameTime:func(->Num32) -extern BeginDrawing:func() -extern EndDrawing:func() -extern CloseWindow:func() -extern ClearBackground:func(color:Color) -extern DrawRectangle:func(x,y,width,height:Int32, color:Color) -extern DrawRectangleRec:func(rec:Rectangle, color:Color) -extern DrawRectangleV:func(pos:Vector2, size:Vector2, color:Color) -extern DrawText:func(text:CString, x,y:Int32, text_height:Int32, color:Color) -extern GetScreenWidth:func(->Int32) -extern GetScreenHeight:func(->Int32) +extern InitWindow : func(width:Int32, height:Int32, title:CString) +extern SetTargetFPS : func(fps:Int32) +extern WindowShouldClose : func(->Bool) +extern GetFrameTime : func(->Num32) +extern BeginDrawing : func() +extern EndDrawing : func() +extern CloseWindow : func() +extern ClearBackground : func(color:Color) +extern DrawRectangle : func(x,y,width,height:Int32, color:Color) +extern DrawRectangleRec : func(rec:Rectangle, color:Color) +extern DrawRectangleV : func(pos:Vector2, size:Vector2, color:Color) +extern DrawText : func(text:CString, x,y:Int32, text_height:Int32, color:Color) +extern GetScreenWidth : func(->Int32) +extern GetScreenHeight : func(->Int32) diff --git a/examples/game/world.tm b/examples/game/world.tm index 76acac6b..e8255ab8 100644 --- a/examples/game/world.tm +++ b/examples/game/world.tm @@ -44,11 +44,11 @@ struct World(player:@Player, goal:@Box, boxes:@[@Box], dt_accum=Num32(0.0), won= func update(w:@World, dt:Num32): w.dt_accum += dt while w.dt_accum > 0: - w:update_once() + w.update_once() w.dt_accum -= World.DT func update_once(w:@World): - w.player:update() + w.player.update() if solve_overlap(w.player.pos, Player.SIZE, w.goal.pos, w.goal.size) != Vector2(0,0): w.won = yes @@ -60,24 +60,24 @@ struct World(player:@Player, goal:@Box, boxes:@[@Box], dt_accum=Num32(0.0), won= func draw(w:@World): for b in w.boxes: - b:draw() - w.goal:draw() - w.player:draw() + b.draw() + w.goal.draw() + w.player.draw() if w.won: DrawText(CString("WINNER"), GetScreenWidth()/Int32(2)-Int32(48*3), GetScreenHeight()/Int32(2)-Int32(24), 48, Color(0,0,0)) func load_map(w:@World, map:Text): - if map:has("[]"): - map = map:translate({"[]"="#", "@ "="@", " "=" "}) + if map.has("[]"): + map = map.translate({"[]"="#", "@ "="@", " "=" "}) w.boxes = @[] box_size := Vector2(50., 50.) - for y,line in map:lines(): - for x,cell in line:split(): + for y,line in map.lines(): + for x,cell in line.split(): if cell == "#": pos := Vector2((Num32(x)-1) * box_size.x, (Num32(y)-1) * box_size.y) box := @Box(pos, size=box_size, color=Color(0x80,0x80,0x80)) - w.boxes:insert(box) + w.boxes.insert(box) else if cell == "@": pos := Vector2((Num32(x)-1) * box_size.x, (Num32(y)-1) * box_size.y) pos += box_size/Num32(2) - Player.SIZE/Num32(2) diff --git a/examples/http-server/connection-queue.tm b/examples/http-server/connection-queue.tm index 84f92362..3c8058d5 100644 --- a/examples/http-server/connection-queue.tm +++ b/examples/http-server/connection-queue.tm @@ -5,21 +5,21 @@ func _assert_success(name:Text, val:Int32; inline): struct ConnectionQueue(_connections:@[Int32]=@[], _mutex=pthread_mutex_t.new(), _cond=pthread_cond_t.new()): func enqueue(queue:ConnectionQueue, connection:Int32): - queue._mutex:lock() - queue._connections:insert(connection) - queue._mutex:unlock() - queue._cond:signal() + queue._mutex.lock() + queue._connections.insert(connection) + queue._mutex.unlock() + queue._cond.signal() func dequeue(queue:ConnectionQueue -> Int32): conn : Int32? = none - queue._mutex:lock() + queue._mutex.lock() while queue._connections.length == 0: - queue._cond:wait(queue._mutex) + queue._cond.wait(queue._mutex) - conn = queue._connections:pop(1) - queue._mutex:unlock() - queue._cond:signal() + conn = queue._connections.pop(1) + queue._mutex.unlock() + queue._cond.signal() return conn! diff --git a/examples/http-server/http-server.tm b/examples/http-server/http-server.tm index 1a09b601..649a9e12 100644 --- a/examples/http-server/http-server.tm +++ b/examples/http-server/http-server.tm @@ -19,9 +19,9 @@ func serve(port:Int32, handler:func(request:HTTPRequest -> HTTPResponse), num_th connections := ConnectionQueue() workers : &[@pthread_t] = &[] for i in num_threads: - workers:insert(pthread_t.new(func(): + workers.insert(pthread_t.new(func(): repeat: - connection := connections:dequeue() + connection := connections.dequeue() request_text := inline C : Text { Text_t request = EMPTY_TEXT; char buf[1024] = {}; @@ -35,7 +35,7 @@ func serve(port:Int32, handler:func(request:HTTPRequest -> HTTPResponse), num_th } request := HTTPRequest.from_text(request_text) or skip - response := handler(request):bytes() + response := handler(request).bytes() inline C { if (_$response.stride != 1) Array$compact(&_$response, 1); @@ -65,26 +65,26 @@ func serve(port:Int32, handler:func(request:HTTPRequest -> HTTPResponse), num_th repeat: conn := inline C : Int32 { accept(_$sock, NULL, NULL) } stop if conn < 0 - connections:enqueue(conn) + connections.enqueue(conn) say("Shutting down...") for w in workers: - w:cancel() + w.cancel() struct HTTPRequest(method:Text, path:Text, version:Text, headers:[Text], body:Text): func from_text(text:Text -> HTTPRequest?): - m := text:pattern_captures($Pat'{word} {..} HTTP/{..}{crlf}{..}') or return none + m := text.pattern_captures($Pat'{word} {..} HTTP/{..}{crlf}{..}') or return none method := m[1] - path := m[2]:replace_pattern($Pat'{2+ /}', '/') + path := m[2].replace_pattern($Pat'{2+ /}', '/') version := m[3] - rest := m[-1]:pattern_captures($Pat/{..}{2 crlf}{0+ ..}/) or return none - headers := rest[1]:split_pattern($Pat/{crlf}/) + rest := m[-1].pattern_captures($Pat/{..}{2 crlf}{0+ ..}/) or return none + headers := rest[1].split_pattern($Pat/{crlf}/) body := rest[-1] return HTTPRequest(method, path, version, headers, body) struct HTTPResponse(body:Text, status=200, content_type="text/plain", headers:{Text=Text}={}): func bytes(r:HTTPResponse -> [Byte]): - body_bytes := r.body:bytes() + body_bytes := r.body.bytes() extra_headers := (++: "$k: $v$(\r\n)" for k,v in r.headers) or "" return " HTTP/1.1 $(r.status) OK$\r @@ -93,10 +93,10 @@ struct HTTPResponse(body:Text, status=200, content_type="text/plain", headers:{T Connection: close$\r $extra_headers $\r$\n - ":bytes() ++ body_bytes + ".bytes() ++ body_bytes func _content_type(file:Path -> Text): - when file:extension() is "html": return "text/html" + when file.extension() is "html": return "text/html" is "tm": return "text/html" is "js": return "text/javascript" is "css": return "text/css" @@ -105,30 +105,30 @@ func _content_type(file:Path -> Text): enum RouteEntry(ServeFile(file:Path), Redirect(destination:Text)): func respond(entry:RouteEntry, request:HTTPRequest -> HTTPResponse): when entry is ServeFile(file): - body := if file:can_execute(): - Command(Text(file)):get_output()! + body := if file.can_execute(): + Command(Text(file)).get_output()! else: - file:read()! + file.read()! return HTTPResponse(body, content_type=_content_type(file)) is Redirect(destination): return HTTPResponse("Found", 302, headers={"Location"=destination}) func load_routes(directory:Path -> {Text=RouteEntry}): routes : &{Text=RouteEntry} = &{} - for file in (directory ++ (./*)):glob(): - skip unless file:is_file() - contents := file:read() or skip - server_path := "/" ++ "/":join(file:relative_to(directory).components) - if file:base_name() == "index.html": - canonical := server_path:without_suffix("index.html") + for file in (directory ++ (./*)).glob(): + skip unless file.is_file() + contents := file.read() or skip + server_path := "/" ++ "/".join(file.relative_to(directory).components) + if file.base_name() == "index.html": + canonical := server_path.without_suffix("index.html") routes[server_path] = Redirect(canonical) routes[canonical] = ServeFile(file) - else if file:extension() == "html": - canonical := server_path:without_suffix(".html") + else if file.extension() == "html": + canonical := server_path.without_suffix(".html") routes[server_path] = Redirect(canonical) routes[canonical] = ServeFile(file) - else if file:extension() == "tm": - canonical := server_path:without_suffix(".tm") + else if file.extension() == "tm": + canonical := server_path.without_suffix(".tm") routes[server_path] = Redirect(canonical) routes[canonical] = ServeFile(file) else: @@ -142,7 +142,7 @@ func main(directory:Path, port=Int32(8080)): serve(port, func(request:HTTPRequest): if handler := routes[request.path]: - return handler:respond(request) + return handler.respond(request) else: return HTTPResponse("Not found!", 404) ) diff --git a/examples/http-server/sample-site/random.tm b/examples/http-server/sample-site/random.tm index 502618e8..29b93be7 100755 --- a/examples/http-server/sample-site/random.tm +++ b/examples/http-server/sample-site/random.tm @@ -11,7 +11,7 @@ func main():

Random Number

- Your random number is: $(random:int(1,100)) + Your random number is: $(random.int(1,100)) ") diff --git a/examples/http/http.tm b/examples/http/http.tm index 12d9978e..048ffaab 100644 --- a/examples/http/http.tm +++ b/examples/http/http.tm @@ -10,7 +10,7 @@ enum _Method(GET, POST, PUT, PATCH, DELETE) func _send(method:_Method, url:Text, data:Text?, headers:[Text]=[] -> HTTPResponse): chunks : @[Text] = @[] save_chunk := func(chunk:CString, size:Int64, n:Int64): - chunks:insert(inline C:Text { + chunks.insert(inline C:Text { Text$format("%.*s", _$size*_$n, _$chunk) }) return n*size @@ -79,7 +79,7 @@ func _send(method:_Method, url:Text, data:Text?, headers:[Text]=[] -> HTTPRespon curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &_$code); } - return HTTPResponse(Int(code), "":join(chunks)) + return HTTPResponse(Int(code), "".join(chunks)) func get(url:Text, headers:[Text]=[] -> HTTPResponse): return _send(GET, url, none, headers) @@ -99,7 +99,7 @@ func delete(url:Text, data:Text?=none, headers=["Content-Type: application/json" func main(): say("GET:") say(get("https://httpbin.org/get").body) - say("Waiting 1sec... + say("Waiting 1sec...") sleep(1) say("POST:") say(post("https://httpbin.org/post", `{"key": "value"}`).body) diff --git a/examples/ini/ini.tm b/examples/ini/ini.tm index cee33f3c..3fa4c834 100644 --- a/examples/ini/ini.tm +++ b/examples/ini/ini.tm @@ -10,29 +10,29 @@ _HELP := " " func parse_ini(path:Path -> {Text={Text=Text}}): - text := path:read() or exit("Could not read INI file: $\[31;1]$(path)$\[]") + text := path.read() or exit("Could not read INI file: $\[31;1]$(path)$\[]") sections : @{Text=@{Text=Text}} = @{} current_section : @{Text=Text} = @{} # Line wraps: - text = text:replace_pattern($Pat/\{1 nl}{0+space}/, " ") + text = text.replace_pattern($Pat/\{1 nl}{0+space}/, " ") - for line in text:lines(): - line = line:trim() - skip if line:starts_with(";") or line:starts_with("#") - if line:matches_pattern($Pat/[?]/): - section_name := line:replace($Pat/[?]/, "\1"):trim():lower() + for line in text.lines(): + line = line.trim() + skip if line.starts_with(";") or line.starts_with("#") + if line.matches_pattern($Pat/[?]/): + section_name := line.replace($Pat/[?]/, "\1").trim().lower() current_section = @{} sections[section_name] = current_section - else if line:matches_pattern($Pat/{..}={..}/): - key := line:replace_pattern($Pat/{..}={..}/, "\1"):trim():lower() - value := line:replace_pattern($Pat/{..}={..}/, "\2"):trim() + else if line.matches_pattern($Pat/{..}={..}/): + key := line.replace_pattern($Pat/{..}={..}/, "\1").trim().lower() + value := line.replace_pattern($Pat/{..}={..}/, "\2").trim() current_section[key] = value return {k=v[] for k,v in sections[]} func main(path:Path, key:Text?): - keys := (key or ""):split($|/|) + keys := (key or "").split($|/|) if keys.length > 2: exit(" Too many arguments! @@ -44,18 +44,18 @@ func main(path:Path, key:Text?): say("$data") return - section := keys[1]:lower() + section := keys[1].lower() section_data := data[section] or exit(" Invalid section name: $\[31;1]$section$\[] - Valid names: $\[1]$(", ":join([k:quoted() for k in data.keys]))$\[] + Valid names: $\[1]$(", ".join([k.quoted() for k in data.keys]))$\[] ") if keys.length < 2 or keys[2] == '*': say("$section_data") return - section_key := keys[2]:lower() + section_key := keys[2].lower() value := section_data[section_key] or exit(" Invalid key: $\[31;1]$section_key$\[] - Valid keys: $\[1]$(", ":join([s:quoted() for s in section_data.keys]))$\[] + Valid keys: $\[1]$(", ".join([s.quoted() for s in section_data.keys]))$\[] ") say(value) diff --git a/examples/learnxiny.tm b/examples/learnxiny.tm index ecb1140f..6a3b7e21 100644 --- a/examples/learnxiny.tm +++ b/examples/learnxiny.tm @@ -160,18 +160,18 @@ func main(): # Sets are similar to tables, but they represent an unordered collection of # unique values: set := {10, 20, 30} - >> set:has(20) + >> set.has(20) = yes - >> set:has(999) + >> set.has(999) = no # You can do some operations on sets: other_set := {30, 40, 50} - >> set:with(other_set) + >> set.with(other_set) = {10, 20, 30, 40, 50} - >> set:without(other_set) + >> set.without(other_set) = {10, 20} - >> set:overlap(other_set) + >> set.overlap(other_set) = {30} # So far, the datastructures that have been discussed are all *immutable*, @@ -184,7 +184,7 @@ func main(): = @[999, 20, 30] # To call a method, you must use ":" and the name of the method: - my_arr:sort() + my_arr.sort() >> my_arr = @[20, 30, 999] @@ -197,7 +197,7 @@ func main(): # location. Later, a new value might end up there, but the photograph will # remain unchanged. snapshot := my_arr[] - my_arr:insert(1000) + my_arr.insert(1000) >> my_arr = @[20, 30, 999, 1000] >> snapshot @@ -275,7 +275,7 @@ func demo_structs(): = 30 # Calling methods: - alice:say_age() + alice.say_age() # You can call static methods by using the class name and ".": >> Person.get_cool_name() diff --git a/examples/log/log.tm b/examples/log/log.tm index 3aa45e7a..7375d5f6 100644 --- a/examples/log/log.tm +++ b/examples/log/log.tm @@ -13,33 +13,33 @@ func _timestamp(->Text): strftime(str, 20, "%F %T", tm_info); str } - return c_str:as_text() + return c_str.as_text() func info(text:Text, newline=yes): say("$\[2]⚫ $text$\[]", newline) for file in logfiles: - file:append("$(_timestamp()) [info] $text$\n") + file.append("$(_timestamp()) [info] $text$\n") func debug(text:Text, newline=yes): say("$\[32]🟢 $text$\[]", newline) for file in logfiles: - file:append("$(_timestamp()) [debug] $text$\n") + file.append("$(_timestamp()) [debug] $text$\n") func warn(text:Text, newline=yes): say("$\[33;1]🟡 $text$\[]", newline) for file in logfiles: - file:append("$(_timestamp()) [warn] $text$\n") + file.append("$(_timestamp()) [warn] $text$\n") func error(text:Text, newline=yes): say("$\[31;1]🔴 $text$\[]", newline) for file in logfiles: - file:append("$(_timestamp()) [error] $text$\n") + file.append("$(_timestamp()) [error] $text$\n") func add_logfile(file:Path): - logfiles:add(file) + logfiles.add(file) func remove_logfile(file:Path): - logfiles:remove(file) + logfiles.remove(file) func main(): add_logfile((./log.txt)) diff --git a/examples/patterns/README.md b/examples/patterns/README.md index 9e9d8601..8e2a1ff8 100644 --- a/examples/patterns/README.md +++ b/examples/patterns/README.md @@ -123,7 +123,7 @@ be automatically escaped using the `{1 ?}` rule described above: # This is: `{ 1{ }` (one open brace) followed by the literal text "..xxx}" # No error: ->> some_text:find($/$user_input/) +>> some_text.find($/$user_input/) = 0 ``` @@ -168,7 +168,7 @@ An iterator function that yields `PatternMatch` objects one at a time. **Example:** ```tomo text := "one, two, three" -for word in text:by_pattern($Pat"{id}"): +for word in text.by_pattern($Pat"{id}"): say(word.text) ``` @@ -190,7 +190,7 @@ An iterator function that yields text segments. **Example:** ```tomo text := "one two three" -for word in text:by_pattern_split($Pat"{whitespace}"): +for word in text.by_pattern_split($Pat"{whitespace}"): say(word.text) ``` @@ -211,7 +211,7 @@ func each_pattern(text:Text, pattern:Pat, fn:func(m:PatternMatch), recursive=yes **Example:** ```tomo text := "one two three" -text:each_pattern($Pat"{id}", func(m:PatternMatch): +text.each_pattern($Pat"{id}", func(m:PatternMatch): say(m.txt) ) ``` @@ -234,7 +234,7 @@ An array of `PatternMatch` objects. **Example:** ```tomo text := "one! two three!" ->> text:find_patterns($Pat"{id}!") +>> text.find_patterns($Pat"{id}!") = [PatternMatch(text="one!", index=1, captures=["one"]), PatternMatch(text="three!", index=10, captures=["three"])] ``` @@ -256,7 +256,7 @@ func has_pattern(text:Text, pattern:Pat -> Bool) **Example:** ```tomo text := "...okay..." ->> text:has_pattern($Pat"{id}") +>> text.has_pattern($Pat"{id}") = yes ``` @@ -281,7 +281,7 @@ A new text with the transformed matches. ```tomo text := "I have #apples and #oranges and #plums" fruits := {"apples"=4, "oranges"=5} ->> text:map_pattern($Pat'#{id}', func(match:PatternMatch): +>> text.map_pattern($Pat'#{id}', func(match:PatternMatch): fruit := match.captures[1] "$(fruits[fruit] or 0) $fruit" ) @@ -305,9 +305,9 @@ func matches_pattern(text:Text, pattern:Pat -> Bool) **Example:** ```tomo ->> "Hello!!!":matches_pattern($Pat"{id}") +>> "Hello!!!".matches_pattern($Pat"{id}") = no ->> "Hello":matches_pattern($Pat"{id}") +>> "Hello".matches_pattern($Pat"{id}") = yes ``` @@ -329,9 +329,9 @@ not match the pattern. **Example:** ```tomo ->> "123 boxes":pattern_captures($Pat"{int} {id}") +>> "123 boxes".pattern_captures($Pat"{int} {id}") = ["123", "boxes"]? ->> "xxx":pattern_captures($Pat"{int} {id}") +>> "xxx".pattern_captures($Pat"{int} {id}") = none ``` @@ -355,19 +355,19 @@ A new text with replacements applied. **Example:** ```tomo ->> "I have 123 apples and 456 oranges":replace_pattern($Pat"{int}", "some") +>> "I have 123 apples and 456 oranges".replace_pattern($Pat"{int}", "some") = "I have some apples and some oranges" ->> "I have 123 apples and 456 oranges":replace_pattern($Pat"{int}", "(@1)") +>> "I have 123 apples and 456 oranges".replace_pattern($Pat"{int}", "(@1)") = "I have (123) apples and (456) oranges" ->> "I have 123 apples and 456 oranges":replace_pattern($Pat"{int}", "(?1)", backref="?") +>> "I have 123 apples and 456 oranges".replace_pattern($Pat"{int}", "(?1)", backref="?") = "I have (123) apples and (456) oranges" ->> "bad(fn(), bad(notbad))":replace_pattern($Pat"bad(?)", "good(@1)") +>> "bad(fn(), bad(notbad))".replace_pattern($Pat"bad(?)", "good(@1)") = "good(fn(), good(notbad))" ->> "bad(fn(), bad(notbad))":replace_pattern($Pat"bad(?)", "good(@1)", recursive=no) +>> "bad(fn(), bad(notbad))".replace_pattern($Pat"bad(?)", "good(@1)", recursive=no) = "good(fn(), bad(notbad))" ``` @@ -388,7 +388,7 @@ An array of text segments. **Example:** ```tomo ->> "one two three":split_pattern($Pat"{whitespace}") +>> "one two three".split_pattern($Pat"{whitespace}") = ["one", "two", "three"] ``` @@ -412,7 +412,7 @@ A new text with all specified replacements applied. **Example:** ```tomo >> text := "foo(x, baz(1))" ->> text:translate_patterns({ +>> text.translate_patterns({ $Pat"{id}(?)"="call(fn('@1'), @2)", $Pat"{id}"="var('@1')", $Pat"{int}"="int(@1)", @@ -439,6 +439,6 @@ The trimmed text. **Example:** ```tomo ->> "123abc456":trim_pattern($Pat"{digit}") +>> "123abc456".trim_pattern($Pat"{digit}") = "abc" ``` diff --git a/examples/pthreads/pthreads.tm b/examples/pthreads/pthreads.tm index fb79e822..3be052b4 100644 --- a/examples/pthreads/pthreads.tm +++ b/examples/pthreads/pthreads.tm @@ -69,18 +69,18 @@ struct IntQueue(_queue:@[Int], _mutex:@pthread_mutex_t, _cond:@pthread_cond_t): return IntQueue(@initial, pthread_mutex_t.new(), pthread_cond_t.new()) func give(q:IntQueue, n:Int): - do: q._mutex:lock() - q._queue:insert(n) - q._mutex:unlock() - q._cond:signal() + do: q._mutex.lock() + q._queue.insert(n) + q._mutex.unlock() + q._cond.signal() func take(q:IntQueue -> Int): - do: q._mutex:lock() - n := q._queue:pop(1) + do: q._mutex.lock() + n := q._queue.pop(1) while not n: - q._cond:wait(q._mutex) - n = q._queue:pop(1) - q._mutex:unlock() + q._cond.wait(q._mutex) + n = q._queue.pop(1) + q._mutex.unlock() return n! fail("Unreachable") @@ -90,29 +90,29 @@ func main(): say_mutex := pthread_mutex_t.new() announce := func(speaker:Text, text:Text): - do: say_mutex:lock() + do: say_mutex.lock() say("$\033[2m[$speaker]$\033[m $text") - say_mutex:unlock() + say_mutex.unlock() worker := pthread_t.new(func(): say("I'm in the thread!") repeat: announce("worker", "waiting for job") - job := jobs:take() + job := jobs.take() result := job * 10 announce("worker", "Jobbing $job into $result") - results:give(result) + results.give(result) announce("worker", "Signaled $result") ) for i in 10: announce("boss", "Pushing job $i") - jobs:give(i) + jobs.give(i) announce("boss", "Gave job $i") for i in 10: announce("boss", "Getting result...") - result := results:take() + result := results.take() announce("boss", "Got result $result") - >> worker:cancel() + >> worker.cancel() diff --git a/examples/random/README.md b/examples/random/README.md index 6233c1ba..d9983ab7 100644 --- a/examples/random/README.md +++ b/examples/random/README.md @@ -17,14 +17,14 @@ a Tomo program launches. This documentation provides details on RNG functions available in the API. Arrays also have some methods which use RNG values: -`array:shuffle()`, `array:shuffled()`, `array:random()`, and `array:sample()`. +`array.shuffle()`, `array.shuffled()`, `array.random()`, and `array.sample()`. - [`func bool(rng: RNG, p: Num = 0.5 -> Bool)`](#bool) - [`func byte(rng: RNG -> Byte)`](#byte) - [`func bytes(rng: RNG, count: Int -> [Byte])`](#bytes) - [`func copy(rng: RNG -> RNG)`](#copy) - [`func int(rng: RNG, min: Int, max: Int -> Int)`](#int`, `int64`, `int32`, `int16`, `int8) -- [`func new(seed: [Byte] = (/dev/urandom):read_bytes(40)! -> RNG)`](#new) +- [`func new(seed: [Byte] = (/dev/urandom).read_bytes(40)! -> RNG)`](#new) - [`func num(rng: RNG, min: Num = 0.0, max: Num = 1.0 -> Num)`](#num`, `num32) ------------- @@ -46,9 +46,9 @@ func bool(rng: RNG, p: Num = 0.5 -> Bool) **Example:** ```tomo ->> random:bool() +>> random.bool() = no ->> random:bool(1.0) +>> random.bool(1.0) = yes ``` @@ -68,7 +68,7 @@ A random byte (0-255). **Example:** ```tomo ->> random:byte() +>> random.byte() = 103[B] ``` @@ -89,7 +89,7 @@ An array of length `count` random bytes with uniform random distribution (0-255) **Example:** ```tomo ->> random:bytes(4) +>> random.bytes(4) = [135[B], 169[B], 103[B], 212[B]] ``` @@ -111,13 +111,13 @@ A copy of the given RNG. **Example:** ```tomo >> rng := RNG.new([]) ->> copy := rng:copy() +>> copy := rng.copy() ->> rng:bytes(10) +>> rng.bytes(10) = [224[B], 102[B], 190[B], 59[B], 251[B], 50[B], 217[B], 170[B], 15[B], 221[B]] # The copy runs in parallel to the original RNG: ->> copy:bytes(10) +>> copy.bytes(10) = [224[B], 102[B], 190[B], 59[B], 251[B], 50[B], 217[B], 170[B], 15[B], 221[B]] ``` @@ -144,7 +144,7 @@ is greater than `max`, an error will be raised. **Example:** ```tomo ->> random:int(1, 10) +>> random.int(1, 10) = 8 ``` @@ -154,7 +154,7 @@ is greater than `max`, an error will be raised. Return a new random number generator. ```tomo -func new(seed: [Byte] = (/dev/urandom):read_bytes(40)! -> RNG) +func new(seed: [Byte] = (/dev/urandom).read_bytes(40)! -> RNG) ``` - `seed`: The seed use for the random number generator. A seed length of 40 @@ -167,7 +167,7 @@ A new random number generator. **Example:** ```tomo >> my_rng := RNG.new([1[B], 2[B], 3[B], 4[B]]) ->> my_rng:bool() +>> my_rng.bool() = yes ``` @@ -191,6 +191,6 @@ A floating point number uniformly chosen from the range `[min, max]` **Example:** ```tomo ->> random:num(1, 10) +>> random.num(1, 10) = 9.512830439975572 ``` diff --git a/examples/random/random.tm b/examples/random/random.tm index 95d2f9fe..1f60aff0 100644 --- a/examples/random/random.tm +++ b/examples/random/random.tm @@ -79,9 +79,9 @@ struct RandomNumberGenerator(_chacha:chacha_ctx, _random_bytes:[Byte]=[]; secret func bool(rng:&RandomNumberGenerator, probability=0.5 -> Bool): if probability == 0.5: - return rng:byte() < 0x80 + return rng.byte() < 0x80 else: - return rng:num(0., 1.) < 0.5 + return rng.num(0., 1.) < 0.5 func int64(rng:&RandomNumberGenerator, min=Int64.min, max=Int64.max -> Int64): fail("Random minimum value $min is larger than the maximum value $max") if min > max @@ -188,7 +188,7 @@ struct RandomNumberGenerator(_chacha:chacha_ctx, _random_bytes:[Byte]=[]; secret } func num32(rng:&RandomNumberGenerator, min=Num32(0.), max=Num32(1.) -> Num32): - return Num32(rng:num(Num(min), Num(max))) + return Num32(rng.num(Num(min), Num(max))) func int(rng:&RandomNumberGenerator, min:Int, max:Int -> Int): return inline C : Int { @@ -228,13 +228,13 @@ struct RandomNumberGenerator(_chacha:chacha_ctx, _random_bytes:[Byte]=[]; secret func main(): >> rng := RandomNumberGenerator.new() - >> rng:num() - >> rng:num() - >> rng:num() - >> rng:num(0, 100) - >> rng:byte() - >> rng:bytes(20) - # >> rng:int(1, 100) - # >> rng:int(1, 100) - # >> rng:int(1, 100) - # >> rng:int(1, 100) + >> rng.num() + >> rng.num() + >> rng.num() + >> rng.num(0, 100) + >> rng.byte() + >> rng.bytes(20) + # >> rng.int(1, 100) + # >> rng.int(1, 100) + # >> rng.int(1, 100) + # >> rng.int(1, 100) diff --git a/examples/shell/shell.tm b/examples/shell/shell.tm index dd26428f..816d63a2 100644 --- a/examples/shell/shell.tm +++ b/examples/shell/shell.tm @@ -2,16 +2,16 @@ use commands lang Shell: convert(text:Text -> Shell): - return Shell.from_text("'" ++ text:replace($/'/, `'"'"'`) ++ "'") + return Shell.from_text("'" ++ text.replace($/'/, `'"'"'`) ++ "'") convert(texts:[Text] -> Shell): - return Shell.from_text(" ":join([Shell(t).text for t in texts])) + return Shell.from_text(" ".join([Shell(t).text for t in texts])) convert(path:Path -> Shell): - return Shell(Text(path:expand_home())) + return Shell(Text(path.expand_home())) convert(paths:[Path] -> Shell): - return Shell.from_text(" ":join([Shell(Text(p)).text for p in paths])) + return Shell.from_text(" ".join([Shell(Text(p)).text for p in paths])) convert(n:Int -> Shell): return Shell.from_text(Text(n)) convert(n:Int64 -> Shell): return Shell.from_text(Text(n)) @@ -25,20 +25,20 @@ lang Shell: return Command("sh", ["-c", shell.text]) func result(shell:Shell, input="", input_bytes:[Byte]=[] -> ProgramResult): - return shell:command():result(input=input, input_bytes=input_bytes) + return shell.command().result(input=input, input_bytes=input_bytes) func run(shell:Shell -> ExitType): - return shell:command():run() + return shell.command().run() func get_output(shell:Shell, input="", trim_newline=yes -> Text?): - return shell:command():get_output(input=input, trim_newline=trim_newline) + return shell.command().get_output(input=input, trim_newline=trim_newline) func get_output_bytes(shell:Shell, input="", input_bytes:[Byte]=[] -> [Byte]?): - return shell:command():get_output_bytes(input=input, input_bytes=input_bytes) + return shell.command().get_output_bytes(input=input, input_bytes=input_bytes) func by_line(shell:Shell -> func(->Text?)?): - return shell:command():by_line() + return shell.command().by_line() func main(command:Shell): - for line in command:by_line()!: + for line in command.by_line()!: >> line diff --git a/examples/time/time.tm b/examples/time/time.tm index 8664f2e4..4d686ac7 100644 --- a/examples/time/time.tm +++ b/examples/time/time.tm @@ -77,10 +77,10 @@ struct Time(tv_sec:Int64, tv_usec:Int64; extern): return seconds func minutes_till(t:Time, target:Time -> Num): - return t:seconds_till(target)/60. + return t.seconds_till(target)/60. func hours_till(t:Time, target:Time -> Num): - return t:seconds_till(target)/3600. + return t.seconds_till(target)/3600. func relative(t:Time, relative_to=Time.now(), timezone=Time.local_timezone() -> Text): inline C { @@ -116,17 +116,17 @@ struct Time(tv_sec:Int64, tv_usec:Int64; extern): func time(t:Time, seconds=no, am_pm=yes, timezone=Time.local_timezone() -> Text): time := if seconds and am_pm: - t:format("%l:%M:%S%P") + t.format("%l:%M:%S%P") else if seconds and not am_pm: - t:format("%T") + t.format("%T") else if not seconds and am_pm: - t:format("%l:%M%P") + t.format("%l:%M%P") else: - t:format("%H:%M") - return time:trim() + t.format("%H:%M") + return time.trim() func date(t:Time, timezone=Time.local_timezone() -> Text): - return t:format("%F") + return t.format("%F") func info(t:Time, timezone=Time.local_timezone() -> TimeInfo): return inline C : TimeInfo { @@ -185,23 +185,23 @@ struct Time(tv_sec:Int64, tv_usec:Int64; extern): } func _run_tests(): - >> Time.now():format() + >> Time.now().format() >> Time.set_local_timezone("Europe/Paris") - >> Time.now():format() + >> Time.now().format() >> Time.set_local_timezone("America/New_York") - >> Time.now():format() - # >> Time.now():format(timezone="Europe/Paris") - # >> Time.now():format() - # >> Time.now():format("%Y-%m-%d") - # >> Time.new(2023, 11, 5):format() + >> Time.now().format() + # >> Time.now().format(timezone="Europe/Paris") + # >> Time.now().format() + # >> Time.now().format("%Y-%m-%d") + # >> Time.new(2023, 11, 5).format() # >> Time.local_timezone() - # >> Time.new(2023, 11, 5):seconds_till(Time.now()) - # >> Time.new(2023, 11, 5):relative() + # >> Time.new(2023, 11, 5).seconds_till(Time.now()) + # >> Time.new(2023, 11, 5).relative() - # >> Time.now():info() - # >> Time.now():time() - # >> Time.now():date() + # >> Time.now().info() + # >> Time.now().time() + # >> Time.now().date() # >> Time.parse("2023-11-05 01:01", "%Y-%m-%d %H:%M") # >> Time.parse("2023-11-05 01:01", "%Y-%m-%d %H:%M", timezone="Europe/Paris") diff --git a/examples/tomo-install/tomo-install.tm b/examples/tomo-install/tomo-install.tm index 0be05619..0a255987 100644 --- a/examples/tomo-install/tomo-install.tm +++ b/examples/tomo-install/tomo-install.tm @@ -12,13 +12,13 @@ _HELP := " func find_urls(path:Path -> [Text]): urls : @[Text] = @[] - if path:is_directory(): - for f in path:children(): - urls:insert_all(find_urls(f)) - else if path:is_file() and path:extension() == ".tm": - for line in path:by_line()!: - if captures := line:pattern_captures($Pat/use{space}{url}/) or line:pattern_captures($Pat/{id}{space}:={space}use{space}{url}/): - urls:insert(captures[-1]) + if path.is_directory(): + for f in path.children(): + urls.insert_all(find_urls(f)) + else if path.is_file() and path.extension() == ".tm": + for line in path.by_line()!: + if captures := line.pattern_captures($Pat/use{space}{url}/) or line.pattern_captures($Pat/{id}{space}:={space}use{space}{url}/): + urls.insert(captures[-1]) return urls func main(paths:[Path]): @@ -27,27 +27,27 @@ func main(paths:[Path]): urls := (++: find_urls(p) for p in paths) or [] - github_token := (~/.config/tomo/github-token):read() + github_token := (~/.config/tomo/github-token).read() - (~/.local/share/tomo/installed):create_directory() - (~/.local/share/tomo/lib):create_directory() + (~/.local/share/tomo/installed).create_directory() + (~/.local/share/tomo/lib).create_directory() for url in urls: original_url := url - url_without_protocol := url:trim_pattern($Pat"http{0-1 s}://", right=no) - hash := $Shell@(echo -n @url_without_protocol | sha256sum):get_output()!:slice(to=32) - if (~/.local/share/tomo/installed/$hash):is_directory(): + url_without_protocol := url.trim_pattern($Pat"http{0-1 s}://", right=no) + hash := $Shell@(echo -n @url_without_protocol | sha256sum).get_output()!.slice(to=32) + if (~/.local/share/tomo/installed/$hash).is_directory(): say("Already installed: $url") skip alias : Text? = none curl_flags := ["-L"] - if github := url_without_protocol:pattern_captures($Pat"github.com/{!/}/{!/}#{..}"): + if github := url_without_protocol.pattern_captures($Pat"github.com/{!/}/{!/}#{..}"): user := github[1] repo := github[2] tag := github[3] url = "https://api.github.com/repos/$user/$repo/tarball/$tag" - alias = "$(repo:without_prefix("tomo-")).$(tag).$(user)" + alias = "$(repo.without_prefix("tomo-")).$(tag).$(user)" if github_token: curl_flags ++= ["-H", "Authorization: Bearer $github_token"] curl_flags ++= [ @@ -55,7 +55,7 @@ func main(paths:[Path]): "-H", "X-GitHub-Api-Version: 2022-11-28", ] - (~/.local/share/tomo/downloads/$hash):create_directory() + (~/.local/share/tomo/downloads/$hash).create_directory() say($Shell@` set -euo pipefail cd ~/.local/share/tomo/downloads/@hash @@ -67,7 +67,7 @@ func main(paths:[Path]): else ln -f -s ../installed/@hash/lib@hash.so ~/.local/share/tomo/lib/lib@hash.so fi - `:get_output()!) + `.get_output()!) if alias: say($Shell( @@ -78,7 +78,7 @@ func main(paths:[Path]): else ln -f -s lib@hash.so ~/.local/share/tomo/lib/lib@alias.so fi - ):get_output()!) + ).get_output()!) say("$\[1]Installed $url!$\[]") diff --git a/examples/tomodeps/tomodeps.tm b/examples/tomodeps/tomodeps.tm index c6c2171e..dd7bec10 100644 --- a/examples/tomodeps/tomodeps.tm +++ b/examples/tomodeps/tomodeps.tm @@ -12,44 +12,44 @@ _HELP := " enum Dependency(File(path:Path), Module(name:Text)) func _get_file_dependencies(file:Path -> {Dependency}): - if not file:is_file(): + if not file.is_file(): say("Could not read file: $file") - return {} + return {/} - deps : @{Dependency} = @{} - if lines := file:by_line(): + deps : @{Dependency} = @{/} + if lines := file.by_line(): for line in lines: - if line:matches_pattern($Pat/use {..}.tm/): - file_import := Path.from_text(line:replace_pattern($Pat/use {..}/, "\1")):resolved(relative_to=file) - deps:add(Dependency.File(file_import)) - else if line:matches_pattern($Pat/use {id}/): - module_name := line:replace_pattern($Pat/use {..}/, "\1") - deps:add(Dependency.Module(module_name)) + if line.matches_pattern($Pat/use {..}.tm/): + file_import := Path.from_text(line.replace_pattern($Pat/use {..}/, "\1")).resolved(relative_to=file) + deps.add(Dependency.File(file_import)) + else if line.matches_pattern($Pat/use {id}/): + module_name := line.replace_pattern($Pat/use {..}/, "\1") + deps.add(Dependency.Module(module_name)) return deps[] func _build_dependency_graph(dep:Dependency, dependencies:@{Dependency={Dependency}}): - return if dependencies:has(dep) + return if dependencies.has(dep) - dependencies[dep] = {} # Placeholder + dependencies[dep] = {/} # Placeholder dep_deps := when dep is File(path): _get_file_dependencies(path) is Module(module): dir := (~/.local/share/tomo/installed/$module) - module_deps : @{Dependency} = @{} - visited : @{Path} = @{} - unvisited := @{f:resolved() for f in dir:files() if f:extension() == ".tm"} + module_deps : @{Dependency} = @{/} + visited : @{Path} = @{/} + unvisited := @{f.resolved() for f in dir.files() if f.extension() == ".tm"} while unvisited.length > 0: file := unvisited.items[-1] - unvisited:remove(file) - visited:add(file) + unvisited.remove(file) + visited.add(file) for file_dep in _get_file_dependencies(file): when file_dep is File(f): - if not visited:has(f): - unvisited:add(f) + if not visited.has(f): + unvisited.add(f) is Module(m): - module_deps:add(file_dep) + module_deps.add(file_dep) module_deps[] dependencies[dep] = dep_deps @@ -66,19 +66,19 @@ func _printable_name(dep:Dependency -> Text): when dep is Module(module): return "$(\x1b)[34;1m$module$(\x1b)[m" is File(f): - f = f:relative_to((.)) - if f:exists(): + f = f.relative_to((.)) + if f.exists(): return Text(f) else: return "$(\x1b)[31;1m$(f) (not found)$(\x1b)[m" func _draw_tree(dep:Dependency, dependencies:{Dependency={Dependency}}, already_printed:@{Dependency}, prefix="", is_last=yes): - if already_printed:has(dep): + if already_printed.has(dep): say(prefix ++ (if is_last: "└── " else: "├── ") ++ _printable_name(dep) ++ " $\x1b[2m(recursive)$\x1b[m") return say(prefix ++ (if is_last: "└── " else: "├── ") ++ _printable_name(dep)) - already_printed:add(dep) + already_printed.add(dep) child_prefix := prefix ++ (if is_last: " " else: "│ ") @@ -88,9 +88,9 @@ func _draw_tree(dep:Dependency, dependencies:{Dependency={Dependency}}, already_ _draw_tree(child, dependencies, already_printed, child_prefix, is_child_last) func draw_tree(dep:Dependency, dependencies:{Dependency={Dependency}}): - printed : @{Dependency} = @{} + printed : @{Dependency} = @{/} say(_printable_name(dep)) - printed:add(dep) + printed.add(dep) deps := dependencies[dep] or {/} for i,child in deps.items: is_child_last := (i == deps.length) @@ -104,11 +104,11 @@ func main(files:[Text]): ") for arg in files: - if arg:matches_pattern($Pat/{..}.tm/): - path := Path.from_text(arg):resolved() + if arg.matches_pattern($Pat/{..}.tm/): + path := Path.from_text(arg).resolved() dependencies := get_dependency_graph(File(path)) draw_tree(File(path), dependencies) - else if arg:matches_pattern($Pat/{id}/): + else if arg.matches_pattern($Pat/{id}/): dependencies := get_dependency_graph(Module(arg)) draw_tree(Module(arg), dependencies) else: diff --git a/examples/vectors/vectors.tm b/examples/vectors/vectors.tm index f978d3d1..42ada614 100644 --- a/examples/vectors/vectors.tm +++ b/examples/vectors/vectors.tm @@ -19,24 +19,24 @@ struct Vec2(x,y:Num): func divided_by(v:Vec2, divisor:Num->Vec2; inline): return Vec2(v.x/divisor, v.y/divisor) func length(v:Vec2->Num; inline): - return (v.x*v.x + v.y*v.y):sqrt() + return (v.x*v.x + v.y*v.y).sqrt() func dist(a,b:Vec2->Num; inline): - return a:minus(b):length() + return a.minus(b).length() func angle(v:Vec2->Num; inline): return Num.atan2(v.y, v.x) func norm(v:Vec2->Vec2; inline): if v.x == 0 and v.y == 0: return v - len := v:length() + len := v.length() return Vec2(v.x/len, v.y/len) func rotated(v:Vec2, radians:Num -> Vec2): - cos := radians:cos() or return v - sin := radians:sin() or return v + cos := radians.cos() or return v + sin := radians.sin() or return v return Vec2(cos*v.x - sin*v.y, sin*v.x + cos*v.y) func mix(a,b:Vec2, amount:Num -> Vec2): return Vec2( - amount:mix(a.x, b.x), - amount:mix(a.y, b.y), + amount.mix(a.x, b.x), + amount.mix(a.y, b.y), ) struct Vec3(x,y,z:Num): @@ -58,19 +58,19 @@ struct Vec3(x,y,z:Num): func divided_by(v:Vec3, divisor:Num->Vec3; inline): return Vec3(v.x/divisor, v.y/divisor, v.z/divisor) func length(v:Vec3->Num; inline): - return (v.x*v.x + v.y*v.y + v.z*v.z):sqrt() + return (v.x*v.x + v.y*v.y + v.z*v.z).sqrt() func dist(a,b:Vec3->Num; inline): - return a:minus(b):length() + return a.minus(b).length() func norm(v:Vec3->Vec3; inline): if v.x == 0 and v.y == 0 and v.z == 0: return v - len := v:length() + len := v.length() return Vec3(v.x/len, v.y/len, v.z/len) func mix(a,b:Vec3, amount:Num -> Vec3): return Vec3( - amount:mix(a.x, b.x), - amount:mix(a.y, b.y), - amount:mix(a.z, b.z), + amount.mix(a.x, b.x), + amount.mix(a.y, b.y), + amount.mix(a.z, b.z), ) @@ -97,7 +97,7 @@ struct IVec2(x,y:Int): y := Num(v.y) return Num.sqrt(x*x + y*y) func dist(a,b:IVec2->Num; inline): - return a:minus(b):length() + return a.minus(b).length() func angle(v:IVec2->Num; inline): return Num.atan2(Num(v.y), Num(v.x)) @@ -125,7 +125,7 @@ struct IVec3(x,y,z:Int): z := Num(v.z) return Num.sqrt(x*x + y*y + z*z) func dist(a,b:IVec3->Num; inline): - return a:minus(b):length() + return a.minus(b).length() func main(): >> Vec2(10, 20) diff --git a/examples/wrap/wrap.tm b/examples/wrap/wrap.tm index 61ca5821..448ab813 100644 --- a/examples/wrap/wrap.tm +++ b/examples/wrap/wrap.tm @@ -15,11 +15,11 @@ UNICODE_HYPHEN := \{hyphen} func unwrap(text:Text, preserve_paragraphs=yes, hyphen=UNICODE_HYPHEN -> Text): if preserve_paragraphs: - paragraphs := text:split($/{2+ nl}/) + paragraphs := text.split($/{2+ nl}/) if paragraphs.length > 1: - return \n\n:join([unwrap(p, hyphen=hyphen, preserve_paragraphs=no) for p in paragraphs]) + return \n\n.join([unwrap(p, hyphen=hyphen, preserve_paragraphs=no) for p in paragraphs]) - return text:replace($/$(hyphen)$(\n)/, "") + return text.replace($/$(hyphen)$(\n)/, "") func wrap(text:Text, width:Int, min_split=3, hyphen="-" -> Text): if width <= 0: @@ -35,8 +35,8 @@ func wrap(text:Text, width:Int, min_split=3, hyphen="-" -> Text): lines : @[Text] = @[] line := "" - for word in text:split($/{whitespace}/): - letters := word:split() + for word in text.split($/{whitespace}/): + letters := word.split() skip if letters.length == 0 while not _can_fit_word(line, letters, width): @@ -49,17 +49,17 @@ func wrap(text:Text, width:Int, min_split=3, hyphen="-" -> Text): split = split _max_ min_split split = split _min_ (letters.length - min_split) if line != "": line ++= " " - line ++= ((++: letters:to(split)) or "") ++ hyphen - letters = letters:from(split + 1) + line ++= ((++: letters.to(split)) or "") ++ hyphen + letters = letters.from(split + 1) else if line == "": # Force split word without hyphenation: if line != "": line ++= " " - line ++= (++: letters:to(line_space)) or "" - letters = letters:from(line_space + 1) + line ++= (++: letters.to(line_space)) or "" + letters = letters.from(line_space + 1) else: pass # Move to next line - lines:insert(line) + lines.insert(line) line = "" if letters.length > 0: @@ -67,9 +67,9 @@ func wrap(text:Text, width:Int, min_split=3, hyphen="-" -> Text): line ++= (++: letters) or "" if line != "": - lines:insert(line) + lines.insert(line) - return \n:join(lines) + return \n.join(lines) func _can_fit_word(line:Text, letters:[Text], width:Int -> Bool; inline): if line == "": @@ -82,21 +82,21 @@ func main(files:[Path], width=80, inplace=no, min_split=3, rewrap=yes, hyphen=UN files = [(/dev/stdin)] for file in files: - text := file:read() or exit("Could not read file: $file") + text := file.read() or exit("Could not read file: $file") if rewrap: text = unwrap(text) - out := if file:is_file() and inplace: + out := if file.is_file() and inplace: file else: (/dev/stdout) first := yes wrapped_paragraphs : @[Text] = @[] - for paragraph in text:split($/{2+ nl}/): - wrapped_paragraphs:insert( + for paragraph in text.split($/{2+ nl}/): + wrapped_paragraphs.insert( wrap(paragraph, width=width, min_split=min_split, hyphen=hyphen) ) - out:write(\n\n:join(wrapped_paragraphs[]) ++ \n) + out.write(\n\n.join(wrapped_paragraphs[]) ++ \n) -- cgit v1.2.3