diff --git a/doc/syntax-spec.md b/doc/syntax-spec.md index 61f81679..db51710d 100644 --- a/doc/syntax-spec.md +++ b/doc/syntax-spec.md @@ -88,16 +88,17 @@ Jou has a few different kinds of tokens: - `continue` - `True` - `False` + - `None` - `NULL` - - `self` + - `void` + - `noreturn` - `and` - `or` - `not` + - `self` - `as` - `sizeof` - `assert` - - `void` - - `noreturn` - `bool` - `byte` - `short` diff --git a/self_hosted/tokenizer.jou b/self_hosted/tokenizer.jou index 004e8fd4..cd867f8c 100644 --- a/self_hosted/tokenizer.jou +++ b/self_hosted/tokenizer.jou @@ -23,10 +23,9 @@ def is_keyword(word: byte*) -> bool: # - syntax documentation keywords = [ "import", "def", "declare", "class", "union", "enum", "global", - "return", "if", "elif", "else", "while", "for", "break", "continue", "pass", - "True", "False", "NULL", "self", - "and", "or", "not", "as", "sizeof", "assert", - "void", "noreturn", + "return", "if", "elif", "else", "while", "for", "pass", "break", "continue", + "True", "False", "None", "NULL", "void", "noreturn", + "and", "or", "not", "self", "as", "sizeof", "assert", "bool", "byte", "short", "int", "long", "float", "double", ] diff --git a/src/parse.c b/src/parse.c index 9b1f8952..388a12fa 100644 --- a/src/parse.c +++ b/src/parse.c @@ -53,6 +53,7 @@ static AstType parse_type(ParserState *ps) AstType result = { .kind = AST_TYPE_NAMED, .location = ps->tokens->location }; if (ps->tokens->type != TOKEN_NAME + && !is_keyword(ps->tokens, "None") && !is_keyword(ps->tokens, "void") && !is_keyword(ps->tokens, "noreturn") && !is_keyword(ps->tokens, "short") @@ -459,6 +460,8 @@ static AstExpression parse_elementary_expression(ParserState *ps) expr.kind = AST_EXPR_GET_VARIABLE; strcpy(expr.data.varname, "self"); ps->tokens++; + } else if (is_keyword(ps->tokens, "None")) { + fail(ps->tokens[0].location, "None is not a value in Jou, use e.g. -1 for numbers or NULL for pointers"); } else { goto not_an_expression; } diff --git a/src/tokenize.c b/src/tokenize.c index 1c491190..3e6b53f1 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -220,10 +220,9 @@ static bool is_keyword(const char *s) // - self-hosted compiler // - syntax documentation "import", "def", "declare", "class", "union", "enum", "global", - "return", "if", "elif", "else", "while", "for", "break", "continue", - "True", "False", "NULL", "self", - "and", "or", "not", "as", "sizeof", "assert", "pass", - "void", "noreturn", + "return", "if", "elif", "else", "while", "for", "pass", "break", "continue", + "True", "False", "None", "NULL", "void", "noreturn", + "and", "or", "not", "self", "as", "sizeof", "assert", "bool", "byte", "short", "int", "long", "float", "double", }; for (const char **kw = &keywords[0]; kw < &keywords[sizeof(keywords)/sizeof(keywords[0])]; kw++) diff --git a/tests/syntax_error/None_as_value.jou b/tests/syntax_error/None_as_value.jou new file mode 100644 index 00000000..c377dae8 --- /dev/null +++ b/tests/syntax_error/None_as_value.jou @@ -0,0 +1,2 @@ +def foo() -> None: + x = None # Error: None is not a value in Jou, use e.g. -1 for numbers or NULL for pointers diff --git a/tests/syntax_error/assign_to_None.jou b/tests/syntax_error/assign_to_None.jou new file mode 100644 index 00000000..e1cafa23 --- /dev/null +++ b/tests/syntax_error/assign_to_None.jou @@ -0,0 +1,4 @@ +def foo() -> None: + # error message is kinda weird, but IMO it's ok. + # Not many people will run into this. It's not tempting for a Python programmer. + None = 123 # Error: None is not a value in Jou, use e.g. -1 for numbers or NULL for pointers