Syntax tweak: use ':' for blocks

This commit is contained in:
Bruce Hill 2024-04-28 14:58:55 -04:00
parent 5910998a19
commit 3c0a8f0b89
19 changed files with 112 additions and 98 deletions

View File

@ -5,12 +5,12 @@ language that cross-compiles to C. Tomo is designed to anticipate and influence
the language design decisions of the future. the language design decisions of the future.
``` ```
func greeting(name:Text)->Text func greeting(name:Text)->Text:
greeting := "hello {name}!" greeting := "hello {name}!"
words := greeting:split(" ") words := greeting:split(" ")
return " ":join([w:capitalize() for w in words]) return " ":join([w:capitalize() for w in words])
func main(name="World") func main(name="World"):
to_say := greeting(name) to_say := greeting(name)
say(to_say) say(to_say)
``` ```

66
parse.c
View File

@ -781,8 +781,10 @@ PARSER(parse_reduction) {
} }
ast_t *fallback = NULL; ast_t *fallback = NULL;
if (match_word(&pos, "else")) if (match_word(&pos, "else")) {
expect_str(ctx, start, &pos, ":", "I expected a ':' here");
fallback = expect(ctx, pos-4, &pos, parse_expr, "I couldn't parse the expression after this 'else'"); fallback = expect(ctx, pos-4, &pos, parse_expr, "I couldn't parse the expression after this 'else'");
}
return NewAST(ctx->file, start, pos, Reduction, .iter=iter, .combination=combination, .fallback=fallback); return NewAST(ctx->file, start, pos, Reduction, .iter=iter, .combination=combination, .fallback=fallback);
} }
@ -838,7 +840,7 @@ PARSER(parse_if) {
if (!condition) condition = expect(ctx, start, &pos, parse_expr, if (!condition) condition = expect(ctx, start, &pos, parse_expr,
"I expected to find an expression for this 'if'"); "I expected to find an expression for this 'if'");
match_word(&pos, "then"); // optional expect_str(ctx, start, &pos, ":", "I expected a ':' here");
ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block, "I expected a body for this 'if' statement"); ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block, "I expected a body for this 'if' statement");
@ -848,6 +850,7 @@ PARSER(parse_if) {
const char *else_start = pos; const char *else_start = pos;
if (get_indent(ctx->file, tmp) == starting_indent && match_word(&tmp, "else")) { if (get_indent(ctx->file, tmp) == starting_indent && match_word(&tmp, "else")) {
pos = tmp; pos = tmp;
expect_str(ctx, start, &pos, ":", "I expected a ':' here");
else_body = expect(ctx, else_start, &pos, parse_opt_indented_block, "I expected a body for this 'else'"); else_body = expect(ctx, else_start, &pos, parse_opt_indented_block, "I expected a body for this 'else'");
} }
return NewAST(ctx->file, start, pos, If, .condition=condition, .body=body, .else_body=else_body); return NewAST(ctx->file, start, pos, If, .condition=condition, .body=body, .else_body=else_body);
@ -881,7 +884,8 @@ PARSER(parse_when) {
var = NULL; var = NULL;
} }
match_word(&pos, "then"); // optional expect_str(ctx, start, &pos, ":", "I expected a ':' here");
ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block, "I expected a body for this 'when' clause"); ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block, "I expected a body for this 'when' clause");
clauses = new(when_clause_t, .var=var, .tag_name=tag_name, .body=body, .next=clauses); clauses = new(when_clause_t, .var=var, .tag_name=tag_name, .body=body, .next=clauses);
tmp = pos; tmp = pos;
@ -893,6 +897,7 @@ PARSER(parse_when) {
const char *else_start = pos; const char *else_start = pos;
if (get_indent(ctx->file, tmp) == starting_indent && match_word(&tmp, "else")) { if (get_indent(ctx->file, tmp) == starting_indent && match_word(&tmp, "else")) {
pos = tmp; pos = tmp;
expect_str(ctx, start, &pos, ":", "I expected a ':' here");
else_body = expect(ctx, else_start, &pos, parse_opt_indented_block, "I expected a body for this 'else'"); else_body = expect(ctx, else_start, &pos, parse_opt_indented_block, "I expected a body for this 'else'");
} }
return NewAST(ctx->file, start, pos, When, .subject=subject, .clauses=clauses, .else_body=else_body); return NewAST(ctx->file, start, pos, When, .subject=subject, .clauses=clauses, .else_body=else_body);
@ -911,6 +916,7 @@ PARSER(parse_for) {
} }
expect_str(ctx, start, &pos, "in", "I expected an 'in' for this 'for'"); expect_str(ctx, start, &pos, "in", "I expected an 'in' for this 'for'");
ast_t *iter = expect(ctx, start, &pos, parse_expr, "I expected an iterable value for this 'for'"); ast_t *iter = expect(ctx, start, &pos, parse_expr, "I expected an iterable value for this 'for'");
expect_str(ctx, start, &pos, ":", "I expected a ':' here");
match(&pos, "do"); // optional match(&pos, "do"); // optional
ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block, "I expected a body for this 'for'"); ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block, "I expected a body for this 'for'");
@ -919,6 +925,7 @@ PARSER(parse_for) {
ast_t *empty = NULL; ast_t *empty = NULL;
if (match_word(&else_start, "else") && get_indent(ctx->file, else_start) == starting_indent) { if (match_word(&else_start, "else") && get_indent(ctx->file, else_start) == starting_indent) {
pos = else_start; pos = else_start;
expect_str(ctx, start, &pos, ":", "I expected a ':' here");
empty = expect(ctx, pos, &pos, parse_opt_indented_block, "I expected a body for this 'else'"); empty = expect(ctx, pos, &pos, parse_opt_indented_block, "I expected a body for this 'else'");
} }
return NewAST(ctx->file, start, pos, For, .index=value ? index : NULL, .value=value ? value : index, .iter=iter, .body=body, .empty=empty); return NewAST(ctx->file, start, pos, For, .index=value ? index : NULL, .value=value ? value : index, .iter=iter, .body=body, .empty=empty);
@ -929,7 +936,7 @@ PARSER(parse_while) {
const char *start = pos; const char *start = pos;
if (!match_word(&pos, "while")) return NULL; if (!match_word(&pos, "while")) return NULL;
ast_t *condition = expect(ctx, start, &pos, parse_expr, "I don't see a viable condition for this 'while'"); ast_t *condition = expect(ctx, start, &pos, parse_expr, "I don't see a viable condition for this 'while'");
match(&pos, "do"); // optional expect_str(ctx, start, &pos, ":", "I expected a ':' here");
ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block, "I expected a body for this 'while'"); ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block, "I expected a body for this 'while'");
const char *tmp = pos; const char *tmp = pos;
whitespace(&tmp); whitespace(&tmp);
@ -1603,7 +1610,7 @@ PARSER(parse_file_body) {
} }
PARSER(parse_struct_def) { PARSER(parse_struct_def) {
// struct Foo(...) \n body // struct Foo(...) [: \n body]
const char *start = pos; const char *start = pos;
if (!match_word(&pos, "struct")) return NULL; if (!match_word(&pos, "struct")) return NULL;
@ -1636,13 +1643,15 @@ PARSER(parse_struct_def) {
expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this struct"); expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this struct");
const char *ns_pos = pos;
whitespace(&ns_pos);
int64_t ns_indent = get_indent(ctx->file, ns_pos);
ast_t *namespace = NULL; ast_t *namespace = NULL;
if (ns_indent > starting_indent) { if (match(&pos, ":")) {
pos = ns_pos; const char *ns_pos = pos;
namespace = optional(ctx, &pos, parse_namespace); whitespace(&ns_pos);
int64_t ns_indent = get_indent(ctx->file, ns_pos);
if (ns_indent > starting_indent) {
pos = ns_pos;
namespace = optional(ctx, &pos, parse_namespace);
}
} }
if (!namespace) if (!namespace)
namespace = NewAST(ctx->file, pos, pos, Block, .statements=NULL); namespace = NewAST(ctx->file, pos, pos, Block, .statements=NULL);
@ -1650,7 +1659,7 @@ PARSER(parse_struct_def) {
} }
ast_t *parse_enum_def(parse_ctx_t *ctx, const char *pos) { ast_t *parse_enum_def(parse_ctx_t *ctx, const char *pos) {
// tagged union: enum Foo[a, b(x:Int,y:Int)=5, ...] \n namespace // tagged union: enum Foo(a, b(x:Int,y:Int)=5, ...) [: \n namespace]
const char *start = pos; const char *start = pos;
if (!match_word(&pos, "enum")) return NULL; if (!match_word(&pos, "enum")) return NULL;
int64_t starting_indent = get_indent(ctx->file, pos); int64_t starting_indent = get_indent(ctx->file, pos);
@ -1713,13 +1722,15 @@ ast_t *parse_enum_def(parse_ctx_t *ctx, const char *pos) {
REVERSE_LIST(tags); REVERSE_LIST(tags);
const char *ns_pos = pos;
whitespace(&ns_pos);
int64_t ns_indent = get_indent(ctx->file, ns_pos);
ast_t *namespace = NULL; ast_t *namespace = NULL;
if (ns_indent > starting_indent) { if (match(&pos, ":")) {
pos = ns_pos; const char *ns_pos = pos;
namespace = optional(ctx, &pos, parse_namespace); whitespace(&ns_pos);
int64_t ns_indent = get_indent(ctx->file, ns_pos);
if (ns_indent > starting_indent) {
pos = ns_pos;
namespace = optional(ctx, &pos, parse_namespace);
}
} }
if (!namespace) if (!namespace)
namespace = NewAST(ctx->file, pos, pos, Block, .statements=NULL); namespace = NewAST(ctx->file, pos, pos, Block, .statements=NULL);
@ -1729,7 +1740,7 @@ ast_t *parse_enum_def(parse_ctx_t *ctx, const char *pos) {
PARSER(parse_lang_def) { PARSER(parse_lang_def) {
const char *start = pos; const char *start = pos;
// lang Name [namespace...] // lang Name: [namespace...]
if (!match_word(&pos, "lang")) return NULL; if (!match_word(&pos, "lang")) return NULL;
int64_t starting_indent = get_indent(ctx->file, pos); int64_t starting_indent = get_indent(ctx->file, pos);
spaces(&pos); spaces(&pos);
@ -1738,13 +1749,15 @@ PARSER(parse_lang_def) {
parser_err(ctx, start, pos, "I expected a name for this lang"); parser_err(ctx, start, pos, "I expected a name for this lang");
spaces(&pos); spaces(&pos);
const char *ns_pos = pos;
whitespace(&ns_pos);
int64_t ns_indent = get_indent(ctx->file, ns_pos);
ast_t *namespace = NULL; ast_t *namespace = NULL;
if (ns_indent > starting_indent) { if (match(&pos, ":")) {
pos = ns_pos; const char *ns_pos = pos;
namespace = optional(ctx, &pos, parse_namespace); whitespace(&ns_pos);
int64_t ns_indent = get_indent(ctx->file, ns_pos);
if (ns_indent > starting_indent) {
pos = ns_pos;
namespace = optional(ctx, &pos, parse_namespace);
}
} }
if (!namespace) if (!namespace)
namespace = NewAST(ctx->file, pos, pos, Block, .statements=NULL); namespace = NewAST(ctx->file, pos, pos, Block, .statements=NULL);
@ -1843,9 +1856,10 @@ PARSER(parse_func_def) {
type_ast_t *ret_type = NULL; type_ast_t *ret_type = NULL;
spaces(&pos); spaces(&pos);
if (match(&pos, "->") || match(&pos, ":")) if (match(&pos, "->"))
ret_type = optional(ctx, &pos, parse_type); ret_type = optional(ctx, &pos, parse_type);
expect_str(ctx, start, &pos, ":", "I expected a ':' here");
ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block, ast_t *body = expect(ctx, start, &pos, parse_opt_indented_block,
"This function needs a body block"); "This function needs a body block");
return NewAST(ctx->file, start, pos, FunctionDef, return NewAST(ctx->file, start, pos, FunctionDef,

View File

@ -1,9 +1,9 @@
func main() func main():
if yes if yes:
>> [:Num32] >> [:Num32]
= [] : [Num32] = [] : [Num32]
if yes if yes:
>> arr := [10, 20, 30] >> arr := [10, 20, 30]
= [10, 20, 30] = [10, 20, 30]
@ -16,18 +16,18 @@ func main()
= 3 = 3
sum := 0 sum := 0
for x in arr for x in arr:
sum += x sum += x
>> sum >> sum
= 60 = 60
str := "" str := ""
for i,x in arr for i,x in arr:
str ++= "({i},{x})" str ++= "({i},{x})"
>> str >> str
= "(1,10)(2,20)(3,30)" = "(1,10)(2,20)(3,30)"
if yes if yes:
>> arr := [10, 20] ++ [30, 40] >> arr := [10, 20] ++ [30, 40]
= [10, 20, 30, 40] = [10, 20, 30, 40]
@ -39,7 +39,7 @@ func main()
>> arr >> arr
= [10, 20, 30, 40, 50, 60, 70] = [10, 20, 30, 40, 50, 60, 70]
if yes if yes:
>> arr := [10, 20] >> arr := [10, 20]
>> copy := arr >> copy := arr
>> arr ++= 30 >> arr ++= 30
@ -48,7 +48,7 @@ func main()
>> copy >> copy
= [10, 20] = [10, 20]
if yes if yes:
>> [10*i for i in 5] >> [10*i for i in 5]
= [10, 20, 30, 40, 50] = [10, 20, 30, 40, 50]
@ -61,7 +61,7 @@ func main()
>> [x for x in y if x > 1 for y in [3, 4, 5] if y < 5] >> [x for x in y if x > 1 for y in [3, 4, 5] if y < 5]
= [2, 3, 2, 3, 4] = [2, 3, 2, 3, 4]
if yes if yes:
>> arr := @[10, 20] >> arr := @[10, 20]
>> copy := arr[] >> copy := arr[]
>> arr:insert(30) >> arr:insert(30)
@ -70,12 +70,12 @@ func main()
>> copy >> copy
= [10, 20] = [10, 20]
if yes if yes:
>> arr := [10, 20, 30] >> arr := [10, 20, 30]
>> arr:reversed() >> arr:reversed()
= [30, 20, 10] = [30, 20, 10]
if yes if yes:
>> nums := [10, -20, 30] >> nums := [10, -20, 30]
// Sorted function doesn't mutate original: // Sorted function doesn't mutate original:
>> nums:sorted() >> nums:sorted()
@ -96,20 +96,20 @@ func main()
>> ["A", "B", "C"]:sample(10, [1.0, 0.5, 0.0]) >> ["A", "B", "C"]:sample(10, [1.0, 0.5, 0.0])
if yes if yes:
>> heap := [Int.random(max=50) for _ in 10] >> heap := [Int.random(max=50) for _ in 10]
>> heap:heapify() >> heap:heapify()
>> heap >> heap
sorted := [:Int] sorted := [:Int]
while #heap > 0 while #heap > 0:
sorted:insert(heap:heap_pop()) sorted:insert(heap:heap_pop())
>> sorted == sorted:sorted() >> sorted == sorted:sorted()
= yes = yes
for _ in 10 for _ in 10:
heap:heap_push(Int.random(max=50)) heap:heap_push(Int.random(max=50))
>> heap >> heap
sorted = [:Int] sorted = [:Int]
while #heap > 0 while #heap > 0:
sorted:insert(heap:heap_pop()) sorted:insert(heap:heap_pop())
>> sorted == sorted:sorted() >> sorted == sorted:sorted()
= yes = yes

View File

@ -1,15 +1,15 @@
func ping(x:Int)->[Text] func ping(x:Int)->[Text]:
if x > 0 if x > 0:
return ["ping: {x}"] ++ pong(x-1) return ["ping: {x}"] ++ pong(x-1)
else else:
return ["ping: {x}"] return ["ping: {x}"]
func pong(x:Int)->[Text] func pong(x:Int)->[Text]:
if x > 0 if x > 0:
return ["pong: {x}"] ++ ping(x-1) return ["pong: {x}"] ++ ping(x-1)
else else:
return ["pong: {x}"] return ["pong: {x}"]
func main() func main():
>> ping(3) >> ping(3)
= ["ping: 3", "pong: 2", "ping: 1", "pong: 0"] = ["ping: 3", "pong: 2", "ping: 1", "pong: 0"]

View File

@ -1,6 +1,6 @@
enum Foo(Zero, One(x:Int), Two(x,y:Int)) enum Foo(Zero, One(x:Int), Two(x,y:Int))
func main() func main():
>> Foo.Zero >> Foo.Zero
= Foo.Zero = Foo.Zero
>> Foo.One(123) >> Foo.One(123)
@ -27,9 +27,9 @@ func main()
>> t[Foo.Zero] >> t[Foo.Zero]
= "missing" = "missing"
when x is o:One when x is o:One:
>> o.x >> o.x
= 123 = 123
else else:
fail("Oops") fail("Oops")

View File

@ -1,5 +1,5 @@
extern CORD_cat:func(a:Text, b:Text)->Text extern CORD_cat:func(a:Text, b:Text)->Text
func main() func main():
>> CORD_cat("hello ", "world") >> CORD_cat("hello ", "world")
= "hello world" = "hello world"

View File

@ -1,35 +1,35 @@
func all_nums(nums:[Int])->Text func all_nums(nums:[Int])->Text:
result := "" result := ""
for num in nums for num in nums:
result ++= "{num}," result ++= "{num},"
else else:
return "EMPTY" return "EMPTY"
return result return result
func labeled_nums(nums:[Int])->Text func labeled_nums(nums:[Int])->Text:
result := "" result := ""
for i,num in nums for i,num in nums:
result ++= "{i}:{num}," result ++= "{i}:{num},"
else else:
return "EMPTY" return "EMPTY"
return result return result
func table_str(t:{Text:Text})->Text func table_str(t:{Text:Text})->Text:
str := "" str := ""
for k,v in t for k,v in t:
str ++= "{k}:{v}," str ++= "{k}:{v},"
else return "EMPTY" else: return "EMPTY"
return str return str
func table_key_str(t:{Text:Text})->Text func table_key_str(t:{Text:Text})->Text:
str := "" str := ""
for k in t for k in t:
str ++= "{k}," str ++= "{k},"
else return "EMPTY" else: return "EMPTY"
return str return str
func main() func main():
>> all_nums([10,20,30]) >> all_nums([10,20,30])
= "10,20,30," = "10,20,30,"
>> all_nums([:Int]) >> all_nums([:Int])

View File

@ -1,10 +1,10 @@
func add(x:Int, y:Int)->Int func add(x:Int, y:Int)->Int:
return x + y return x + y
func cached_heap(x:Int; cached)->@Int func cached_heap(x:Int; cached)->@Int:
return @x return @x
func main() func main():
>> add(3, 5) >> add(3, 5)
= 8 = 8

View File

@ -1,4 +1,4 @@
func main() func main():
>> 2 + 3 >> 2 + 3
= 5 = 5
@ -27,7 +27,7 @@ func main()
= 1 = 1
nums := "" nums := ""
for x in 5 for x in 5:
nums ++= "{x}," nums ++= "{x},"
>> nums >> nums
= "1,2,3,4,5," = "1,2,3,4,5,"

View File

@ -1,13 +1,13 @@
func make_adder(x:Int)-> func(y:Int)->Int func make_adder(x:Int)-> func(y:Int)->Int:
return func(y:Int) x + y return func(y:Int) x + y
func suffix_fn(fn:func(t:Text)->Text, suffix:Text)->func(t:Text)->Text func suffix_fn(fn:func(t:Text)->Text, suffix:Text)->func(t:Text)->Text:
return func(t:Text) fn(t)++suffix return func(t:Text) fn(t)++suffix
func mul_func(n:Int, fn:func(x:Int)->Int)-> func(x:Int)->Int func mul_func(n:Int, fn:func(x:Int)->Int)-> func(x:Int)->Int:
return func(x:Int) n*fn(x) return func(x:Int) n*fn(x)
func main() func main():
>> add_one := func(x:Int) x + 1 >> add_one := func(x:Int) x + 1
>> add_one(10) >> add_one(10)
= 11 = 11

View File

@ -1,6 +1,6 @@
lang HTML lang HTML:
HEADER := $HTML{}"<!DOCTYPE HTML>" HEADER := $HTML{}"<!DOCTYPE HTML>"
func escape(t:Text)->HTML func escape(t:Text)->HTML:
t = t:replace("&", "&amp;") t = t:replace("&", "&amp;")
t = t:replace("<", "&lt;") t = t:replace("<", "&lt;")
t = t:replace(">", "&gt;") t = t:replace(">", "&gt;")
@ -8,13 +8,13 @@ lang HTML
t = t:replace("'", "&#39;") t = t:replace("'", "&#39;")
return HTML.from_unsafe_text(t) return HTML.from_unsafe_text(t)
func escape_int(i:Int)->HTML func escape_int(i:Int)->HTML:
return HTML.from_unsafe_text("{i}") return HTML.from_unsafe_text("{i}")
func paragraph(content:HTML)->HTML func paragraph(content:HTML)->HTML:
return $HTML{}"<p>{content}</p>" return $HTML{}"<p>{content}</p>"
func main() func main():
>> HTML.HEADER >> HTML.HEADER
= $HTML"<!DOCTYPE HTML>" = $HTML"<!DOCTYPE HTML>"

View File

@ -1,9 +1,9 @@
struct Foo(x:Int, y:Int) struct Foo(x:Int, y:Int):
func len(f:Foo)->Num func len(f:Foo)->Num:
return Num.sqrt(f.x*f.x + f.y*f.y) return Num.sqrt(f.x*f.x + f.y*f.y)
func main() func main():
>> 3 _min_ 5 >> 3 _min_ 5
= 3 = 3
>> 5 _min_ 3 >> 5 _min_ 3

View File

@ -1,4 +1,4 @@
func main() func main():
>> n := 1.5 >> n := 1.5
= 1.5 = 1.5

View File

@ -1,6 +1,6 @@
struct Foo(x,y:Int) struct Foo(x,y:Int)
func main() func main():
>> (+) [10, 20, 30] >> (+) [10, 20, 30]
= 60 = 60

View File

@ -4,7 +4,7 @@ struct Mixed(x:Int, text:Text)
struct LinkedList(x:Int, next=!LinkedList) struct LinkedList(x:Int, next=!LinkedList)
struct Password(text:Text; secret) struct Password(text:Text; secret)
func test_literals() func test_literals():
>> x := Pair(10, 20) >> x := Pair(10, 20)
= Pair(x=10, y=20) = Pair(x=10, y=20)
>> y := Pair(y=20, 10) >> y := Pair(y=20, 10)
@ -14,7 +14,7 @@ func test_literals()
>> x == Pair(-1, -2) >> x == Pair(-1, -2)
= no = no
func test_metamethods() func test_metamethods():
>> x := Pair(10, 20) >> x := Pair(10, 20)
>> y := Pair(100, 200) >> y := Pair(100, 200)
>> x == y >> x == y
@ -32,7 +32,7 @@ func test_metamethods()
>> t2[y] >> t2[y]
= "missing" = "missing"
func test_mixed() func test_mixed():
>> x := Mixed(10, "Hello") >> x := Mixed(10, "Hello")
>> y := Mixed(99, "Hello") >> y := Mixed(99, "Hello")
>> x == y >> x == y
@ -49,7 +49,7 @@ func test_mixed()
>> t[y] >> t[y]
= "missing" = "missing"
func main() func main():
test_literals() test_literals()
test_metamethods() test_metamethods()
test_mixed() test_mixed()

View File

@ -1,4 +1,4 @@
func main() func main():
>> t := {"one":1, "two":2; default=999} >> t := {"one":1, "two":2; default=999}
= {"one":1, "two":2; default=999} = {"one":1, "two":2; default=999}
@ -10,7 +10,7 @@ func main()
= 999 = 999
t_str := "" t_str := ""
for k,v in t for k,v in t:
t_str ++= "({k}:{v})" t_str ++= "({k}:{v})"
>> t_str >> t_str
= "(one:1)(two:2)" = "(one:1)(two:2)"
@ -45,7 +45,7 @@ func main()
= ?%{"one":1, "two":2; default=999} = ?%{"one":1, "two":2; default=999}
t2_str := "" t2_str := ""
for k,v in t2 for k,v in t2:
t2_str ++= "({k}:{v})" t2_str ++= "({k}:{v})"
>> t2_str >> t2_str
= "(three:3)" = "(three:3)"

View File

@ -1,4 +1,4 @@
func main() func main():
>> str := "Hello Amélie!" >> str := "Hello Amélie!"
>> str:upper() >> str:upper()
= "HELLO AMÉLIE!" = "HELLO AMÉLIE!"

View File

@ -1,9 +1,9 @@
imported := use ./use_import imported := use ./use_import
func asdf()->imported.ImportedType func asdf()->imported.ImportedType:
return imported.get_value() return imported.get_value()
func main() func main():
>> [:imported.ImportedType] >> [:imported.ImportedType]
>> asdf() >> asdf()
= ImportedType(name="Hello") = ImportedType(name="Hello")

View File

@ -1,7 +1,7 @@
struct ImportedType(name:Text) struct ImportedType(name:Text)
func get_value()->ImportedType func get_value()->ImportedType:
return ImportedType("Hello") return ImportedType("Hello")
func main() func main():
pass pass