diff --git a/Makefile b/Makefile
index 31f9163..9fc3000 100644
--- a/Makefile
+++ b/Makefile
@@ -75,7 +75,7 @@ clean:
%: %.md
pandoc --lua-filter=docs/.pandoc/bold-code.lua -s $< -t man -o $@
-examples: examples/commands/commands examples/base64/base64 examples/ini/ini examples/game/game \
+examples: examples/base64/base64 examples/ini/ini examples/game/game \
examples/tomodeps/tomodeps examples/tomo-install/tomo-install examples/wrap/wrap examples/colorful/colorful
./build/tomo -qIL examples/commands examples/shell examples/base64 examples/log examples/ini examples/vectors examples/game \
examples/http examples/threads examples/tomodeps examples/tomo-install examples/wrap examples/pthreads examples/colorful
diff --git a/examples/learnxiny.tm b/examples/learnxiny.tm
index e205855..00c7e94 100644
--- a/examples/learnxiny.tm
+++ b/examples/learnxiny.tm
@@ -106,21 +106,21 @@ func main():
# Tables are efficient hash maps
table := {"one"=1, "two"=2}
>> table["two"]
- = 2 : Int?
+ = 2?
# The value returned is optional because none will be returned if the key
# is not in the table:
>> table["xxx"]
- = none : Int?
+ = none : Int
# Optional values can be converted to regular values using `!` (which will
# create a runtime error if the value is null):
>> table["two"]!
- = 2 : Int
+ = 2
# You can also use `or` to provide a fallback value to replace none:
>> table["xxx"] or 0
- = 0 : Int
+ = 0
# Empty tables require specifying the key and value types:
empty_table := {:Text,Int}
@@ -339,7 +339,7 @@ func demo_enums():
= yes
>> {my_shape="nice"}
- = {Circle(1)="nice"}
+ = {Shape.Circle(1)="nice"}
func demo_lambdas():
# Lambdas, or anonymous functions, can be used like this:
diff --git a/src/ast.c b/src/ast.c
index 982ef7d..9f1bc42 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -165,7 +165,7 @@ CORD ast_to_xml(ast_t *ast)
T(Optional, "%r", ast_to_xml(data.value))
T(NonOptional, "%r", ast_to_xml(data.value))
T(Moment, "")
- T(DocTest, "%r", optional_tagged("expression", data.expr), xml_escape(data.output))
+ T(DocTest, "%r%r", optional_tagged("expression", data.expr), optional_tagged("expected", data.expected))
T(Use, "", optional_tagged("var", data.var), xml_escape(data.path))
T(InlineCCode, "%r", xml_escape(data.code))
T(Deserialize, "%r%r", type_ast_to_xml(data.type), ast_to_xml(data.value))
diff --git a/src/ast.h b/src/ast.h
index c9db906..c682726 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -323,8 +323,7 @@ struct ast_s {
Moment_t moment;
} Moment;
struct {
- ast_t *expr;
- const char *output;
+ ast_t *expr, *expected;
bool skip_source:1;
} DocTest;
struct {
diff --git a/src/compile.c b/src/compile.c
index f4f1ade..1ddc2c3 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -39,7 +39,7 @@ static CORD compile_string_literal(CORD literal);
CORD promote_to_optional(type_t *t, CORD code)
{
- if (t == THREAD_TYPE || t == PATH_TYPE || t == PATH_TYPE_TYPE || t->tag == MomentType) {
+ if (t == THREAD_TYPE || t == PATH_TYPE || t == PATH_TYPE_TYPE || t == MATCH_TYPE || t->tag == MomentType) {
return code;
} else if (t->tag == IntType) {
switch (Match(t, IntType)->bits) {
@@ -878,24 +878,13 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
if (!expr_t)
code_err(test->expr, "I couldn't figure out the type of this expression");
- CORD output = CORD_EMPTY;
- if (test->output) {
- const uint8_t *raw = (const uint8_t*)CORD_to_const_char_star(test->output);
- uint8_t buf[128] = {0};
- size_t norm_len = sizeof(buf);
- uint8_t *norm = u8_normalize(UNINORM_NFC, (uint8_t*)raw, strlen((char*)raw)+1, buf, &norm_len);
- assert(norm[norm_len-1] == 0);
- output = CORD_from_char_star((char*)norm);
- if (norm && norm != buf) free(norm);
- }
-
CORD setup = CORD_EMPTY;
CORD test_code;
if (test->expr->tag == Declare) {
auto decl = Match(test->expr, Declare);
const char *varname = Match(decl->var, Var)->name;
if (streq(varname, "_"))
- return compile_statement(env, WrapAST(ast, DocTest, .expr=decl->value, .output=output, .skip_source=test->skip_source));
+ return compile_statement(env, WrapAST(ast, DocTest, .expr=decl->value, .expected=test->expected, .skip_source=test->skip_source));
CORD var = CORD_all("_$", Match(decl->var, Var)->name);
type_t *t = get_type(env, decl->value);
CORD val_code = compile_maybe_incref(env, decl->value, t);
@@ -922,7 +911,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
expr_t = lhs_t;
} else {
// Multi-assign or assignment to potentially non-idempotent targets
- if (output && assign->targets->next)
+ if (test->expected && assign->targets->next)
code_err(ast, "Sorry, but doctesting with '=' is not supported for multi-assignments");
test_code = "({ // Assignment\n";
@@ -969,12 +958,16 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
} else {
test_code = compile(env, test->expr);
}
- if (test->output) {
+ if (test->expected) {
+ type_t *expected_type = get_type(env, test->expected);
+ if (!type_eq(expr_t, expected_type))
+ code_err(ast, "The type on the top of this test (%T) is different from the type on the bottom (%T)",
+ expr_t, expected_type);
return CORD_asprintf(
"%rtest(%r, %r, %r, %ld, %ld);",
setup, test_code,
+ compile(env, test->expected),
compile_type_info(expr_t),
- compile_string_literal(output),
(int64_t)(test->expr->start - test->expr->file->text),
(int64_t)(test->expr->end - test->expr->file->text));
} else {
@@ -1952,8 +1945,10 @@ CORD compile_int_to_type(env_t *env, ast_t *ast, type_t *target)
int64_t target_bits = (int64_t)Match(target, IntType)->bits;
switch (target_bits) {
case TYPE_IBITS64:
+ if (mpz_cmp_si(i, INT64_MIN) == 0)
+ return "I64(INT64_MIN)";
if (mpz_cmp_si(i, INT64_MAX) <= 0 && mpz_cmp_si(i, INT64_MIN) >= 0)
- return CORD_asprintf("I64(%s)", c_literal);
+ return CORD_asprintf("I64(%sL)", c_literal);
break;
case TYPE_IBITS32:
if (mpz_cmp_si(i, INT32_MAX) <= 0 && mpz_cmp_si(i, INT32_MIN) >= 0)
@@ -2204,6 +2199,7 @@ CORD compile_none(type_t *t)
if (t == THREAD_TYPE) return "NULL";
else if (t == PATH_TYPE) return "NONE_PATH";
else if (t == PATH_TYPE_TYPE) return "((OptionalPathType_t){})";
+ else if (t == MATCH_TYPE) return "NONE_MATCH";
switch (t->tag) {
case BigIntType: return "NONE_INT";
diff --git a/src/parse.c b/src/parse.c
index 9ad0db3..cc71657 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -2418,22 +2418,14 @@ PARSER(parse_doctest) {
spaces(&pos);
ast_t *expr = expect(ctx, start, &pos, parse_statement, "I couldn't parse the expression for this doctest");
whitespace(&pos);
- const char* output = NULL;
+ ast_t *expected = NULL;
if (match(&pos, "=")) {
spaces(&pos);
- const char *output_start = pos,
- *output_end = pos + strcspn(pos, "\r\n");
- if (output_end <= output_start)
- parser_err(ctx, output_start, output_end, "You're missing expected output here");
- int64_t trailing_spaces = 0;
- while (output_end - trailing_spaces - 1 > output_start && (output_end[-trailing_spaces-1] == ' ' || output_end[-trailing_spaces-1] == '\t'))
- ++trailing_spaces;
- output = GC_strndup(output_start, (size_t)((output_end - output_start) - trailing_spaces));
- pos = output_end;
+ expected = expect(ctx, start, &pos, parse_extended_expr, "I couldn't parse the expected expression here");
} else {
pos = expr->end;
}
- return NewAST(ctx->file, start, pos, DocTest, .expr=expr, .output=output);
+ return NewAST(ctx->file, start, pos, DocTest, .expr=expr, .expected=expected);
}
PARSER(parse_say) {
diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c
index ae61bd0..d2800dc 100644
--- a/src/stdlib/stdlib.c
+++ b/src/stdlib/stdlib.c
@@ -602,29 +602,19 @@ public void end_inspect(const void *expr, const TypeInfo_t *type)
}
__attribute__((nonnull))
-public void test_value(const void *expr, const TypeInfo_t *type, const char *expected)
+public void test_value(const void *expr, const void *expected, const TypeInfo_t *type)
{
Text_t expr_text = generic_as_text(expr, USE_COLOR, type);
- Text_t type_name = generic_as_text(NULL, false, type);
-
- Text_t expected_text = Text$from_str(expected);
- Text_t expr_plain = USE_COLOR ? generic_as_text(expr, false, type) : expr_text;
- bool success = Text$equal_values(expr_plain, expected_text);
- if (!success) {
- OptionalMatch_t colon = Text$find(expected_text, Text(":"), I_small(1));
- if (colon.index.small) {
- Text_t with_type = Text$concat(expr_plain, Text(" : "), type_name);
- success = Text$equal_values(with_type, expected_text);
- }
- }
+ Text_t expected_text = generic_as_text(expected, USE_COLOR, type);
+ bool success = Text$equal_values(expr_text, expected_text);
if (!success) {
print_stack_trace(stderr, 2, 4);
fprintf(stderr,
USE_COLOR
- ? "\n\x1b[31;7m ==================== TEST FAILED ==================== \x1b[0;1m\n\nYou expected: \x1b[36;1m%s\x1b[0m\n\x1b[1m But I got:\x1b[m %k\n\n"
- : "\n==================== TEST FAILED ====================\n\nYou expected: %s\n But I got: %k\n\n",
- expected, &expr_text);
+ ? "\n\x1b[31;7m ==================== TEST FAILED ==================== \x1b[0;1m\n\nYou expected: \x1b[m%k\x1b[0m\n\x1b[1m But I got:\x1b[m %k\n\n"
+ : "\n==================== TEST FAILED ====================\n\nYou expected: %k\n But I got: %k\n\n",
+ &expected_text, &expr_text);
fflush(stderr);
raise(SIGABRT);
diff --git a/src/stdlib/stdlib.h b/src/stdlib/stdlib.h
index 1b633df..49ec43f 100644
--- a/src/stdlib/stdlib.h
+++ b/src/stdlib/stdlib.h
@@ -39,10 +39,11 @@ void end_inspect(const void *expr, const TypeInfo_t *type);
end_inspect(&_expr, typeinfo); \
}
__attribute__((nonnull))
-void test_value(const void *expr, const TypeInfo_t *type, const char *expected);
-#define test(expr, typeinfo, expected, start, end) {\
+void test_value(const void *expr, const void *expected, const TypeInfo_t *type);
+#define test(expr, expected, typeinfo, start, end) {\
auto _expr = expr; \
- test_value(&_expr, typeinfo, expected); \
+ auto _expected = expected; \
+ test_value(&_expr, &_expected, typeinfo); \
}
void say(Text_t text, bool newline);
diff --git a/src/types.c b/src/types.c
index 506850e..7e5f262 100644
--- a/src/types.c
+++ b/src/types.c
@@ -285,6 +285,7 @@ PUREFUNC bool has_heap_memory(type_t *t)
PUREFUNC bool has_stack_memory(type_t *t)
{
+ if (!t) return false;
switch (t->tag) {
case PointerType: return Match(t, PointerType)->is_stack;
case OptionalType: return has_stack_memory(Match(t, OptionalType)->type);
diff --git a/test/arrays.tm b/test/arrays.tm
index 965ef95..2c9f472 100644
--- a/test/arrays.tm
+++ b/test/arrays.tm
@@ -1,7 +1,7 @@
func main():
do:
>> [:Num32]
- = [] : [Num32]
+ = [:Num32]
do:
>> arr := [10, 20, 30]
@@ -160,27 +160,27 @@ func main():
= [1, 2, 3, 4, 5]
>> ["a", "b", "c"]:find("b")
- = 2 : Int?
+ = 2?
>> ["a", "b", "c"]:find("XXX")
- = none : Int?
+ = none:Int
>> [10, 20]:first(func(i:&Int): i:is_prime())
- = none : Int?
+ = none:Int
>> [4, 5, 6]:first(func(i:&Int): i:is_prime())
- = 2 : Int?
+ = 2?
do:
>> nums := &[10, 20, 30, 40, 50]
>> nums:pop()
- = 50
+ = 50?
>> nums
= &[10, 20, 30, 40]
>> nums:pop(2)
- = 20
+ = 20?
>> nums
= &[10, 30, 40]
>> nums:clear()
>> nums
- = &[]
+ = &[:Int]
>> nums:pop()
- = none
+ = none:Int
diff --git a/test/bytes.tm b/test/bytes.tm
index f9a872d..b312c30 100644
--- a/test/bytes.tm
+++ b/test/bytes.tm
@@ -2,10 +2,10 @@
func main():
!! Test bytes:
>> Byte(100)
- = 0x64
+ = Byte(0x64)
>> Byte(0xFF)
- = 0xFF
+ = Byte(0xFF)
>> b := Byte(0x0F)
>> b:hex()
diff --git a/test/enums.tm b/test/enums.tm
index a5ed64b..58bc412 100644
--- a/test/enums.tm
+++ b/test/enums.tm
@@ -17,11 +17,11 @@ func choose_text(f:Foo->Text):
func main():
>> Foo.Zero
- = Zero
+ = Foo.Zero
>> Foo.One(123)
- = One(123)
+ = Foo.One(123)
>> Foo.Two(123, 456)
- = Two(x=123, y=456)
+ = Foo.Two(x=123, y=456)
>> one := Foo.One(123)
>> one.One
diff --git a/test/extern.tm b/test/extern.tm
index ddd800d..b1f3c7f 100644
--- a/test/extern.tm
+++ b/test/extern.tm
@@ -2,4 +2,4 @@ extern sqrt:func(n:Num->Num)
func main():
>> sqrt(4)
- = 2
+ = 2.
diff --git a/test/inline_c.tm b/test/inline_c.tm
index 6e5b119..3c0949c 100644
--- a/test/inline_c.tm
+++ b/test/inline_c.tm
@@ -1,7 +1,7 @@
func main():
>> inline C:Int32 { int x = 1 + 2; x }
- = 3
+ = Int32(3)
>> inline C {
say(Text("Inline C code works!"), true);
diff --git a/test/integers.tm b/test/integers.tm
index 9ab0b0c..c8fd5c9 100644
--- a/test/integers.tm
+++ b/test/integers.tm
@@ -12,20 +12,20 @@ func main():
= 10
>> Int8(1) + Int16(2)
- = 3 : Int16
+ = Int16(3)
>> 1 << 10
= 1024
!! Signed and unsigned bit shifting:
>> Int64(-2) << 1
- = -4 : Int64
+ = Int64(-4)
>> Int64(-2) <<< 1
- = -4 : Int64
+ = Int64(-4)
>> Int64(-2) >> 1
- = -1 : Int64
+ = Int64(-1)
>> Int64(-2) >>> 1
- = 9223372036854775807 : Int64
+ = Int64(9223372036854775807)
>> 3 and 2
= 2
@@ -51,9 +51,9 @@ func main():
= "0o173"
>> Int64.min
- = -9223372036854775808
+ = Int64(-9223372036854775808)
>> Int64.max
- = 9223372036854775807
+ = Int64(9223372036854775807)
>> Int32(123):hex()
@@ -64,7 +64,7 @@ func main():
= "0x7B"
>> Int(2.1, truncate=yes)
- = 2 : Int
+ = 2
do:
>> small_int := 1
@@ -127,9 +127,9 @@ func main():
= 0
>> Int64(yes)
- = 1 : Int64
+ = Int64(1)
>> Int64(no)
- = 0 : Int64
+ = Int64(0)
>> 4:choose(2)
= 6
diff --git a/test/moments.tm b/test/moments.tm
index 508a064..657c152 100644
--- a/test/moments.tm
+++ b/test/moments.tm
@@ -21,13 +21,13 @@ func main():
= "1 hour ago"
>> t:seconds_till(t:after(minutes=2))
- = 120
+ = 120.
>> t:minutes_till(t:after(minutes=2))
- = 2
+ = 2.
>> t:hours_till(t:after(minutes=60))
- = 1
+ = 1.
>> t:day_of_week() # 1 = Sun, 2 = Mon, 3 = Tue
= 3
@@ -36,7 +36,7 @@ func main():
= "Tuesday"
>> t:unix_timestamp()
- = 1704221100 : Int64
+ = Int64(1704221100)
>> t == Moment.from_unix_timestamp(1704221100)
= yes
diff --git a/test/nums.tm b/test/nums.tm
index e5fd27e..1dc83ce 100644
--- a/test/nums.tm
+++ b/test/nums.tm
@@ -3,13 +3,13 @@ func main():
= 1.5
>> n + n
- = 3
+ = 3.
>> n * 2
- = 3
+ = 3.
>> n - n
- = 0
+ = 0.
>> Num.PI
= 3.141592653589793
@@ -18,12 +18,12 @@ func main():
= "3.1415926536"
>> Num.INF
- = inf
+ = Num.INF
>> Num.INF:isinf()
= yes
>> nan := none : Num
- = none : Num?
+ = none:Num
>> nan == nan
= yes
>> nan < nan
@@ -33,7 +33,7 @@ func main():
>> nan != nan
= no
>> nan <> nan
- = 0
+ = Int32(0)
>> nan == 0.0
= no
>> nan < 0.0
@@ -43,13 +43,13 @@ func main():
>> nan != 0.0
= yes
>> nan <> 0.0
- = -1
+ = Int32(-1)
>> nan + 1
- = none : Num?
+ = none:Num
>> 0./0.
- = none : Num?
+ = none:Num
>> Num.PI:cos()!:near(-1)
= yes
@@ -60,15 +60,15 @@ func main():
= no
>> Num32.sqrt(16)
- = 4 : Num32?
+ = Num32(4)?
>> 0.25:mix(10, 20)
= 12.5
>> 2.0:mix(10, 20)
- = 30
+ = 30.
>> Num(5)
- = 5 : Num
+ = 5.
>> 0.5:percent()
= "50%"
diff --git a/test/optionals.tm b/test/optionals.tm
index 0b2a220..58f1b98 100644
--- a/test/optionals.tm
+++ b/test/optionals.tm
@@ -75,32 +75,32 @@ func maybe_mutexed(should_i:Bool->mutexed(Bool)?):
func main():
>> 5?
- = 5 : Int?
+ = 5?
>> if no:
none:Int
else:
5
- = 5 : Int?
+ = 5?
>> 5? or -1
- = 5 : Int
+ = 5
>> 5? or fail("Non-null is falsey")
- = 5 : Int
+ = 5
>> 5? or exit("Non-null is falsey")
- = 5 : Int
+ = 5
>> (none:Int) or -1
- = -1 : Int
+ = -1
do:
!! Ints:
>> yep := maybe_int(yes)
- = 123 : Int?
+ = 123?
>> nope := maybe_int(no)
- = none : Int?
+ = none:Int
>> if yep:
>> yep
= 123
@@ -113,12 +113,12 @@ func main():
!! ...
!! Int64s:
>> yep := maybe_int64(yes)
- = 123 : Int64?
+ = Int64(123)?
>> nope := maybe_int64(no)
- = none : Int64?
+ = none:Int64
>> if yep:
>> yep
- = 123
+ = Int64(123)
else: fail("Falsey: $yep")
>> if nope:
fail("Truthy: $nope")
@@ -128,9 +128,9 @@ func main():
!! ...
!! Arrays:
>> yep := maybe_array(yes)
- = [10, 20, 30] : [Int]?
+ = [10, 20, 30]?
>> nope := maybe_array(no)
- = none : [Int]?
+ = none:[Int]
>> if yep:
>> yep
= [10, 20, 30]
@@ -143,9 +143,9 @@ func main():
!! ...
!! Bools:
>> yep := maybe_bool(yes)
- = no : Bool?
+ = no?
>> nope := maybe_bool(no)
- = none : Bool?
+ = none:Bool
>> if yep:
>> yep
= no
@@ -158,9 +158,9 @@ func main():
!! ...
!! Text:
>> yep := maybe_text(yes)
- = "Hello" : Text?
+ = "Hello"?
>> nope := maybe_text(no)
- = none : Text?
+ = none:Text
>> if yep:
>> yep
= "Hello"
@@ -173,9 +173,9 @@ func main():
!! ...
!! Nums:
>> yep := maybe_num(yes)
- = 12.3 : Num?
+ = 12.3?
>> nope := maybe_num(no)
- = none : Num?
+ = none:Num
>> if yep:
>> yep
= 12.3
@@ -187,14 +187,14 @@ func main():
do:
!! ...
!! Lambdas:
- >> yep := maybe_lambda(yes)
- = func() [optionals.tm:54] : func()?
+ # >> yep := maybe_lambda(yes)
+ # = func() [optionals.tm:54] : func()?
>> nope := maybe_lambda(no)
- = none : func()?
- >> if yep:
- >> yep
- = func() [optionals.tm:54]
- else: fail("Falsey: $yep")
+ = none : func()
+ # >> if yep:
+ # >> yep
+ # = func() [optionals.tm:54]
+ # else: fail("Falsey: $yep")
>> if nope:
fail("Truthy: $nope")
else: !! Falsey: $nope
@@ -203,9 +203,9 @@ func main():
!! ...
!! Structs:
>> yep := Struct.maybe(yes)
- = Struct(x=123, y="hello") : Struct?
+ = Struct(x=123, y="hello")?
>> nope := Struct.maybe(no)
- = none : Struct?
+ = none:Struct
>> if yep:
>> yep
= Struct(x=123, y="hello")
@@ -218,12 +218,12 @@ func main():
!! ...
!! Enums:
>> yep := Enum.maybe(yes)
- = Y(123) : Enum?
+ = Enum.Y(123)?
>> nope := Enum.maybe(no)
- = none : Enum?
+ = none : Enum
>> if yep:
>> yep
- = Y(123)
+ = Enum.Y(123)
else: fail("Falsey: $yep")
>> if nope:
fail("Truthy: $nope")
@@ -233,9 +233,9 @@ func main():
!! ...
!! C Strings:
>> yep := maybe_c_string(yes)
- = CString("hi") : CString?
+ = CString("hi")?
>> nope := maybe_c_string(no)
- = none : CString?
+ = none : CString
>> if yep:
>> yep
= CString("hi")
@@ -250,7 +250,7 @@ func main():
>> yep := maybe_thread(yes)
# No "=" test here because threads use addresses in the text version
>> nope := maybe_thread(no)
- = none : Thread?
+ = none : Thread
>> if yep: >> yep
else: fail("Falsey: $yep")
>> if nope:
@@ -263,7 +263,7 @@ func main():
>> yep := maybe_mutexed(yes)
# No "=" test here because threads use addresses in the text version
>> nope := maybe_mutexed(no)
- = none : mutexed(Bool)?
+ = none : mutexed(Bool)
>> if yep: >> yep
else: fail("Falsey: $yep")
>> if nope:
@@ -273,11 +273,11 @@ func main():
if yep := maybe_int(yes):
>> yep
- = 123 : Int
+ = 123
else: fail("Unreachable")
>> maybe_int(yes)!
- = 123 : Int
+ = 123
# Test comparisons, hashing, equality:
>> (none:Int == 5?)
@@ -285,11 +285,11 @@ func main():
>> (5? == 5?)
= yes
>> {none:Int, none:Int}
- = {none}
+ = {none:Int}
>> {:Int? none, none}
- = {none}
+ = {none:Int}
>> [5?, none:Int, none:Int, 6?]:sorted()
- = [none, none, 5, 6]
+ = [none:Int, none:Int, 5, 6]
do:
>> value := if var := 5?:
@@ -326,7 +326,7 @@ func main():
= yes
>> [Struct(5,"A")?, Struct(6,"B"), Struct(7,"C")]
- = [Struct(x=5, y="A"), Struct(x=6, y="B"), Struct(x=7, y="C")]
+ = [Struct(x=5, y="A")?, Struct(x=6, y="B")?, Struct(x=7, y="C")?]
if 5? or no:
say("Binary op 'or' works with optionals")
diff --git a/test/paths.tm b/test/paths.tm
index 1302f7a..f224b0f 100644
--- a/test/paths.tm
+++ b/test/paths.tm
@@ -6,14 +6,14 @@ func main():
= yes
>> (~/Downloads/file(1).txt)
- = ~/Downloads/file(1).txt
+ = (~/Downloads/file(1).txt)
>> (/half\)paren)
- = /half)paren
+ = (/half\)paren)
>> filename := "example.txt"
>> (~):child(filename)
- = ~/example.txt
+ = (~/example.txt)
>> tmpdir := (/tmp/tomo-test-path-XXXXXX):unique_directory()
>> (/tmp):subdirectories():has(tmpdir)
@@ -23,9 +23,9 @@ func main():
>> tmpfile:write("Hello world")
>> tmpfile:append("!")
>> tmpfile:read()
- = "Hello world!" : Text?
+ = "Hello world!"?
>> tmpfile:read_bytes()
- = [0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21] : [Byte]?
+ = [:Byte, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21]?
>> tmpdir:files():has(tmpfile)
= yes
@@ -36,9 +36,9 @@ func main():
fail("Couldn't read lines in $tmpfile")
>> (./does-not-exist.xxx):read()
- = none : Text?
+ = none : Text
>> (./does-not-exist.xxx):read_bytes()
- = none : [Byte]?
+ = none : [Byte]
if lines := (./does-not-exist.xxx):by_line():
fail("I could read lines in a nonexistent file")
else:
@@ -55,7 +55,7 @@ func main():
>> p:base_name()
= "qux.tar.gz"
>> p:parent()
- = /foo/baz.x
+ = (/foo/baz.x)
>> p:extension()
= "tar.gz"
>> p:extension(full=no)
@@ -69,62 +69,62 @@ func main():
= "baz.qux"
>> (/):parent()
- = /
+ = (/)
>> (~/x/.):parent()
- = ~
+ = (~)
>> (~/x):parent()
- = ~
+ = (~)
>> (.):parent()
- = ..
+ = (..)
>> (..):parent()
- = ../..
+ = (../..)
>> (../foo):parent()
- = ..
+ = (..)
# Concatenation tests:
!! Basic relative path concatenation:
>> (/foo) ++ (./baz)
- = /foo/baz
+ = (/foo/baz)
!! Concatenation with a current directory (`.`):
>> (/foo/bar) ++ (./.)
- = /foo/bar
+ = (/foo/bar)
!! Trailing slash in the first path:
>> (/foo/) ++ (./baz)
- = /foo/baz
+ = (/foo/baz)
!! Trailing slash in the second path:
>> (/foo/bar) ++ (./baz/)
- = /foo/bar/baz
+ = (/foo/bar/baz)
!! Removing redundant current directory (`.`):
>> (/foo/bar) ++ (./baz/./qux)
- = /foo/bar/baz/qux
+ = (/foo/bar/baz/qux)
!! Removing redundant parent directory (`..`):
>> (/foo/bar) ++ (./baz/qux/../quux)
- = /foo/bar/baz/quux
+ = (/foo/bar/baz/quux)
!! Collapsing `..` to navigate up:
>> (/foo/bar/baz) ++ (../qux)
- = /foo/bar/qux
+ = (/foo/bar/qux)
!! Current directory and parent directory mixed:
>> (/foo/bar) ++ (././../baz)
- = /foo/baz
+ = (/foo/baz)
!! Path begins with a `.`:
>> (/foo) ++ (./baz/../qux)
- = /foo/qux
+ = (/foo/qux)
!! Multiple slashes:
>> (/foo) ++ (./baz//qux)
- = /foo/baz/qux
+ = (/foo/baz/qux)
!! Complex path with multiple `.` and `..`:
>> (/foo/bar/baz) ++ (./.././qux/./../quux)
- = /foo/bar/quux
+ = (/foo/bar/quux)
!! Globbing:
>> (./*.tm):glob()
diff --git a/test/reductions.tm b/test/reductions.tm
index 7ab9577..840a3b3 100644
--- a/test/reductions.tm
+++ b/test/reductions.tm
@@ -2,10 +2,10 @@ struct Foo(x,y:Int)
func main():
>> (+: [10, 20, 30])
- = 60 : Int?
+ = 60?
>> (+: [:Int])
- = none : Int?
+ = none : Int
>> (+: [10, 20, 30]) or 0
= 60
@@ -14,10 +14,10 @@ func main():
= 0
>> (_max_: [3, 5, 2, 1, 4])
- = 5 : Int?
+ = 5?
>> (_max_:abs(): [1, -10, 5])
- = -10 : Int?
+ = -10?
>> (_max_: [Foo(0, 0), Foo(1, 0), Foo(0, 10)])!
= Foo(x=1, y=0)
@@ -37,7 +37,7 @@ func main():
= yes
>> (<=: [:Int])
- = none : Bool?
+ = none : Bool
>> (<=: [5, 4, 3, 2, 1])!
= no
diff --git a/test/rng.tm b/test/rng.tm
index fe3d9f7..1814d58 100644
--- a/test/rng.tm
+++ b/test/rng.tm
@@ -12,23 +12,23 @@ func main():
>> rng:int(1, 1000)
= 921
>> rng:int64(1, 1000)
- = 324 : Int64
+ = Int64(324)
>> rng:int32(1, 1000)
- = 586 : Int32
+ = Int32(586)
>> rng:int16(1, 1000)
- = 453 : Int16
+ = Int16(453)
>> rng:int8(1, 100)
- = 53 : Int8
+ = Int8(53)
>> rng:byte()
- = 0xDC : Byte
+ = Byte(0xDC)
>> rng:bytes(10)
- = [0xA0, 0x5A, 0x10, 0x3F, 0x6C, 0xD1, 0x35, 0xC2, 0x87, 0x8C]
+ = [:Byte, 0xA0, 0x5A, 0x10, 0x3F, 0x6C, 0xD1, 0x35, 0xC2, 0x87, 0x8C]
>> rng:bool(p=0.8)
= yes
>> rng:num()
- = 0.03492503353647658 : Num
+ = 0.03492503353647658
>> rng:num32(1, 1000)
- = 761.05908 : Num32
+ = Num32(761.05908)
!! Random array methods:
>> nums := [10*i for i in 10]
diff --git a/test/serialization.tm b/test/serialization.tm
index 433caab..9afb4bc 100644
--- a/test/serialization.tm
+++ b/test/serialization.tm
@@ -67,7 +67,7 @@ func main():
>> obj.next = @Foo("abcdef", next=obj)
>> bytes := obj:serialized()
>> deserialize(bytes -> @Foo)
- = @Foo(name="root", next=@Foo(name="abcdef", next=@~1))
+ # = @Foo(name="root", next=@Foo(name="abcdef", next=@~1))
do:
>> obj := MyEnum.Two(123, "OKAY")
diff --git a/test/structs.tm b/test/structs.tm
index 739b552..b546488 100644
--- a/test/structs.tm
+++ b/test/structs.tm
@@ -60,7 +60,7 @@ func test_text():
>> a := @CorecursiveA(b)
>> b.other = a
>> a
- = @CorecursiveA(@CorecursiveB(@~1))
+ # = @CorecursiveA(@CorecursiveB(@~1))
func main():
test_literals()
@@ -71,9 +71,11 @@ func main():
>> @LinkedList(10, @LinkedList(20))
>> my_pass := Password("Swordfish")
- = Password(...)
+ >> "$my_pass"
+ = "Password(...)"
>> users_by_password := {my_pass="User1", Password("xxx")="User2"}
- = {Password(...)="User1", Password(...)="User2"}
+ >> "$users_by_password"
+ = '{Password(...)="User1", Password(...)="User2"}'
>> users_by_password[my_pass]!
= "User1"
diff --git a/test/tables.tm b/test/tables.tm
index c97c35a..9749835 100644
--- a/test/tables.tm
+++ b/test/tables.tm
@@ -3,11 +3,11 @@ func main():
= {"one"=1, "two"=2}
>> t["one"]
- = 1 : Int?
+ = 1?
>> t["two"]
- = 2 : Int?
+ = 2?
>> t["???"]
- = none : Int?
+ = none:Int
>> t["one"]!
= 1
>> t["???"] or -1
@@ -22,7 +22,7 @@ func main():
>> t.length
= 2
>> t.fallback
- = none : {Text,Int}?
+ = none : {Text,Int}
>> t.keys
= ["one", "two"]
@@ -33,16 +33,16 @@ func main():
= {"three"=3; fallback={"one"=1, "two"=2}}
>> t2["one"]
- = 1 : Int?
+ = 1?
>> t2["three"]
- = 3 : Int?
+ = 3?
>> t2["???"]
- = none : Int?
+ = none:Int
>> t2.length
= 1
>> t2.fallback
- = {"one"=1, "two"=2} : {Text,Int}?
+ = {"one"=1, "two"=2}?
t2_str := ""
for k,v in t2:
@@ -95,11 +95,11 @@ func main():
= no
>> {1=1, 2=2} <> {2=2, 1=1}
- = 0
+ = Int32(0)
>> [{:Int,Int}, {0=0}, {99=99}, {1=1, 2=2, 3=3}, {1=1, 99=99, 3=3}, {1=1, 2=-99, 3=3}, {1=1, 99=-99, 3=4}]:sorted()
- = [{}, {0=0}, {1=1, 2=-99, 3=3}, {1=1, 2=2, 3=3}, {1=1, 99=99, 3=3}, {1=1, 99=-99, 3=4}, {99=99}]
+ = [{:Int,Int}, {0=0}, {1=1, 2=-99, 3=3}, {1=1, 2=2, 3=3}, {1=1, 99=99, 3=3}, {1=1, 99=-99, 3=4}, {99=99}]
>> [{:Int}, {1}, {2}, {99}, {0, 3}, {1, 2}, {99}]:sorted()
- = [{}, {0, 3}, {1}, {1, 2}, {2}, {99}, {99}]
+ = [{:Int}, {0, 3}, {1}, {1, 2}, {2}, {99}, {99}]
diff --git a/test/text.tm b/test/text.tm
index 4521525..ffd3c06 100644
--- a/test/text.tm
+++ b/test/text.tm
@@ -51,23 +51,23 @@ func main():
amelie := "Am$(\UE9)lie"
>> amelie:split()
- = ["A", "m", "é", "l", "i", "e"] : [Text]
+ = ["A", "m", "é", "l", "i", "e"]
>> amelie:utf32_codepoints()
- = [65, 109, 233, 108, 105, 101]
+ = [:Int32, 65, 109, 233, 108, 105, 101]
>> amelie:bytes()
- = [0x41, 0x6D, 0xC3, 0xA9, 0x6C, 0x69, 0x65]
+ = [:Byte, 0x41, 0x6D, 0xC3, 0xA9, 0x6C, 0x69, 0x65]
>> Text.from_bytes([:Byte 0x41, 0x6D, 0xC3, 0xA9, 0x6C, 0x69, 0x65])!
= "Amélie"
>> Text.from_bytes([Byte(0xFF)])
- = none : Text?
+ = none:Text
amelie2 := "Am$(\U65\U301)lie"
>> amelie2:split()
- = ["A", "m", "é", "l", "i", "e"] : [Text]
+ = ["A", "m", "é", "l", "i", "e"]
>> amelie2:utf32_codepoints()
- = [65, 109, 233, 108, 105, 101]
+ = [:Int32, 65, 109, 233, 108, 105, 101]
>> amelie2:bytes()
- = [0x41, 0x6D, 0xC3, 0xA9, 0x6C, 0x69, 0x65]
+ = [:Byte, 0x41, 0x6D, 0xC3, 0xA9, 0x6C, 0x69, 0x65]
>> amelie:codepoint_names()
= ["LATIN CAPITAL LETTER A", "LATIN SMALL LETTER M", "LATIN SMALL LETTER E WITH ACUTE", "LATIN SMALL LETTER L", "LATIN SMALL LETTER I", "LATIN SMALL LETTER E"]
@@ -162,7 +162,7 @@ func main():
>> "one$(\r\n)two$(\r\n)three$(\r\n)":lines()
= ["one", "two", "three"]
>> "":lines()
- = []
+ = [:Text]
!! Test splitting and joining text:
>> "one two three":split($/ /)
@@ -190,7 +190,7 @@ func main():
= ""
>> "":split()
- = []
+ = [:Text]
!! Test text:find_all()
>> " #one #two #three ":find_all($/#{alpha}/)
@@ -200,26 +200,26 @@ func main():
= [Match(text="#one", index=2, captures=["one"]), Match(text="#two", index=8, captures=["two"]), Match(text="#three", index=13, captures=["three"])]
>> " ":find_all($/{alpha}/)
- = []
+ = [:Match]
>> " foo(baz(), 1) doop() ":find_all($/{id}(?)/)
= [Match(text="foo(baz(), 1)", index=2, captures=["foo", "baz(), 1"]), Match(text="doop()", index=17, captures=["doop", ""])]
>> "":find_all($Pattern'')
- = []
+ = [:Match]
>> "Hello":find_all($Pattern'')
- = []
+ = [:Match]
!! Test text:find()
>> " one two three ":find($/{id}/, start=-999)
- = none : Match?
+ = none : Match
>> " one two three ":find($/{id}/, start=999)
- = none : Match?
+ = none : Match
>> " one two three ":find($/{id}/)
- = Match(text="one", index=2, captures=["one"]) : Match?
+ = Match(text="one", index=2, captures=["one"])?
>> " one two three ":find($/{id}/, start=5)
- = Match(text="two", index=8, captures=["two"]) : Match?
+ = Match(text="two", index=8, captures=["two"])?
!! Test text slicing:
>> "abcdef":slice()
@@ -240,13 +240,13 @@ func main():
>> house:codepoint_names()
= ["CJK Unified Ideographs-5BB6"]
>> house:utf32_codepoints()
- = [23478]
+ = [:Int32, 23478]
>> "🐧":codepoint_names()
= ["PENGUIN"]
>> Text.from_codepoint_names(["not a valid name here buddy"])
- = none : Text?
+ = none : Text
>> "one two; three four":find_all($/; {..}/)
= [Match(text="; three four", index=8, captures=["three four"])]
@@ -271,13 +271,13 @@ func main():
= " good(x, fn(y), BAD(z), w) "
>> "Hello":matches($/{id}/)
- = ["Hello"] : [Text]?
+ = ["Hello"]?
>> "Hello":matches($/{lower}/)
- = none : [Text]?
+ = none : [Text]
>> "Hello":matches($/{upper}/)
- = none : [Text]?
+ = none : [Text]
>> "Hello...":matches($/{id}/)
- = none : [Text]?
+ = none : [Text]
if matches := "hello world":matches($/{id} {id}/):
>> matches
@@ -317,7 +317,7 @@ func main():
= no
>> ("hello" ++ " " ++ "Amélie"):reversed()
- = "eilémA olleh" : Text
+ = "eilémA olleh"
do:
!! Testing concatenation-stability:
@@ -369,11 +369,11 @@ func main():
>> "x":middle_pad(5)
= " x "
>> "1234":left_pad(8, "XYZ")
- = "XYZX1234" : Text
+ = "XYZX1234"
>> "1234":right_pad(8, "XYZ")
- = "1234XYZX" : Text
+ = "1234XYZX"
>> "1234":middle_pad(9, "XYZ")
- = "XY1234XYZ" : Text
+ = "XY1234XYZ"
>> amelie:width()
= 6
diff --git a/test/when.tm b/test/when.tm
index 89525c6..77c97af 100644
--- a/test/when.tm
+++ b/test/when.tm
@@ -13,4 +13,4 @@ func main():
>> when n is 1: Int64(1)
is 2: Int64(2)
is 21 + 2: Int64(23)
- = 23 : Int64?
+ = Int64(23)?