aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--ast.c4
-rw-r--r--ast.h4
-rw-r--r--compile.c14
-rw-r--r--docs/optionals.md44
-rw-r--r--environment.c36
-rw-r--r--examples/base64/base64.tm4
-rw-r--r--examples/http/http.tm4
-rw-r--r--parse.c17
-rw-r--r--repl.c2
-rw-r--r--test/iterators.tm4
-rw-r--r--test/optionals.tm38
-rw-r--r--test/structs.tm4
-rw-r--r--typecheck.c8
14 files changed, 97 insertions, 91 deletions
diff --git a/Makefile b/Makefile
index 9fdc0581..c8515b9a 100644
--- a/Makefile
+++ b/Makefile
@@ -69,6 +69,9 @@ clean:
%: %.md
pandoc --lua-filter=.pandoc/bold-code.lua -s $< -t man -o $@
+examples:
+ tomo -IL examples/vectors examples/base64 examples/log examples/ini examples/game examples/http examples/threads examples/tomodeps examples/tomo-install examples/wrap
+
install: tomo libtomo.so tomo.1
mkdir -p -m 755 "$(PREFIX)/man/man1" "$(PREFIX)/bin" "$(PREFIX)/include/tomo" "$(PREFIX)/lib" "$(PREFIX)/share/tomo/modules"
cp -v stdlib/*.h "$(PREFIX)/include/tomo/"
@@ -81,4 +84,4 @@ uninstall:
rm -rvf "$(PREFIX)/bin/tomo" "$(PREFIX)/include/tomo" "$(PREFIX)/lib/libtomo.so" "$(PREFIX)/share/tomo"; \
.SUFFIXES:
-.PHONY: all clean install uninstall test tags
+.PHONY: all clean install uninstall test tags examples
diff --git a/ast.c b/ast.c
index 86265454..750245f4 100644
--- a/ast.c
+++ b/ast.c
@@ -101,7 +101,7 @@ CORD ast_to_xml(ast_t *ast)
switch (ast->tag) {
#define T(type, ...) case type: { auto data = ast->__data.type; (void)data; return CORD_asprintf(__VA_ARGS__); }
T(Unknown, "<Unknown>")
- T(Null, "<Null>%r</Null>", type_ast_to_xml(data.type))
+ T(None, "<None>%r</None>", type_ast_to_xml(data.type))
T(Bool, "<Bool value=\"%s\" />", data.b ? "yes" : "no")
T(Var, "<Var>%s</Var>", data.name)
T(Int, "<Int>%s</Int>", data.str)
@@ -203,7 +203,7 @@ int printf_ast(FILE *stream, const struct printf_info *info, const void *const a
PUREFUNC bool is_idempotent(ast_t *ast)
{
switch (ast->tag) {
- case Int: case Bool: case Num: case Var: case Null: case TextLiteral: return true;
+ case Int: case Bool: case Num: case Var: case None: case TextLiteral: return true;
case Index: {
auto index = Match(ast, Index);
return is_idempotent(index->indexed) && index->index != NULL && is_idempotent(index->index);
diff --git a/ast.h b/ast.h
index 3535734c..01ca9537 100644
--- a/ast.h
+++ b/ast.h
@@ -122,7 +122,7 @@ struct type_ast_s {
typedef enum {
Unknown = 0,
- Null, Bool, Var,
+ None, Bool, Var,
Int, Num,
TextLiteral, TextJoin, PrintStatement,
Declare, Assign,
@@ -155,7 +155,7 @@ struct ast_s {
struct {} Unknown;
struct {
type_ast_t *type;
- } Null;
+ } None;
struct {
bool b;
} Bool;
diff --git a/compile.c b/compile.c
index 46ee8228..817b322e 100644
--- a/compile.c
+++ b/compile.c
@@ -1557,7 +1557,7 @@ CORD compile_to_type(env_t *env, ast_t *ast, type_t *t)
{
if (ast->tag == Int && is_numeric_type(t))
return compile_int_to_type(env, ast, t);
- if (ast->tag == Null && Match(ast, Null)->type == NULL)
+ if (ast->tag == None && Match(ast, None)->type == NULL)
return compile_null(t);
CORD code = compile(env, ast);
type_t *actual = get_type(env, ast);
@@ -1890,7 +1890,7 @@ CORD compile_null(type_t *t)
env_t *enum_env = Match(t, EnumType)->env;
return CORD_all("((", compile_type(t), "){", namespace_prefix(enum_env, enum_env->namespace), "null})");
}
- default: compiler_err(NULL, NULL, NULL, "Null isn't implemented for this type: %T", t);
+ default: compiler_err(NULL, NULL, NULL, "NONE isn't implemented for this type: %T", t);
}
}
@@ -1930,10 +1930,10 @@ static CORD compile_num_to_type(ast_t *ast, type_t *type)
CORD compile(env_t *env, ast_t *ast)
{
switch (ast->tag) {
- case Null: {
- if (!Match(ast, Null)->type)
- code_err(ast, "This 'NULL' needs to specify what type it is using `!Type` syntax");
- type_t *t = parse_type_ast(env, Match(ast, Null)->type);
+ case None: {
+ if (!Match(ast, None)->type)
+ code_err(ast, "This 'NONE' needs to specify what type it is using `NONE:Type` syntax");
+ type_t *t = parse_type_ast(env, Match(ast, None)->type);
return compile_null(t);
}
case Bool: return Match(ast, Bool)->b ? "yes" : "no";
@@ -2746,7 +2746,7 @@ CORD compile(env_t *env, ast_t *ast)
self = compile_to_pointer_depth(env, call->self, 0, false);
arg_t *arg_spec = new(arg_t, .name="count", .type=INT_TYPE,
.next=new(arg_t, .name="weights", .type=Type(ArrayType, .item_type=Type(NumType)),
- .default_val=FakeAST(Null, .type=new(type_ast_t, .tag=ArrayTypeAST,
+ .default_val=FakeAST(None, .type=new(type_ast_t, .tag=ArrayTypeAST,
.__data.ArrayTypeAST.item=new(type_ast_t, .tag=VarTypeAST, .__data.VarTypeAST.name="Num"))),
.next=new(arg_t, .name="rng", .type=RNG_TYPE, .default_val=default_rng)));
return CORD_all("Array$sample(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
diff --git a/docs/optionals.md b/docs/optionals.md
index 584625fe..a0f54626 100644
--- a/docs/optionals.md
+++ b/docs/optionals.md
@@ -35,36 +35,36 @@ Optional types are written using a `?` after the type name. So, an optional
integer would be written as `Int?` and an optional array of texts would be
written as `[Text]?`.
-Null values can be written explicitly using the `!` prefix operator and the
-type of null value. For example, if you wanted to declare a variable that could
-be either an integer value or a null value and initialize it as a null value,
-you would write it as:
+None can be written explicitly using `NONE` with a type annotation. For
+example, if you wanted to declare a variable that could be either an integer
+value or `NONE` and initialize it as none, you would write it as:
```tomo
-x := !Int
+x := NONE:Int
```
Similarly, if you wanted to declare a variable that could be an array of texts
-or null and initialize it as null, you would write:
+or none and initialize it as none, you would write:
```tomo
x := ![Text]
```
-If you want to declare a variable and initialize it with a non-null value, but
-keep open the possibility of assigning a null value later, you can use the
-postfix `?` operator to indicate that a value is optional:
+If you want to declare a variable and initialize it with a non-none value, but
+keep open the possibility of assigning `NONE` later, you can use the postfix
+`?` operator to indicate that a value is optional:
```tomo
x := 5?
-# Later on, assign null:
+# Later on, assign none:
x = !Int
```
## Type Inference
-For convenience, null values can also be written as `NONE` for any type in
-situations where the compiler knows what type of optional value is expected:
+For convenience, `NONE` can also be written without the explicit type
+annotation for any type in situations where the compiler knows what type of
+optional value is expected:
- When assigning to a variable that has already been declared as optional.
- When returning from a function with an explicit optional return type.
@@ -82,7 +82,7 @@ func doop(arg:Int?)->Text?:
doop(NONE)
```
-Non-null values can also be automatically promoted to optional values without
+Non-none values can also be automatically promoted to optional values without
the need for an explicit `?` operator in the cases listed above:
```tomo
@@ -95,12 +95,12 @@ func doop(arg:Int?)->Text?:
doop(123)
```
-## Null Checking
+## None Checking
-In addition to using conditionals to check for null values, you can also use
-`or` to get a non-null value by either providing an alternative non-null value
-or by providing an early out statement like `return`/`skip`/`stop` or a function
-with an `Abort` type like `fail()` or `exit()`:
+In addition to using conditionals to check for `NONE`, you can also use `or` to
+get a non-none value by either providing an alternative non-none value or by
+providing an early out statement like `return`/`skip`/`stop` or a function with
+an `Abort` type like `fail()` or `exit()`:
```tomo
maybe_x := 5?
@@ -120,7 +120,7 @@ func do_stuff(matches:[Text]):
for line in lines:
matches := line:matches($/{..},{..}/) or skip
- # The `or skip` above means that if we're here, `matches` is non-null:
+ # The `or skip` above means that if we're here, `matches` is non-none:
do_stuff(matches)
```
@@ -132,9 +132,9 @@ booleans, texts, enums, nums, or integers (`Int` type only). This is done by
using carefully chosen values, such as `0` for pointers, `2` for booleans, or a
negative length for arrays. However, for fixed-size integers (`Int64`, `Int32`,
`Int16`, and `Int8`), bytes, and structs, an additional byte is required for
-out-of-band information about whether the value is null or not.
+out-of-band information about whether the value is none or not.
-Floating point numbers (`Num` and `Num32`) use `NaN` to represent null, so
-optional nums should be careful to avoid using `NaN` as a non-null value. This
+Floating point numbers (`Num` and `Num32`) use `NaN` to represent none, so
+optional nums should be careful to avoid using `NaN` as a non-none value. This
option was chosen to minimize the memory overhead of optional nums and because
`NaN` literally means "not a number".
diff --git a/environment.c b/environment.c
index 8be31dc7..6f2ff882 100644
--- a/environment.c
+++ b/environment.c
@@ -47,7 +47,7 @@ env_t *new_compilation_unit(CORD libname)
{"exit", {.code="tomo_exit",
.type=Type(FunctionType, .args=new(
arg_t, .name="message", .type=Type(OptionalType, .type=Type(TextType)),
- .default_val=FakeAST(Null, .type=new(type_ast_t, .tag=VarTypeAST, .__data.VarTypeAST.name="Text")),
+ .default_val=FakeAST(None, .type=new(type_ast_t, .tag=VarTypeAST, .__data.VarTypeAST.name="Text")),
.next=new(arg_t, .name="code", .type=Type(IntType, .bits=TYPE_IBITS32),
.default_val=FakeAST(InlineCCode, .code="1", .type=Type(IntType, .bits=TYPE_IBITS32)))),
.ret=Type(AbortType))}},
@@ -295,29 +295,29 @@ env_t *new_compilation_unit(CORD libname)
// Used as a default for functions below:
{"now", "Moment$now", "func(->Moment)"},
- {"after", "Moment$after", "func(moment:Moment,seconds,minutes,hours=0.0,days,weeks,months,years=0,timezone=!Text -> Moment)"},
- {"date", "Moment$date", "func(moment:Moment,timezone=!Text -> Text)"},
- {"day_of_month", "Moment$day_of_month", "func(moment:Moment,timezone=!Text -> Int)"},
- {"day_of_week", "Moment$day_of_week", "func(moment:Moment,timezone=!Text -> Int)"},
- {"day_of_year", "Moment$day_of_year", "func(moment:Moment,timezone=!Text -> Int)"},
- {"format", "Moment$format", "func(moment:Moment,format=\"%Y-%m-%dT%H:%M:%S%z\",timezone=!Text -> Text)"},
+ {"after", "Moment$after", "func(moment:Moment,seconds,minutes,hours=0.0,days,weeks,months,years=0,timezone=NONE:Text -> Moment)"},
+ {"date", "Moment$date", "func(moment:Moment,timezone=NONE:Text -> Text)"},
+ {"day_of_month", "Moment$day_of_month", "func(moment:Moment,timezone=NONE:Text -> Int)"},
+ {"day_of_week", "Moment$day_of_week", "func(moment:Moment,timezone=NONE:Text -> Int)"},
+ {"day_of_year", "Moment$day_of_year", "func(moment:Moment,timezone=NONE:Text -> Int)"},
+ {"format", "Moment$format", "func(moment:Moment,format=\"%Y-%m-%dT%H:%M:%S%z\",timezone=NONE:Text -> Text)"},
{"from_unix_timestamp", "Moment$from_unix_timestamp", "func(timestamp:Int64 -> Moment)"},
{"get_local_timezone", "Moment$get_local_timezone", "func(->Text)"},
- {"hour", "Moment$hour", "func(moment:Moment,timezone=!Text -> Int)"},
+ {"hour", "Moment$hour", "func(moment:Moment,timezone=NONE:Text -> Int)"},
{"hours_till", "Moment$hours_till", "func(now,then:Moment -> Num)"},
- {"minute", "Moment$minute", "func(moment:Moment,timezone=!Text -> Int)"},
+ {"minute", "Moment$minute", "func(moment:Moment,timezone=NONE:Text -> Int)"},
{"minutes_till", "Moment$minutes_till", "func(now,then:Moment -> Num)"},
- {"month", "Moment$month", "func(moment:Moment,timezone=!Text -> Int)"},
- {"nanosecond", "Moment$nanosecond", "func(moment:Moment,timezone=!Text -> Int)"},
- {"new", "Moment$new", "func(year,month,day:Int,hour,minute=0,second=0.0,timezone=!Text -> Moment)"},
+ {"month", "Moment$month", "func(moment:Moment,timezone=NONE:Text -> Int)"},
+ {"nanosecond", "Moment$nanosecond", "func(moment:Moment,timezone=NONE:Text -> Int)"},
+ {"new", "Moment$new", "func(year,month,day:Int,hour,minute=0,second=0.0,timezone=NONE:Text -> Moment)"},
{"parse", "Moment$parse", "func(text:Text, format=\"%Y-%m-%dT%H:%M:%S%z\" -> Moment?)"},
- {"relative", "Moment$relative", "func(moment:Moment,relative_to=Moment.now(),timezone=!Text -> Text)"},
- {"second", "Moment$second", "func(moment:Moment,timezone=!Text -> Int)"},
+ {"relative", "Moment$relative", "func(moment:Moment,relative_to=Moment.now(),timezone=NONE:Text -> Text)"},
+ {"second", "Moment$second", "func(moment:Moment,timezone=NONE:Text -> Int)"},
{"seconds_till", "Moment$seconds_till", "func(now:Moment,then:Moment -> Num)"},
- {"set_local_timezone", "Moment$set_local_timezone", "func(timezone=!Text)"},
- {"time", "Moment$time", "func(moment:Moment,seconds=no,am_pm=yes,timezone=!Text -> Text)"},
+ {"set_local_timezone", "Moment$set_local_timezone", "func(timezone=NONE:Text)"},
+ {"time", "Moment$time", "func(moment:Moment,seconds=no,am_pm=yes,timezone=NONE:Text -> Text)"},
{"unix_timestamp", "Moment$unix_timestamp", "func(moment:Moment -> Int64)"},
- {"year", "Moment$year", "func(moment:Moment,timezone=!Text -> Int)"},
+ {"year", "Moment$year", "func(moment:Moment,timezone=NONE:Text -> Int)"},
)},
{"Path", Type(TextType, .lang="Path", .env=namespace_env(env, "Path")), "Text_t", "Text$info", TypedArray(ns_entry_t,
{"append", "Path$append", "func(path:Path, text:Text, permissions=Int32(0o644))"},
@@ -340,7 +340,7 @@ env_t *new_compilation_unit(CORD libname)
{"is_symlink", "Path$is_symlink", "func(path:Path -> Bool)"},
{"parent", "Path$parent", "func(path:Path -> Path)"},
{"read", "Path$read", "func(path:Path -> Text?)"},
- {"read_bytes", "Path$read_bytes", "func(path:Path, limit=!Int -> [Byte]?)"},
+ {"read_bytes", "Path$read_bytes", "func(path:Path, limit=NONE:Int -> [Byte]?)"},
{"relative", "Path$relative", "func(path:Path, relative_to=(./) -> Path)"},
{"remove", "Path$remove", "func(path:Path, ignore_missing=no)"},
{"resolved", "Path$resolved", "func(path:Path, relative_to=(./) -> Path)"},
diff --git a/examples/base64/base64.tm b/examples/base64/base64.tm
index f3762628..bed94ac1 100644
--- a/examples/base64/base64.tm
+++ b/examples/base64/base64.tm
@@ -59,10 +59,10 @@ lang Base64:
output[dest+2] = _EQUAL_BYTE
output[dest+3] = _EQUAL_BYTE
- return Base64.without_escaping(Text.from_bytes(output) or return !Base64)
+ return Base64.without_escaping(Text.from_bytes(output) or return NONE)
func decode_text(b64:Base64 -> Text?):
- return Text.from_bytes(b64:decode_bytes() or return !Text)
+ return Text.from_bytes(b64:decode_bytes() or return NONE)
func decode_bytes(b64:Base64 -> [Byte]?):
bytes := b64.text_content:bytes()
diff --git a/examples/http/http.tm b/examples/http/http.tm
index f64a5048..f36fac60 100644
--- a/examples/http/http.tm
+++ b/examples/http/http.tm
@@ -78,7 +78,7 @@ func _send(method:_Method, url:Text, data:Text?, headers=[:Text] -> HTTPResponse
return HTTPResponse(Int(code), "":join(chunks))
func get(url:Text, headers=[:Text] -> HTTPResponse):
- return _send(GET, url, !Text, headers)
+ return _send(GET, url, NONE, headers)
func post(url:Text, data="", headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse):
return _send(POST, url, data, headers)
@@ -89,7 +89,7 @@ func put(url:Text, data="", headers=["Content-Type: application/json", "Accept:
func patch(url:Text, data="", headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse):
return _send(PATCH, url, data, headers)
-func delete(url:Text, data=!Text, headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse):
+func delete(url:Text, data=NONE:Text, headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse):
return _send(DELETE, url, data, headers)
func main():
diff --git a/parse.c b/parse.c
index b1d9f739..d92df34d 100644
--- a/parse.c
+++ b/parse.c
@@ -116,7 +116,7 @@ static PARSER(parse_lang_def);
static PARSER(parse_namespace);
static PARSER(parse_negative);
static PARSER(parse_not);
-static PARSER(parse_null);
+static PARSER(parse_none);
static PARSER(parse_num);
static PARSER(parse_parens);
static PARSER(parse_pass);
@@ -1530,14 +1530,17 @@ PARSER(parse_lambda) {
return NewAST(ctx->file, start, pos, Lambda, .id=ctx->next_lambda_id++, .args=args, .ret_type=ret, .body=body);
}
-PARSER(parse_null) {
+PARSER(parse_none) {
const char *start = pos;
- if (match_word(&pos, "NONE"))
- return NewAST(ctx->file, start, pos, Null, .type=NULL);
- if (!match(&pos, "!")) return NULL;
+ if (!match_word(&pos, "NONE"))
+ return NULL;
+
+ if (!match(&pos, ":"))
+ return NewAST(ctx->file, start, pos, None, .type=NULL);
+
type_ast_t *type = parse_type(ctx, pos);
if (!type) return NULL;
- return NewAST(ctx->file, start, type->end, Null, .type=type);
+ return NewAST(ctx->file, start, type->end, None, .type=type);
}
PARSER(parse_var) {
@@ -1553,7 +1556,7 @@ PARSER(parse_term_no_suffix) {
(void)(
false
|| (term=parse_moment(ctx, pos)) // Must come before num/int
- || (term=parse_null(ctx, pos))
+ || (term=parse_none(ctx, pos))
|| (term=parse_num(ctx, pos)) // Must come before int
|| (term=parse_int(ctx, pos))
|| (term=parse_negative(ctx, pos)) // Must come after num/int
diff --git a/repl.c b/repl.c
index 4a5d6644..7374ad31 100644
--- a/repl.c
+++ b/repl.c
@@ -337,7 +337,7 @@ void eval(env_t *env, ast_t *ast, void *dest)
type_t *t = get_type(env, ast);
size_t size = type_size(t);
switch (ast->tag) {
- case Null:
+ case None:
if (dest) *(void**)dest = 0;
break;
case Bool:
diff --git a/test/iterators.tm b/test/iterators.tm
index 2adcab4a..ebb040fd 100644
--- a/test/iterators.tm
+++ b/test/iterators.tm
@@ -4,7 +4,7 @@ struct Pair(x:Text, y:Text)
func pairwise(strs:[Text] -> func(->Pair?)):
i := 1
return func():
- if i + 1 > strs.length: return !Pair
+ if i + 1 > strs.length: return NONE:Pair
i += 1
return Pair(strs[i-1], strs[i])?
@@ -12,7 +12,7 @@ func range(first:Int, last:Int -> func(->Int?)):
i := first
return func():
if i > last:
- return !Int
+ return NONE:Int
i += 1
return (i-1)?
diff --git a/test/optionals.tm b/test/optionals.tm
index 84a4a9ca..acefdd2a 100644
--- a/test/optionals.tm
+++ b/test/optionals.tm
@@ -11,74 +11,74 @@ enum Enum(X, Y(y:Int)):
if should_i:
return Enum.Y(123)
else:
- return !Enum
+ return NONE
func maybe_int(should_i:Bool->Int?):
if should_i:
return 123
else:
- return !Int
+ return NONE
func maybe_int64(should_i:Bool->Int64?):
if should_i:
return Int64(123)
else:
- return !Int64
+ return NONE
func maybe_array(should_i:Bool->[Int]?):
if should_i:
return [10, 20, 30]
else:
- return ![Int]
+ return NONE
func maybe_bool(should_i:Bool->Bool?):
if should_i:
return no
else:
- return !Bool
+ return NONE
func maybe_text(should_i:Bool->Text?):
if should_i:
return "Hello"
else:
- return !Text
+ return NONE
func maybe_num(should_i:Bool->Num?):
if should_i:
return 12.3
else:
- return !Num
+ return NONE
func maybe_lambda(should_i:Bool-> func()?):
if should_i:
return func(): say("hi!")
else:
- return !func()
+ return NONE
func maybe_c_string(should_i:Bool->CString?):
if should_i:
return ("hi":as_c_string())?
else:
- return !CString
+ return NONE
func maybe_channel(should_i:Bool->|Int|?):
if should_i:
return |:Int|?
else:
- return !|Int|
+ return NONE
func maybe_thread(should_i:Bool->Thread?):
if should_i:
return Thread.new(func(): pass)
else:
- return !Thread
+ return NONE
func main():
>> 5?
= 5 : Int?
>> if no:
- !Int
+ NONE:Int
else:
5
= 5 : Int?
@@ -92,7 +92,7 @@ func main():
>> 5? or exit("Non-null is falsey")
= 5 : Int
- >> (!Int) or -1
+ >> (NONE:Int) or -1
= -1 : Int
do:
@@ -279,13 +279,13 @@ func main():
= 123 : Int
# Test comparisons, hashing, equality:
- >> (!Int == 5?)
+ >> (NONE:Int == 5?)
= no
>> (5? == 5?)
= yes
- >> {!Int, !Int}
+ >> {NONE:Int, NONE:Int}
= {NONE}
- >> [5?, !Int, !Int, 6?]:sorted()
+ >> [5?, NONE:Int, NONE:Int, 6?]:sorted()
= [NONE, NONE, 5, 6]
do:
@@ -296,7 +296,7 @@ func main():
= 5
do:
- >> value := if var := !Int:
+ >> value := if var := NONE:Int:
var
else:
0
@@ -310,7 +310,7 @@ func main():
>> opt
do:
- >> opt := !Int
+ >> opt := NONE:Int
>> if opt:
>> opt
else:
@@ -319,7 +319,7 @@ func main():
>> not 5?
= no
- >> not !Int
+ >> not NONE:Int
= yes
>> [Struct(5,"A")?, Struct(6,"B"), Struct(7,"C")]
diff --git a/test/structs.tm b/test/structs.tm
index 26b24d62..ae5bec0f 100644
--- a/test/structs.tm
+++ b/test/structs.tm
@@ -2,11 +2,11 @@
struct Single(x:Int)
struct Pair(x,y:Int)
struct Mixed(x:Int, text:Text)
-struct LinkedList(x:Int, next=!@LinkedList)
+struct LinkedList(x:Int, next=NONE:@LinkedList)
struct Password(text:Text; secret)
struct CorecursiveA(other:@CorecursiveB?)
-struct CorecursiveB(other=!@CorecursiveA)
+struct CorecursiveB(other=NONE:@CorecursiveA)
func test_literals():
>> Single(123)
diff --git a/typecheck.c b/typecheck.c
index da810258..8bb5dc48 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -505,10 +505,10 @@ type_t *get_type(env_t *env, ast_t *ast)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-default"
switch (ast->tag) {
- case Null: {
- if (!Match(ast, Null)->type)
+ case None: {
+ if (!Match(ast, None)->type)
return Type(OptionalType, .type=NULL);
- type_t *t = parse_type_ast(env, Match(ast, Null)->type);
+ type_t *t = parse_type_ast(env, Match(ast, None)->type);
return Type(OptionalType, .type=t);
}
case Bool: {
@@ -1310,7 +1310,7 @@ type_t *parse_type_string(env_t *env, const char *str)
PUREFUNC bool is_constant(env_t *env, ast_t *ast)
{
switch (ast->tag) {
- case Bool: case Num: case Null: return true;
+ case Bool: case Num: case None: return true;
case Int: {
auto info = Match(ast, Int);
Int_t int_val = Int$parse(Text$from_str(info->str));