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/examples/aoc2023/day02/part2.jou b/examples/aoc2023/day02/part2.jou index 37bb5c11..b8a209fa 100644 --- a/examples/aoc2023/day02/part2.jou +++ b/examples/aoc2023/day02/part2.jou @@ -8,7 +8,7 @@ class Game: green: int blue: int - def update(self, text: byte*) -> void: + def update(self, text: byte*) -> None: n: int color: byte[10] assert sscanf(text, "%d %9s", &n, color) == 2 diff --git a/examples/aoc2023/day03/part2.jou b/examples/aoc2023/day03/part2.jou index aeb8649f..c4853a2d 100644 --- a/examples/aoc2023/day03/part2.jou +++ b/examples/aoc2023/day03/part2.jou @@ -20,7 +20,7 @@ def read_file(filename: byte*) -> byte*: return result -def find_whole_number(input: byte*, a_digit: byte*, start: byte**, end: byte**) -> void: +def find_whole_number(input: byte*, a_digit: byte*, start: byte**, end: byte**) -> None: *start = a_digit while *start > input and is_ascii_digit((*start)[-1]): --*start diff --git a/examples/aoc2023/day05/part1.jou b/examples/aoc2023/day05/part1.jou index 0c4b03f0..89e5a592 100644 --- a/examples/aoc2023/day05/part1.jou +++ b/examples/aoc2023/day05/part1.jou @@ -8,7 +8,7 @@ class Map: triples: long[3][50] ntriples: int - def add_triple(self, s: byte*) -> void: + def add_triple(self, s: byte*) -> None: a: long b: long c: long @@ -34,7 +34,7 @@ class Input: maps: Map[10] nmaps: int - def add_seeds(self, line: byte*) -> void: + def add_seeds(self, line: byte*) -> None: assert self->n_seed_numbers == 0 assert starts_with(line, "seeds: ") diff --git a/examples/aoc2023/day05/part2.jou b/examples/aoc2023/day05/part2.jou index e276bdf6..e04b1a42 100644 --- a/examples/aoc2023/day05/part2.jou +++ b/examples/aoc2023/day05/part2.jou @@ -12,7 +12,7 @@ class List: def end(self) -> long*: return &self->ptr[self->len] - def append(self, n: long) -> void: + def append(self, n: long) -> None: if self->alloc == self->len: if self->alloc == 0: self->alloc = 4 @@ -24,11 +24,11 @@ class List: self->ptr[self->len++] = n - def extend(self, other: List) -> void: + def extend(self, other: List) -> None: for v = other.ptr; v < other.end(); v++: self->append(*v) - def remove_dupes(self) -> void: + def remove_dupes(self) -> None: for i = self->len-1; i >= 0; i--: # delete i'th number if it occurs after index i for k = i+1; k < self->len; k++: @@ -41,7 +41,7 @@ class Map: triples: long[3][50] ntriples: int - def add_triple(self, s: byte*) -> void: + def add_triple(self, s: byte*) -> None: a: long b: long c: long @@ -109,7 +109,7 @@ class Input: maps: Map[10] nmaps: int - def add_seeds(self, line: byte*) -> void: + def add_seeds(self, line: byte*) -> None: assert self->n_seed_ranges == 0 assert starts_with(line, "seeds: ") line = &line[6] diff --git a/examples/aoc2023/day06/part2.jou b/examples/aoc2023/day06/part2.jou index a792dc52..49563459 100644 --- a/examples/aoc2023/day06/part2.jou +++ b/examples/aoc2023/day06/part2.jou @@ -5,7 +5,7 @@ import "stdlib/io.jou" import "stdlib/math.jou" -def remove_all_whitespace(s: byte*) -> void: +def remove_all_whitespace(s: byte*) -> None: while *s != '\0': if is_ascii_whitespace(*s): memmove(s, &s[1], strlen(s)) diff --git a/examples/aoc2023/day07/part1.jou b/examples/aoc2023/day07/part1.jou index 147b52ec..60c0eea9 100644 --- a/examples/aoc2023/day07/part1.jou +++ b/examples/aoc2023/day07/part1.jou @@ -110,13 +110,13 @@ class Hand: return 0 -def swap(h1: Hand*, h2: Hand*) -> void: +def swap(h1: Hand*, h2: Hand*) -> None: temp = *h1 *h1 = *h2 *h2 = temp -def sort(hands: Hand*, nhands: int) -> void: +def sort(hands: Hand*, nhands: int) -> None: # bubble sort go brrr for sorted_part_len = 1; sorted_part_len < nhands; sorted_part_len++: i = sorted_part_len diff --git a/examples/aoc2023/day07/part2.jou b/examples/aoc2023/day07/part2.jou index 7b69eb59..68986e68 100644 --- a/examples/aoc2023/day07/part2.jou +++ b/examples/aoc2023/day07/part2.jou @@ -145,13 +145,13 @@ class Hand: return 0 -def swap(h1: Hand*, h2: Hand*) -> void: +def swap(h1: Hand*, h2: Hand*) -> None: temp = *h1 *h1 = *h2 *h2 = temp -def sort(hands: Hand*, nhands: int) -> void: +def sort(hands: Hand*, nhands: int) -> None: # bubble sort go brrr for sorted_part_len = 1; sorted_part_len < nhands; sorted_part_len++: i = sorted_part_len diff --git a/examples/aoc2023/day08/part1.jou b/examples/aoc2023/day08/part1.jou index 05fc847f..d74af4a7 100644 --- a/examples/aoc2023/day08/part1.jou +++ b/examples/aoc2023/day08/part1.jou @@ -15,7 +15,7 @@ class Input: nodes: Node[1000] nnodes: int - def add_node(self, node: Node) -> void: + def add_node(self, node: Node) -> None: assert self->nnodes < sizeof(self->nodes)/sizeof(self->nodes[0]) self->nodes[self->nnodes++] = node diff --git a/examples/aoc2023/day08/part2.jou b/examples/aoc2023/day08/part2.jou index 62c25b2d..a75311b6 100644 --- a/examples/aoc2023/day08/part2.jou +++ b/examples/aoc2023/day08/part2.jou @@ -17,7 +17,7 @@ class Input: nodes: Node[1000] nnodes: int - def add_node(self, node: Node) -> void: + def add_node(self, node: Node) -> None: assert self->nnodes < sizeof(self->nodes)/sizeof(self->nodes[0]) self->nodes[self->nnodes++] = node @@ -27,7 +27,7 @@ class Input: return &self->nodes[i] assert False - def find_node_pointers(self) -> void: + def find_node_pointers(self) -> None: for i = 0; i < self->nnodes; i++: self->nodes[i].left_node = self->find_node(self->nodes[i].left) self->nodes[i].right_node = self->find_node(self->nodes[i].right) @@ -45,7 +45,7 @@ class List: assert self->len != 0 return self->end()[-1] - def append(self, n: long) -> void: + def append(self, n: long) -> None: if self->alloc == self->len: if self->alloc == 0: self->alloc = 4 @@ -57,12 +57,12 @@ class List: self->ptr[self->len++] = n - def extend(self, other: List) -> void: + def extend(self, other: List) -> None: for v = other.ptr; v < other.end(); v++: self->append(*v) -def swap(a: long*, b: long*) -> void: +def swap(a: long*, b: long*) -> None: temp = *a *a = *b *b = temp @@ -99,11 +99,11 @@ class ZCounts: first_cycle: List cycle_offset: long # 10 in the example, each cycle starts 10 bigger than previous - def free(self) -> void: + def free(self) -> None: free(self->non_repeating.ptr) free(self->first_cycle.ptr) - def print(self) -> void: + def print(self) -> None: printf(" ") for p = self->non_repeating.ptr; p < self->non_repeating.end(); p++: printf("%d ", *p) @@ -115,7 +115,7 @@ class ZCounts: printf("%d ", *p + k*self->cycle_offset) printf("| ...\n") - def simplify_cycles(self) -> void: + def simplify_cycles(self) -> None: # If the first cycle repeats the same thing twice, reduce it to half of its length. # If the first cycle repeats the same thing 3 times, reduce it to 1/3 length. # And so on. diff --git a/self_hosted/ast.jou b/self_hosted/ast.jou index b1ccb410..39f522bf 100644 --- a/self_hosted/ast.jou +++ b/self_hosted/ast.jou @@ -15,7 +15,7 @@ class AstArrayType: member_type: AstType* length: AstExpression* - def free(self) -> void: + def free(self) -> None: self->member_type->free() self->length->free() free(self->member_type) @@ -33,10 +33,13 @@ class AstType: def is_void(self) -> bool: return self->kind == AstTypeKind::Named and strcmp(self->name, "void") == 0 + def is_none(self) -> bool: + return self->kind == AstTypeKind::Named and strcmp(self->name, "None") == 0 + def is_noreturn(self) -> bool: return self->kind == AstTypeKind::Named and strcmp(self->name, "noreturn") == 0 - def print(self, show_lineno: bool) -> void: + def print(self, show_lineno: bool) -> None: if self->kind == AstTypeKind::Named: printf("%s", self->name) elif self->kind == AstTypeKind::Pointer: @@ -51,7 +54,7 @@ class AstType: if show_lineno: printf(" [line %d]", self->location.lineno) - def free(self) -> void: + def free(self) -> None: if self->kind == AstTypeKind::Pointer: self->value_type->free() free(self->value_type) @@ -142,7 +145,7 @@ class AstExpression: float_or_double_text: byte[100] operands: AstExpression* # Only for operators. Length is arity, see get_arity() - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: printf("[line %d] ", self->location.lineno) if self->kind == AstExpressionKind::String: printf("\"") @@ -257,7 +260,7 @@ class AstExpression: for i = 0; i < self->get_arity(); i++: self->operands[i].print(tp.print_prefix(i == self->get_arity()-1)) - def free(self) -> void: + def free(self) -> None: if self->kind == AstExpressionKind::Call: self->call.free() elif self->kind == AstExpressionKind::As: @@ -319,7 +322,7 @@ class AstArray: length: int items: AstExpression* - def free(self) -> void: + def free(self) -> None: for i = 0; i < self->length; i++: self->items[i].free() free(self->items) @@ -333,7 +336,7 @@ class AstClassField: uses_arrow_operator: bool # distinguishes foo.bar and foo->bar field_name: byte[100] - def free(self) -> void: + def free(self) -> None: self->instance->free() free(self->instance) @@ -341,7 +344,7 @@ class AstAsExpression: value: AstExpression type: AstType - def free(self) -> void: + def free(self) -> None: self->value.free() self->type.free() @@ -360,7 +363,7 @@ class AstCall: else: return "method" - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: if self->method_call_self != NULL: sub = tp.print_prefix(self->nargs == 0) printf("self: ") @@ -371,7 +374,7 @@ class AstCall: printf("argument %d: ", i) self->args[i].print(sub) - def free(self) -> void: + def free(self) -> None: for i = 0; i < self->nargs; i++: self->args[i].free() free(self->args) @@ -383,13 +386,13 @@ class AstInstantiation: field_names: byte[100]* field_values: AstExpression* - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: for i = 0; i < self->nfields; i++: sub = tp.print_prefix(i == self->nfields - 1) printf("field \"%s\": ", self->field_names[i]) self->field_values[i].print(sub) - def free(self) -> void: + def free(self) -> None: for i = 0; i < self->nfields; i++: self->field_values[i].free() free(self->field_names) @@ -434,7 +437,7 @@ class AstStatement: classdef: AstClassDef enumdef: AstEnumDef - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: printf("[line %d] ", self->location.lineno) if self->kind == AstStatementKind::ExpressionStatement: printf("expression statement\n") @@ -505,7 +508,7 @@ class AstStatement: else: printf("??????\n") - def free(self) -> void: + def free(self) -> None: if self->kind == AstStatementKind::Enum: self->enumdef.free() if self->kind == AstStatementKind::ExpressionStatement: @@ -523,7 +526,7 @@ class AstConditionAndBody: condition: AstExpression body: AstBody - def print(self, tp: TreePrinter, body_is_last_sub_item: bool) -> void: + def print(self, tp: TreePrinter, body_is_last_sub_item: bool) -> None: sub = tp.print_prefix(False) printf("condition: ") self->condition.print(sub) @@ -532,7 +535,7 @@ class AstConditionAndBody: printf("body:\n") self->body.print(sub) - def free(self) -> void: + def free(self) -> None: self->condition.free() self->body.free() @@ -540,7 +543,7 @@ class AstAssignment: target: AstExpression value: AstExpression - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: self->target.print(tp.print_prefix(False)) self->value.print(tp.print_prefix(True)) @@ -549,7 +552,7 @@ class AstIfStatement: n_if_and_elifs: int # At least 1 (the if statement). The rest, if any, are elifs. else_body: AstBody # Empty if there is no else - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: for i = 0; i < self->n_if_and_elifs; i++: self->if_and_elifs[i].print(tp, i == self->n_if_and_elifs - 1 and self->else_body.nstatements == 0) @@ -558,7 +561,7 @@ class AstIfStatement: printf("else body:\n") self->else_body.print(sub) - def free(self) -> void: + def free(self) -> None: for i = 0; i < self->n_if_and_elifs; i++: self->if_and_elifs[i].free() free(self->if_and_elifs) @@ -574,7 +577,7 @@ class AstForLoop: incr: AstStatement* body: AstBody - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: sub = tp.print_prefix(False) printf("init: ") self->init->print(sub) @@ -591,7 +594,7 @@ class AstForLoop: printf("body:\n") self->body.print(sub) - def free(self) -> void: + def free(self) -> None: self->init->free() free(self->init) self->cond.free() @@ -607,7 +610,7 @@ class AstNameTypeValue: value: AstExpression* # can be NULL # tp can be set to NULL, in that case no trailing newline is printed - def print(self, tp: TreePrinter*) -> void: + def print(self, tp: TreePrinter*) -> None: printf("%s: ", self->name) self->type.print(True) if tp == NULL: @@ -619,7 +622,7 @@ class AstNameTypeValue: printf("initial value: ") self->value->print(sub) - def free(self) -> void: + def free(self) -> None: if self->value != NULL: self->value->free() free(self->value) @@ -628,11 +631,11 @@ class AstBody: statements: AstStatement* nstatements: int - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: for i = 0; i < self->nstatements; i++: self->statements[i].print(tp.print_prefix(i == self->nstatements - 1)) - def free(self) -> void: + def free(self) -> None: for i = 0; i < self->nstatements; i++: self->statements[i].free() free(self->statements) @@ -645,7 +648,7 @@ class AstSignature: takes_varargs: bool # True for functions like printf() return_type: AstType - def print(self) -> void: + def print(self) -> None: printf("%s(", self->name) for i = 0; i < self->nargs; i++: if i != 0: @@ -664,7 +667,7 @@ class AstSignature: self->return_type.print(True) printf("\n") - def free(self) -> void: + def free(self) -> None: self->return_type.free() class AstImport: @@ -672,12 +675,12 @@ class AstImport: specified_path: byte* # Path in jou code e.g. "stdlib/io.jou" resolved_path: byte* # Absolute path or relative to current working directory e.g. "/home/akuli/jou/stdlib/io.jou" - def print(self) -> void: + def print(self) -> None: printf( "line %d: Import \"%s\", which resolves to \"%s\".\n", self->location.lineno, self->specified_path, self->resolved_path) - def free(self) -> void: + def free(self) -> None: free(self->specified_path) free(self->resolved_path) @@ -687,14 +690,14 @@ class AstFile: nimports: int body: AstBody - def print(self) -> void: + def print(self) -> None: printf("===== AST for file \"%s\" =====\n", self->path) for i = 0; i < self->nimports; i++: self->imports[i].print() for i = 0; i < self->body.nstatements; i++: self->body.statements[i].print(TreePrinter{}) - def free(self) -> void: + def free(self) -> None: for i = 0; i < self->nimports; i++: self->imports[i].free() free(self->imports) @@ -704,11 +707,11 @@ class AstFunctionOrMethod: signature: AstSignature body: AstBody # empty body means declaration, otherwise it's a definition - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: self->signature.print() self->body.print(tp) - def free(self) -> void: + def free(self) -> None: self->signature.free() self->body.free() @@ -716,12 +719,12 @@ class AstUnionFields: fields: AstNameTypeValue* nfields: int - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: for i = 0; i < self->nfields; i++: subprinter = tp.print_prefix(i == self->nfields-1) self->fields[i].print(&subprinter) # TODO: does this need to be optional/pointer? - def free(self) -> void: + def free(self) -> None: for i = 0; i < self->nfields; i++: self->fields[i].free() free(self->fields) @@ -738,7 +741,7 @@ class AstClassMember: union_fields: AstUnionFields method: AstFunctionOrMethod - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: if self->kind == AstClassMemberKind::Field: printf("field ") self->field.print(NULL) @@ -753,7 +756,7 @@ class AstClassMember: else: assert False - def free(self) -> void: + def free(self) -> None: if self->kind == AstClassMemberKind::Field: self->field.free() elif self->kind == AstClassMemberKind::Union: @@ -769,12 +772,12 @@ class AstClassDef: members: AstClassMember* nmembers: int - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: printf("class \"%s\" with %d members\n", self->name, self->nmembers) for i = 0; i < self->nmembers; i++: self->members[i].print(tp.print_prefix(i == self->nmembers-1)) - def free(self) -> void: + def free(self) -> None: for i = 0; i < self->nmembers; i++: self->members[i].free() free(self->members) @@ -785,11 +788,11 @@ class AstEnumDef: member_count: int member_names: byte[100]* - def print(self, tp: TreePrinter) -> void: + def print(self, tp: TreePrinter) -> None: printf("enum \"%s\" with %d members\n", self->name, self->member_count) for i = 0; i < self->member_count; i++: tp.print_prefix(i == self->member_count-1) puts(self->member_names[i]) - def free(self) -> void: + def free(self) -> None: free(self->member_names) diff --git a/self_hosted/create_llvm_ir.jou b/self_hosted/create_llvm_ir.jou index d9a874fe..c2e9f2aa 100644 --- a/self_hosted/create_llvm_ir.jou +++ b/self_hosted/create_llvm_ir.jou @@ -152,7 +152,7 @@ class AstToIR: argtypes[i] = type_to_llvm(sig->argtypes[i]) # TODO: tell llvm if we know a function is noreturn - if sig->return_type == NULL: # "-> noreturn" or "-> void" + if sig->return_type == NULL: # "-> noreturn" or "-> None" return_type = LLVMVoidType() else: return_type = type_to_llvm(sig->return_type) @@ -162,7 +162,7 @@ class AstToIR: return LLVMAddFunction(self->module, full_name, function_type) - def new_block(self, name_hint: byte*) -> void: + def new_block(self, name_hint: byte*) -> None: assert self->llvm_function != NULL block = LLVMAppendBasicBlock(self->llvm_function, name_hint) LLVMPositionBuilderAtEnd(self->builder, block) @@ -321,7 +321,7 @@ class AstToIR: printf("%s %d %s\n", lhs_type->name, op, rhs_type->name) assert False - def do_assert(self, condition: LLVMValue*) -> void: + def do_assert(self, condition: LLVMValue*) -> None: true_block = LLVMAppendBasicBlock(self->llvm_function, "assert_true") false_block = LLVMAppendBasicBlock(self->llvm_function, "assert_false") LLVMBuildCondBr(self->builder, condition, true_block, false_block) @@ -635,7 +635,7 @@ class AstToIR: return result return self->do_cast(result, types->original_type, types->implicit_cast_type) - def do_if_statement(self, ast: AstIfStatement*) -> void: + def do_if_statement(self, ast: AstIfStatement*) -> None: assert ast->n_if_and_elifs >= 1 done = LLVMAppendBasicBlock(self->llvm_function, "if_done") @@ -658,7 +658,7 @@ class AstToIR: # ...body... # # While loop is basically a special case of for loop, so it uses this too. - def do_loop(self, init: AstStatement*, cond: AstExpression*, incr: AstStatement*, body: AstBody*) -> void: + def do_loop(self, init: AstStatement*, cond: AstExpression*, incr: AstStatement*, body: AstBody*) -> None: cond_block = LLVMAppendBasicBlock(self->llvm_function, "loop_cond") body_block = LLVMAppendBasicBlock(self->llvm_function, "loop_body") incr_block = LLVMAppendBasicBlock(self->llvm_function, "loop_incr") @@ -694,7 +694,7 @@ class AstToIR: # rest of the function/method goes to done block LLVMPositionBuilderAtEnd(self->builder, done_block) - def do_in_place_operation(self, op: AstExpressionKind, assignment: AstAssignment*) -> void: + def do_in_place_operation(self, op: AstExpressionKind, assignment: AstAssignment*) -> None: target_pointer = self->do_address_of_expression(&assignment->target) target_type = self->function_or_method_types->get_expression_types(&assignment->target)->original_type rhs = self->do_expression(&assignment->value) @@ -704,7 +704,7 @@ class AstToIR: new_value = self->do_binop(op, old_value, target_type, rhs, rhs_type) LLVMBuildStore(self->builder, new_value, target_pointer) - def do_statement(self, ast: AstStatement*) -> void: + def do_statement(self, ast: AstStatement*) -> None: if ast->kind == AstStatementKind::ExpressionStatement: self->do_expression(&ast->expression) elif ast->kind == AstStatementKind::Return: @@ -755,11 +755,11 @@ class AstToIR: printf("create_llvm_ir: unknown statement kind %d...\n", ast->kind) assert False - def do_body(self, body: AstBody*) -> void: + def do_body(self, body: AstBody*) -> None: for i = 0; i < body->nstatements; i++: self->do_statement(&body->statements[i]) - def define_function_or_method(self, funcdef: AstFunctionOrMethod*, self_type: Type*) -> void: + def define_function_or_method(self, funcdef: AstFunctionOrMethod*, self_type: Type*) -> None: assert self->function_or_method_types == NULL self->function_or_method_types = self->file_types->find_defined_function_or_method(funcdef->signature.name, self_type) assert self->function_or_method_types != NULL diff --git a/self_hosted/evaluate.jou b/self_hosted/evaluate.jou index fb702bcb..e2b0c0e8 100644 --- a/self_hosted/evaluate.jou +++ b/self_hosted/evaluate.jou @@ -39,7 +39,7 @@ def evaluate_compile_time_if_statement(if_stmt: AstIfStatement*) -> AstBody: # Replace body->statements[i] with zero or more statements from another body. -def replace(body: AstBody*, i: int, new: AstBody) -> void: +def replace(body: AstBody*, i: int, new: AstBody) -> None: body->statements[i].free() item_size = sizeof(body->statements[0]) @@ -53,7 +53,7 @@ def replace(body: AstBody*, i: int, new: AstBody) -> void: # This handles nested if statements. -def evaluate_compile_time_if_statements_in_body(body: AstBody*) -> void: +def evaluate_compile_time_if_statements_in_body(body: AstBody*) -> None: i = 0 while i < body->nstatements: if body->statements[i].kind == AstStatementKind::If: diff --git a/self_hosted/llvm.jou b/self_hosted/llvm.jou index 522dc888..8001c04d 100644 --- a/self_hosted/llvm.jou +++ b/self_hosted/llvm.jou @@ -19,14 +19,14 @@ class LLVMTargetMachine: _dummy: int # =========== Target.h =========== -declare LLVMInitializeX86TargetInfo() -> void -declare LLVMInitializeX86Target() -> void -declare LLVMInitializeX86TargetMC() -> void -declare LLVMInitializeX86AsmPrinter() -> void -declare LLVMInitializeX86AsmParser() -> void -declare LLVMInitializeX86Disassembler() -> void +declare LLVMInitializeX86TargetInfo() -> None +declare LLVMInitializeX86Target() -> None +declare LLVMInitializeX86TargetMC() -> None +declare LLVMInitializeX86AsmPrinter() -> None +declare LLVMInitializeX86AsmParser() -> None +declare LLVMInitializeX86Disassembler() -> None -declare LLVMDisposeTargetData(TD: LLVMTargetData*) -> void +declare LLVMDisposeTargetData(TD: LLVMTargetData*) -> None declare LLVMCopyStringRepOfTargetData(TD: LLVMTargetData*) -> byte* declare LLVMStoreSizeOfType(TD: LLVMTargetData*, Ty: LLVMType*) -> long @@ -64,7 +64,7 @@ enum LLVMCodeGenFileType: ObjectFile declare LLVMCreateTargetMachine(T: LLVMTarget*, Triple: byte*, CPU: byte*, Features: byte*, Level: LLVMCodeGenOptLevel, Reloc: LLVMRelocMode, CodeModel: LLVMCodeModel) -> LLVMTargetMachine* -declare LLVMDisposeTargetMachine(T: LLVMTargetMachine*) -> void +declare LLVMDisposeTargetMachine(T: LLVMTargetMachine*) -> None declare LLVMCreateTargetDataLayout(T: LLVMTargetMachine*) -> LLVMTargetData* declare LLVMTargetMachineEmitToFile(T: LLVMTargetMachine*, M: LLVMModule*, Filename: byte*, codegen: LLVMCodeGenFileType, ErrorMessage: byte**) -> int declare LLVMGetTargetFromTriple(Triple: byte*, T: LLVMTarget**, ErrorMessage: byte**) -> int @@ -192,13 +192,13 @@ declare LLVMFunctionType(ReturnType: LLVMType*, ParamTypes: LLVMType**, ParamCou declare LLVMStructType(ElementTypes: LLVMType**, ElementCount: int, Packed: int) -> LLVMType* declare LLVMArrayType(ElementType: LLVMType*, ElementCount: int) -> LLVMType* declare LLVMPointerType(ElementType: LLVMType*, AddressSpace: int) -> LLVMType* -declare LLVMDisposeMessage(Message: byte*) -> void +declare LLVMDisposeMessage(Message: byte*) -> None declare LLVMModuleCreateWithName(ModuleID: byte*) -> LLVMModule* -declare LLVMDisposeModule(M: LLVMModule*) -> void +declare LLVMDisposeModule(M: LLVMModule*) -> None declare LLVMGetSourceFileName(M: LLVMModule*, Len: long*) -> byte* # Return value not owned -declare LLVMSetDataLayout(M: LLVMModule*, DataLayoutStr: byte*) -> void -declare LLVMSetTarget(M: LLVMModule*, Triple: byte*) -> void -declare LLVMDumpModule(M: LLVMModule*) -> void +declare LLVMSetDataLayout(M: LLVMModule*, DataLayoutStr: byte*) -> None +declare LLVMSetTarget(M: LLVMModule*, Triple: byte*) -> None +declare LLVMDumpModule(M: LLVMModule*) -> None declare LLVMPrintModuleToString(M: LLVMModule*) -> byte* declare LLVMAddFunction(M: LLVMModule*, Name: byte*, FunctionTy: LLVMType*) -> LLVMValue* declare LLVMGetNamedFunction(M: LLVMModule*, Name: byte*) -> LLVMValue* @@ -219,16 +219,16 @@ declare LLVMConstInt(IntTy: LLVMType*, N: long, SignExtend: int) -> LLVMValue* declare LLVMConstRealOfString(RealTy: LLVMType*, Text: byte*) -> LLVMValue* declare LLVMConstString(Str: byte*, Length: int, DontNullTerminate: int) -> LLVMValue* declare LLVMSizeOf(Ty: LLVMType*) -> LLVMValue* -declare LLVMSetLinkage(Global: LLVMValue*, Linkage: LLVMLinkage) -> void +declare LLVMSetLinkage(Global: LLVMValue*, Linkage: LLVMLinkage) -> None declare LLVMAddGlobal(M: LLVMModule*, Ty: LLVMType*, Name: byte*) -> LLVMValue* declare LLVMGetNamedGlobal(M: LLVMModule*, Name: byte*) -> LLVMValue* -declare LLVMSetInitializer(GlobalVar: LLVMValue*, ConstantVal: LLVMValue*) -> void +declare LLVMSetInitializer(GlobalVar: LLVMValue*, ConstantVal: LLVMValue*) -> None declare LLVMAppendBasicBlock(Fn: LLVMValue*, Name: byte*) -> LLVMBasicBlock* -declare LLVMAddIncoming(PhiNode: LLVMValue*, IncomingValues: LLVMValue**, IncomingBlocks: LLVMBasicBlock**, Count: int) -> void +declare LLVMAddIncoming(PhiNode: LLVMValue*, IncomingValues: LLVMValue**, IncomingBlocks: LLVMBasicBlock**, Count: int) -> None declare LLVMCreateBuilder() -> LLVMBuilder* -declare LLVMPositionBuilderAtEnd(Builder: LLVMBuilder*, Block: LLVMBasicBlock*) -> void +declare LLVMPositionBuilderAtEnd(Builder: LLVMBuilder*, Block: LLVMBasicBlock*) -> None declare LLVMGetInsertBlock(Builder: LLVMBuilder*) -> LLVMBasicBlock* -declare LLVMDisposeBuilder(Builder: LLVMBuilder*) -> void +declare LLVMDisposeBuilder(Builder: LLVMBuilder*) -> None declare LLVMBuildRet(Builder: LLVMBuilder*, V: LLVMValue*) -> LLVMValue* declare LLVMBuildRetVoid(Builder: LLVMBuilder*) -> LLVMValue* declare LLVMBuildBr(Builder: LLVMBuilder*, Dest: LLVMBasicBlock*) -> LLVMValue* @@ -274,4 +274,4 @@ declare LLVMBuildExtractValue(Builder: LLVMBuilder*, AggVal: LLVMValue*, Index: declare LLVMBuildInsertValue(Builder: LLVMBuilder*, AggVal: LLVMValue*, EltVal: LLVMValue*, Index: int, Name: byte*) -> LLVMValue* declare LLVMCreatePassManager() -> LLVMPassManager* declare LLVMRunPassManager(PM: LLVMPassManager*, M: LLVMModule*) -> int -declare LLVMDisposePassManager(PM: LLVMPassManager*) -> void +declare LLVMDisposePassManager(PM: LLVMPassManager*) -> None diff --git a/self_hosted/main.jou b/self_hosted/main.jou index fd82e5ef..4f39c145 100644 --- a/self_hosted/main.jou +++ b/self_hosted/main.jou @@ -29,11 +29,11 @@ class CommandLineArgs: # An error message should have already been printed to stderr, without a trailing \n -def fail_parsing_args(argv0: byte*, message: byte*) -> void: +def fail_parsing_args(argv0: byte*, message: byte*) -> None: fprintf(stderr, "%s: %s (try \"%s --help\")\n", argv0, message, argv0) exit(2) -def print_help(argv0: byte*) -> void: +def print_help(argv0: byte*) -> None: printf("Usage:\n") printf(" %s [options] FILENAME.jou\n", argv0) printf(" %s --help # This message\n", argv0) @@ -117,7 +117,7 @@ def get_sane_filename(path: byte*) -> byte[50]: name[i] = '_' return name -def check_ast_and_import_conflicts(ast: AstFile*, symbol: ExportSymbol*) -> void: +def check_ast_and_import_conflicts(ast: AstFile*, symbol: ExportSymbol*) -> None: for i = 0; i < ast->body.nstatements; i++: ts = &ast->body.statements[i] if ts->kind == AstStatementKind::Function: @@ -169,14 +169,14 @@ class Compiler: nfiles: int automagic_files: byte*[10] - def determine_automagic_files(self) -> void: + def determine_automagic_files(self) -> None: self->automagic_files[0] = malloc(strlen(self->stdlib_path) + 40) sprintf(self->automagic_files[0], "%s/_assert_fail.jou", self->stdlib_path) if WINDOWS: self->automagic_files[1] = malloc(strlen(self->stdlib_path) + 40) sprintf(self->automagic_files[1], "%s/_windows_startup.jou", self->stdlib_path) - def parse_all_files(self) -> void: + def parse_all_files(self) -> None: queue: ParseQueueItem* = malloc(50 * sizeof queue[0]) queue_len = 0 queue[queue_len++] = ParseQueueItem{path = self->args->main_path} @@ -224,7 +224,7 @@ class Compiler: free(queue) - def process_imports_and_exports(self) -> void: + def process_imports_and_exports(self) -> None: if self->verbosity >= 1: printf("Processing imports/exports\n") @@ -267,7 +267,7 @@ class Compiler: free(self->files[i].pending_exports) self->files[i].pending_exports = NULL - def typecheck_stage1_all_files(self) -> void: + def typecheck_stage1_all_files(self) -> None: for i = 0; i < self->nfiles; i++: if self->verbosity >= 1: printf("Type-check stage 1: %s\n", self->files[i].ast.path) @@ -278,7 +278,7 @@ class Compiler: &self->files[i].ast, ) - def typecheck_stage2_all_files(self) -> void: + def typecheck_stage2_all_files(self) -> None: for i = 0; i < self->nfiles; i++: if self->verbosity >= 1: printf("Type-check stage 2: %s\n", self->files[i].ast.path) @@ -289,7 +289,7 @@ class Compiler: &self->files[i].ast, ) - def typecheck_stage3_all_files(self) -> void: + def typecheck_stage3_all_files(self) -> None: for i = 0; i < self->nfiles; i++: if self->verbosity >= 1: printf("Type-check stage 3: %s\n", self->files[i].ast.path) @@ -416,7 +416,7 @@ class Compiler: return exe - def run(self, exe: byte*) -> void: + def run(self, exe: byte*) -> None: command = malloc(strlen(exe) + 10) sprintf(command, "\"%s\"", exe) if self->verbosity >= 1: diff --git a/self_hosted/parser.jou b/self_hosted/parser.jou index 1b3166d7..e3f8bfa3 100644 --- a/self_hosted/parser.jou +++ b/self_hosted/parser.jou @@ -99,7 +99,7 @@ class MemberInfo: name: byte[100] name_location: Location -def check_class_for_duplicate_names(classdef: AstClassDef*) -> void: +def check_class_for_duplicate_names(classdef: AstClassDef*) -> None: n = 0 for i = 0; i < classdef->nmembers; i++: member = &classdef->members[i] @@ -155,7 +155,7 @@ class Parser: stdlib_path: byte* is_parsing_method_body: bool - def eat_newline(self) -> void: + def eat_newline(self) -> None: if self->tokens->kind != TokenKind::Newline: self->tokens->fail_expected_got("end of line") self->tokens++ @@ -201,6 +201,7 @@ class Parser: def parse_type(self) -> AstType: if not ( self->tokens->kind == TokenKind::Name + or self->tokens->is_keyword("None") or self->tokens->is_keyword("void") or self->tokens->is_keyword("noreturn") or self->tokens->is_keyword("short") @@ -338,7 +339,7 @@ class Parser: # Special case for common typo: def foo(): if self->tokens->is_operator(":"): - fail(self->tokens->location, "return type must be specified with '->', or with '-> void' if the function doesn't return anything") + fail(self->tokens->location, "return type must be specified with '->', or with '-> None' if the function doesn't return anything") if not self->tokens->is_operator("->"): self->tokens->fail_expected_got("a '->'") self->tokens++ @@ -882,7 +883,7 @@ class Parser: self->eat_newline() return result - def parse_start_of_body(self) -> void: + def parse_start_of_body(self) -> None: if not self->tokens->is_operator(":"): self->tokens->fail_expected_got("':' followed by a new line with more indentation") self->tokens++ diff --git a/self_hosted/parses_wrong.txt b/self_hosted/parses_wrong.txt new file mode 100644 index 00000000..05a0c544 --- /dev/null +++ b/self_hosted/parses_wrong.txt @@ -0,0 +1,2 @@ +tests/syntax_error/assign_to_None.jou +tests/syntax_error/None_as_value.jou diff --git a/self_hosted/paths.jou b/self_hosted/paths.jou index 3f1b5f6f..25679b9c 100644 --- a/self_hosted/paths.jou +++ b/self_hosted/paths.jou @@ -113,10 +113,10 @@ def find_stdlib() -> byte*: # We need to ignore the error when directory exists already (EEXIST). # Ideally we wouldn't ignore any other errors. if WINDOWS: - def my_mkdir(path: byte*) -> void: + def my_mkdir(path: byte*) -> None: _mkdir(path) else: - def my_mkdir(path: byte*) -> void: + def my_mkdir(path: byte*) -> None: mkdir(path, 0o777) # this is what mkdir in bash does according to strace def get_path_to_file_in_jou_compiled(filename: byte*) -> byte*: @@ -129,10 +129,10 @@ def get_path_to_file_in_jou_compiled(filename: byte*) -> byte*: return result # TODO: put this to stdlib? or does it do too much for a stdlib function? -def delete_slice(start: byte*, end: byte*) -> void: +def delete_slice(start: byte*, end: byte*) -> None: memmove(start, end, strlen(end) + 1) -def simplify_path(path: byte*) -> void: +def simplify_path(path: byte*) -> None: if WINDOWS: # Backslash to forward slash. for p = path; *p != '\0'; p++: diff --git a/self_hosted/runs_wrong.txt b/self_hosted/runs_wrong.txt index 97972d9f..96e30101 100644 --- a/self_hosted/runs_wrong.txt +++ b/self_hosted/runs_wrong.txt @@ -31,7 +31,7 @@ tests/should_succeed/loops.jou tests/should_succeed/plusplus_minusminus.jou tests/should_succeed/pointer.jou tests/should_succeed/printf.jou -tests/should_succeed/return_void.jou +tests/other_errors/return_void.jou tests/should_succeed/sizeof.jou tests/should_succeed/stderr.jou tests/should_succeed/undefined_value_warning.jou @@ -46,3 +46,6 @@ stdlib/ascii.jou tests/should_succeed/ascii_test.jou stdlib/_macos_startup.jou tests/should_succeed/if_WINDOWS_at_runtime.jou +tests/should_succeed/return_none.jou +tests/syntax_error/assign_to_None.jou +tests/syntax_error/None_as_value.jou diff --git a/self_hosted/target.jou b/self_hosted/target.jou index ec2b56a8..905cd471 100644 --- a/self_hosted/target.jou +++ b/self_hosted/target.jou @@ -22,11 +22,11 @@ class Target: global target: Target # TODO: run this with atexit() once we have function pointers -#def cleanup() -> void: +#def cleanup() -> None: # LLVMDisposeTargetMachine(target.target_machine) # LLVMDisposeTargetData(target.target_data) -def init_target() -> void: +def init_target() -> None: LLVMInitializeX86TargetInfo() LLVMInitializeX86Target() LLVMInitializeX86TargetMC() diff --git a/self_hosted/token.jou b/self_hosted/token.jou index e769ae75..008b1369 100644 --- a/self_hosted/token.jou +++ b/self_hosted/token.jou @@ -36,7 +36,7 @@ class Token: short_string: byte[100] # Name, Keyword, Operator long_string: byte* # String - def print(self) -> void: + def print(self) -> None: if self->kind == TokenKind::Byte: printf("byte %#02x", self->byte_value) if isprint(self->byte_value) != 0: @@ -101,7 +101,7 @@ class Token: def is_close_paren(self) -> bool: return self->is_operator(")") or self->is_operator("]") or self->is_operator("}") - def fail_expected_got(self, what_was_expected_instead: byte*) -> void: + def fail_expected_got(self, what_was_expected_instead: byte*) -> None: got: byte[100] if self->kind == TokenKind::Short: got = "a short" diff --git a/self_hosted/tokenizer.jou b/self_hosted/tokenizer.jou index 914939f4..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", ] @@ -190,7 +189,7 @@ class Tokenizer: self->location.lineno++ return c - def unread_byte(self, b: byte) -> void: + def unread_byte(self, b: byte) -> None: if b == '\0': return @@ -228,7 +227,7 @@ class Tokenizer: self->unread_byte(b) return dest - def consume_rest_of_line(self) -> void: + def consume_rest_of_line(self) -> None: while True: c = self->read_byte() if c == '\0' or c == '\n': @@ -424,7 +423,7 @@ class Tokenizer: sprintf(message, "there is no '%s' operator", operator) fail(self->location, message) - def handle_parentheses(self, token: Token*) -> void: + def handle_parentheses(self, token: Token*) -> None: if token->kind == TokenKind::EndOfFile and self->open_parens_len > 0: open_token = self->open_parens[0] actual_open = open_token.short_string[0] @@ -605,7 +604,7 @@ def tokenize(path: byte*, import_location: Location*) -> Token*: free(raw_tokens) return better_tokens -def print_tokens(tokens: Token*) -> void: +def print_tokens(tokens: Token*) -> None: printf("===== Tokens for file \"%s\" =====\n", tokens->location.path) t = tokens current_lineno = -1 diff --git a/self_hosted/typecheck.jou b/self_hosted/typecheck.jou index fb00606b..ddfc60e9 100644 --- a/self_hosted/typecheck.jou +++ b/self_hosted/typecheck.jou @@ -60,7 +60,7 @@ def can_cast_explicitly(from: Type*, to: Type*) -> bool: # The template can contain "" and "". They will be substituted with names # of types. We cannot use printf() style functions because the arguments can be in # any order. -def fail_with_implicit_cast_error(location: Location, template: byte*, from: Type*, to: Type*) -> void: +def fail_with_implicit_cast_error(location: Location, template: byte*, from: Type*, to: Type*) -> None: assert template != NULL n = 0 @@ -118,7 +118,7 @@ class ExpressionTypes: return self->implicit_cast_type # TODO: error_location is probably unnecessary, can get location from self->expression - def do_implicit_cast(self, to: Type*, error_location: Location, error_template: byte*) -> void: + def do_implicit_cast(self, to: Type*, error_location: Location, error_template: byte*) -> None: # This cannot be called multiple times assert self->implicit_cast_type == NULL assert not self->implicit_array_to_pointer_cast @@ -157,7 +157,7 @@ class ExpressionTypes: ) # Does not store the new type to self, because explicit casts have their own AstExpression which has its own expression types. - def do_explicit_cast(self, to: Type*, error_location: Location) -> void: + def do_explicit_cast(self, to: Type*, error_location: Location) -> None: assert self->implicit_cast_type == NULL assert not self->implicit_array_to_pointer_cast @@ -170,7 +170,7 @@ class ExpressionTypes: if from->kind == TypeKind::Array and to->is_pointer_type(): self->cast_array_to_pointer() - def cast_array_to_pointer(self) -> void: + def cast_array_to_pointer(self) -> None: assert self->original_type->kind == TypeKind::Array self->do_implicit_cast(self->original_type->array.item_type->get_pointer_type(), Location{}, NULL) @@ -215,7 +215,7 @@ class FileTypes: globals: GlobalVariable* nglobals: int - def add_imported_symbol(self, symbol: ExportSymbol*) -> void: + def add_imported_symbol(self, symbol: ExportSymbol*) -> None: if symbol->kind != ExportSymbolKind::Function: # TODO return @@ -251,7 +251,7 @@ class FileTypes: return self->globals[i].type return NULL -def check_type_doesnt_exist(ft: FileTypes*, name: byte*, location: Location) -> void: +def check_type_doesnt_exist(ft: FileTypes*, name: byte*, location: Location) -> None: existing = ft->find_type(name) if existing != NULL: description = short_type_description(existing) @@ -298,6 +298,8 @@ def evaluate_array_length(expression: AstExpression*) -> int: def type_from_ast(ft: FileTypes*, ast_type: AstType*) -> Type*: if ast_type->is_void(): fail(ast_type->location, "'void' cannot be used here because it is not a type") + if ast_type->is_none(): + fail(ast_type->location, "'None' cannot be used here because it is not a type") if ast_type->is_noreturn(): fail(ast_type->location, "'noreturn' cannot be used here because it is not a type") @@ -360,7 +362,7 @@ def handle_signature(ft: FileTypes*, astsig: AstSignature*, self_type: Type*) -> else: sig.argtypes[i] = type_from_ast(ft, &astsig->args[i].type) - if astsig->return_type.is_void() or astsig->return_type.is_noreturn(): + if astsig->return_type.is_none() or astsig->return_type.is_noreturn(): sig.return_type = NULL else: sig.return_type = type_from_ast(ft, &astsig->return_type) @@ -372,7 +374,7 @@ def handle_signature(ft: FileTypes*, astsig: AstSignature*, self_type: Type*) -> return sig -def handle_class_members_stage2(ft: FileTypes*, classdef: AstClassDef*) -> void: +def handle_class_members_stage2(ft: FileTypes*, classdef: AstClassDef*) -> None: # Previous type-checking stage created an opaque type. type: Type* = NULL for i = 0; i < ft->ntypes; i++: @@ -586,7 +588,7 @@ def short_expression_description(expr: AstExpression*) -> byte[200]: # value of the pointer &foo to bar. # # error_template can be e.g. "cannot take address of %s" or "cannot assign to %s" -def ensure_can_take_address(expression: AstExpression*, error_template: byte*) -> void: +def ensure_can_take_address(expression: AstExpression*, error_template: byte*) -> None: if expression->kind == AstExpressionKind::GetClassField: # &foo.bar --> must ensure we can take address of foo. # Doesn't apply to &foo->bar because that's foo + some offset, so foo is already a pointer. @@ -1177,7 +1179,7 @@ class Stage3TypeChecker: value: AstExpression*, # the 1 of "foo += 1" op_expr_kind: AstExpressionKind, # e.g. AstExpressionKind::Add op_description: byte[20], # e.g. "addition" - ) -> void: + ) -> None: ensure_can_take_address(target, "cannot assign to %s") target_types = self->do_expression(target) value_types = self->do_expression(value) @@ -1194,7 +1196,7 @@ class Stage3TypeChecker: # If this assert fails, we probably need a new error message. assert target_types->implicit_cast_type == NULL - def do_statement(self, statement: AstStatement*) -> void: + def do_statement(self, statement: AstStatement*) -> None: if statement->kind == AstStatementKind::ExpressionStatement: self->do_expression_maybe_void(&statement->expression) @@ -1208,7 +1210,7 @@ class Stage3TypeChecker: if statement->return_value != NULL and sig->return_type == NULL: snprintf( msg, sizeof msg, - "%s '%s' cannot return a value because it was defined with '-> void'", + "%s '%s' cannot return a value because it was defined with '-> None'", sig->function_or_method(), sig->name, ) fail(statement->location, msg) @@ -1333,11 +1335,11 @@ class Stage3TypeChecker: printf("*** typecheck: unknown statement kind %d\n", statement->kind) assert False - def do_body(self, body: AstBody*) -> void: + def do_body(self, body: AstBody*) -> None: for i = 0; i < body->nstatements; i++: self->do_statement(&body->statements[i]) - def define_function_or_method(self, signature: Signature*, body: AstBody*) -> void: + def define_function_or_method(self, signature: Signature*, body: AstBody*) -> None: assert self->current_function_or_method == NULL self->file_types->defined_functions = realloc( self->file_types->defined_functions, @@ -1353,7 +1355,7 @@ class Stage3TypeChecker: self->current_function_or_method = NULL -def typecheck_stage3_function_and_method_bodies(file_types: FileTypes*, ast_file: AstFile*) -> void: +def typecheck_stage3_function_and_method_bodies(file_types: FileTypes*, ast_file: AstFile*) -> None: checker = Stage3TypeChecker{file_types = file_types} for i = 0; i < ast_file->body.nstatements; i++: ts = &ast_file->body.statements[i] diff --git a/self_hosted/types.jou b/self_hosted/types.jou index 51447563..e393048a 100644 --- a/self_hosted/types.jou +++ b/self_hosted/types.jou @@ -133,7 +133,7 @@ global short_type: Type* global int_type: Type* global long_type: Type* -def init_types() -> void: +def init_types() -> None: void_ptr_type = Type{name = "void*", kind = TypeKind::VoidPointer} bool_type = Type{name = "bool", kind = TypeKind::Bool} float_type = Type{name = "float", size_in_bits = 32, kind = TypeKind::FloatingPoint} @@ -226,7 +226,7 @@ class Signature: if include_return_type: if self->return_type == NULL: - strcat(result, " -> void") + strcat(result, " -> None") else: strcat(result, " -> ") strcat(result, self->return_type->name) @@ -241,6 +241,6 @@ class Signature: memcpy(result.argtypes, self->argtypes, result.nargs * sizeof(result.argtypes[0])) return result - def free(self) -> void: + def free(self) -> None: free(self->argnames) free(self->argtypes) diff --git a/src/codegen.c b/src/codegen.c index 2f73ce63..2a36a52f 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -176,7 +176,7 @@ static LLVMValueRef codegen_function_or_method_decl(const struct State *st, cons LLVMTypeRef returntype; // TODO: tell llvm, if we know a function is noreturn ? - if (sig->returntype == NULL) // "-> noreturn" or "-> void" + if (sig->returntype == NULL) // "-> noreturn" or "-> None" returntype = LLVMVoidType(); else returntype = codegen_type(sig->returntype); diff --git a/src/parse.c b/src/parse.c index c8704ac7..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") @@ -184,7 +185,7 @@ static AstSignature parse_function_signature(ParserState *ps, bool accept_self) fail_with_error( ps->tokens->location, "return type must be specified with '->'," - " or with '-> void' if the function doesn't return anything" + " or with '-> None' if the function doesn't return anything" ); } fail_with_parse_error(ps->tokens, "a '->'"); @@ -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/src/typecheck.c b/src/typecheck.c index fc67e1f0..029d7fe4 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -148,6 +148,11 @@ static bool is_void(const AstType *t) return t->kind == AST_TYPE_NAMED && !strcmp(t->data.name, "void"); } +static bool is_none(const AstType *t) +{ + return t->kind == AST_TYPE_NAMED && !strcmp(t->data.name, "None"); +} + static bool is_noreturn(const AstType *t) { return t->kind == AST_TYPE_NAMED && !strcmp(t->data.name, "noreturn"); @@ -155,7 +160,7 @@ static bool is_noreturn(const AstType *t) static const Type *type_from_ast(const FileTypes *ft, const AstType *asttype) { - if (is_void(asttype) || is_noreturn(asttype)) + if (is_void(asttype) || is_none(asttype) || is_noreturn(asttype)) fail_with_error(asttype->location, "'%s' cannot be used here because it is not a type", asttype->data.name); const Type *tmp; @@ -234,8 +239,10 @@ static Signature handle_signature(FileTypes *ft, const AstSignature *astsig, con } sig.is_noreturn = is_noreturn(&astsig->returntype); - if (is_void(&astsig->returntype) || is_noreturn(&astsig->returntype)) + if (is_none(&astsig->returntype) || is_noreturn(&astsig->returntype)) sig.returntype = NULL; + else if (is_void(&astsig->returntype)) + fail_with_error(astsig->returntype.location, "void is not a valid return type, use '-> None' if the function does not return a value"); else sig.returntype = type_from_ast(ft, &astsig->returntype); @@ -1263,7 +1270,7 @@ static void typecheck_statement(FileTypes *ft, const AstStatement *stmt) if (stmt->data.returnvalue && !returntype) { fail_with_error( stmt->location, - "function '%s' cannot return a value because it was defined with '-> void'", + "function '%s' cannot return a value because it was defined with '-> None'", ft->current_fom_types->signature.name); } if (returntype && !stmt->data.returnvalue) { diff --git a/stdlib/_macos_startup.jou b/stdlib/_macos_startup.jou index 0c51a8ab..1d8baae8 100644 --- a/stdlib/_macos_startup.jou +++ b/stdlib/_macos_startup.jou @@ -14,7 +14,7 @@ declare global __stdinp: void* declare global __stdoutp: void* declare global __stderrp: void* -def _jou_macos_startup() -> void: +def _jou_macos_startup() -> None: stdin = __stdinp stdout = __stdoutp stderr = __stderrp diff --git a/stdlib/_windows_startup.jou b/stdlib/_windows_startup.jou index 7dd4ef8b..878f9622 100644 --- a/stdlib/_windows_startup.jou +++ b/stdlib/_windows_startup.jou @@ -20,7 +20,7 @@ global stderr: void* declare __acrt_iob_func(index: int) -> void* -def _jou_windows_startup() -> void: +def _jou_windows_startup() -> None: stdin = __acrt_iob_func(0) stdout = __acrt_iob_func(1) stderr = __acrt_iob_func(2) diff --git a/stdlib/ascii.jou b/stdlib/ascii.jou index dd21ffaa..e1498a91 100644 --- a/stdlib/ascii.jou +++ b/stdlib/ascii.jou @@ -26,7 +26,7 @@ def is_ascii_whitespace(b: byte) -> bool: # Removes ASCII whitespace from both ends of a string in-place. # Similar to .strip() in Python or .trim() in JavaScript. -def trim_ascii_whitespace(s: byte*) -> void: +def trim_ascii_whitespace(s: byte*) -> None: start = s while *start != '\0' and is_ascii_whitespace(*start): start++ diff --git a/stdlib/errno.jou b/stdlib/errno.jou index 99afd529..9fd56299 100644 --- a/stdlib/errno.jou +++ b/stdlib/errno.jou @@ -2,7 +2,7 @@ # See also _windows_startup.jou declare __errno_location() -> int* -def set_errno(value: int) -> void: +def set_errno(value: int) -> None: *__errno_location() = value def get_errno() -> int: diff --git a/stdlib/io.jou b/stdlib/io.jou index 53f35083..83b7129a 100644 --- a/stdlib/io.jou +++ b/stdlib/io.jou @@ -81,4 +81,4 @@ declare feof(file: FILE*) -> int declare ferror(file: FILE*) -> int # Move back to beginning of file. -declare rewind(file: FILE*) -> void +declare rewind(file: FILE*) -> None diff --git a/stdlib/mem.jou b/stdlib/mem.jou index edbf04d7..2bbaea02 100644 --- a/stdlib/mem.jou +++ b/stdlib/mem.jou @@ -5,7 +5,7 @@ declare malloc(size: long) -> void* declare calloc(a: long, b: long) -> void* declare realloc(ptr: void*, size: long) -> void* -declare free(ptr: void*) -> void +declare free(ptr: void*) -> None # TODO: explain what each of these does declare memset(dest: void*, fill_byte: int, count: long) -> void* diff --git a/tests/404/class_field.jou b/tests/404/class_field.jou index 33f8fb8d..7657a0b6 100644 --- a/tests/404/class_field.jou +++ b/tests/404/class_field.jou @@ -1,6 +1,6 @@ class Foo: x: int -def asdasd() -> void: +def asdasd() -> None: foo = Foo{x=1} bar = foo.y # Error: class Foo has no field named 'y' diff --git a/tests/404/enum.jou b/tests/404/enum.jou index 2dba4640..938bf8e6 100644 --- a/tests/404/enum.jou +++ b/tests/404/enum.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = Foo::Bar # Error: there is no type named 'Foo' diff --git a/tests/404/enum_member.jou b/tests/404/enum_member.jou index db524307..ae640a2d 100644 --- a/tests/404/enum_member.jou +++ b/tests/404/enum_member.jou @@ -2,5 +2,5 @@ enum FooBar: Foo Bar -def foo() -> void: +def foo() -> None: x = FooBar::Asdf # Error: enum FooBar has no member named 'Asdf' diff --git a/tests/404/indirect_import_symbol.jou b/tests/404/indirect_import_symbol.jou index 3942093f..cab4fac0 100644 --- a/tests/404/indirect_import_symbol.jou +++ b/tests/404/indirect_import_symbol.jou @@ -6,5 +6,5 @@ import "../should_succeed/imported/point_factory.jou" -def foo() -> void: +def foo() -> None: p = Point{x=1, y=2} # Error: there is no type named 'Point' diff --git a/tests/404/method_on_int.jou b/tests/404/method_on_int.jou index 7c3a28fa..9ad051d1 100644 --- a/tests/404/method_on_int.jou +++ b/tests/404/method_on_int.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: (1 + 2).asdf() # Error: type int does not have any methods because it is a number type, not a class diff --git a/tests/already_exists_error/class_field_and_method.jou b/tests/already_exists_error/class_field_and_method.jou index a1f8c59f..288d0279 100644 --- a/tests/already_exists_error/class_field_and_method.jou +++ b/tests/already_exists_error/class_field_and_method.jou @@ -1,4 +1,4 @@ class Foo: x: int - def x(self) -> void: # Error: class Foo already has a field named 'x' + def x(self) -> None: # Error: class Foo already has a field named 'x' return diff --git a/tests/already_exists_error/func.jou b/tests/already_exists_error/func.jou index ed9d8379..b5f28993 100644 --- a/tests/already_exists_error/func.jou +++ b/tests/already_exists_error/func.jou @@ -1,5 +1,5 @@ -def foo() -> void: +def foo() -> None: return -def foo() -> void: # Error: a function named 'foo' already exists +def foo() -> None: # Error: a function named 'foo' already exists return diff --git a/tests/already_exists_error/func_import.jou b/tests/already_exists_error/func_import.jou index c698d578..695147fa 100644 --- a/tests/already_exists_error/func_import.jou +++ b/tests/already_exists_error/func_import.jou @@ -1,4 +1,4 @@ import "stdlib/io.jou" -def puts() -> void: # Error: a function named 'puts' already exists +def puts() -> None: # Error: a function named 'puts' already exists return diff --git a/tests/already_exists_error/local_var.jou b/tests/already_exists_error/local_var.jou index 545d6203..c1f0d011 100644 --- a/tests/already_exists_error/local_var.jou +++ b/tests/already_exists_error/local_var.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: x: int x: int # Error: a variable named 'x' already exists diff --git a/tests/already_exists_error/method.jou b/tests/already_exists_error/method.jou index f6ffb7f5..f6106af0 100644 --- a/tests/already_exists_error/method.jou +++ b/tests/already_exists_error/method.jou @@ -1,5 +1,5 @@ class Foo: - def bar(self) -> void: + def bar(self) -> None: return - def bar(self) -> void: # Error: class Foo already has a method named 'bar' + def bar(self) -> None: # Error: class Foo already has a method named 'bar' return diff --git a/tests/other_errors/array0.jou b/tests/other_errors/array0.jou index 07ba4713..561486a4 100644 --- a/tests/other_errors/array0.jou +++ b/tests/other_errors/array0.jou @@ -1,2 +1,2 @@ -def foo(x: int[0]) -> void: # Error: array length must be positive +def foo(x: int[0]) -> None: # Error: array length must be positive return diff --git a/tests/other_errors/array_literal_as_a_pointer.jou b/tests/other_errors/array_literal_as_a_pointer.jou index be942ee5..1de83feb 100644 --- a/tests/other_errors/array_literal_as_a_pointer.jou +++ b/tests/other_errors/array_literal_as_a_pointer.jou @@ -1,6 +1,6 @@ import "stdlib/io.jou" -def foo() -> void: +def foo() -> None: # This works message = ['h','i','\0'] puts(message) diff --git a/tests/other_errors/assign_to_WINDOWS.jou b/tests/other_errors/assign_to_WINDOWS.jou index 62bb5a97..0ff70e2d 100644 --- a/tests/other_errors/assign_to_WINDOWS.jou +++ b/tests/other_errors/assign_to_WINDOWS.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: WINDOWS = False # Error: cannot assign to a special constant diff --git a/tests/other_errors/dumb_assignment.jou b/tests/other_errors/dumb_assignment.jou index 96e0e5b4..58cf9c60 100644 --- a/tests/other_errors/dumb_assignment.jou +++ b/tests/other_errors/dumb_assignment.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: 1 = 1 # Error: cannot assign to a constant diff --git a/tests/other_errors/duplicate_arg_name.jou b/tests/other_errors/duplicate_arg_name.jou index 9e11077c..1aa7860c 100644 --- a/tests/other_errors/duplicate_arg_name.jou +++ b/tests/other_errors/duplicate_arg_name.jou @@ -1 +1 @@ -declare foo(x: int, x: byte) -> void # Error: there are multiple arguments named 'x' +declare foo(x: int, x: byte) -> None # Error: there are multiple arguments named 'x' diff --git a/tests/other_errors/empty_array.jou b/tests/other_errors/empty_array.jou index d75a1ca9..f5f3c96f 100644 --- a/tests/other_errors/empty_array.jou +++ b/tests/other_errors/empty_array.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = [] # Error: arrays cannot be empty diff --git a/tests/other_errors/field_of_a_field_of_a_field_error.jou b/tests/other_errors/field_of_a_field_of_a_field_error.jou index 6bcd4522..26a57035 100644 --- a/tests/other_errors/field_of_a_field_of_a_field_error.jou +++ b/tests/other_errors/field_of_a_field_of_a_field_error.jou @@ -5,5 +5,5 @@ class FooY: class FooZ: z: FooY -def bar() -> void: +def bar() -> None: FooZ{}.z.y.x++ # Error: cannot increment a field of a field of a field of a newly created instance diff --git a/tests/other_errors/func_then_method.jou b/tests/other_errors/func_then_method.jou index 6e8ba735..0d4d21a0 100644 --- a/tests/other_errors/func_then_method.jou +++ b/tests/other_errors/func_then_method.jou @@ -1,11 +1,11 @@ import "stdlib/io.jou" class Foo: - def do_stuff(self) -> void: + def do_stuff(self) -> None: printf("Doing stuff!\n") def make_foo() -> Foo: return Foo{} -def bar() -> void: +def bar() -> None: make_foo().do_stuff() # Error: cannot take address of a function call, needed for calling the do_stuff() method diff --git a/tests/other_errors/function_call_indexing.jou b/tests/other_errors/function_call_indexing.jou index c14856ec..c86d2a66 100644 --- a/tests/other_errors/function_call_indexing.jou +++ b/tests/other_errors/function_call_indexing.jou @@ -1,7 +1,7 @@ def foo() -> int[3]: return [1, 2, 3] -def bar() -> void: +def bar() -> None: # This works my_var = foo() x = my_var[1] diff --git a/tests/other_errors/increment_indirect_addressof_fails.jou b/tests/other_errors/increment_indirect_addressof_fails.jou index 0cffb06f..1e578368 100644 --- a/tests/other_errors/increment_indirect_addressof_fails.jou +++ b/tests/other_errors/increment_indirect_addressof_fails.jou @@ -1,5 +1,5 @@ class Foo: x: int -def bar() -> void: +def bar() -> None: Foo{x=1}.x++ # Error: cannot increment a field of a newly created instance diff --git a/tests/other_errors/instantiation_address_of_field.jou b/tests/other_errors/instantiation_address_of_field.jou index be296164..2a87d912 100644 --- a/tests/other_errors/instantiation_address_of_field.jou +++ b/tests/other_errors/instantiation_address_of_field.jou @@ -6,6 +6,6 @@ class Foo: def make_foo_pointer() -> Foo*: return malloc(123) -def asdf() -> void: +def asdf() -> None: magic_pointer = &make_foo_pointer()->x # This succeeds magic_pointer = &Foo{}.x # Error: the '&' operator cannot be used with a field of a newly created instance diff --git a/tests/other_errors/instantiation_dupe.jou b/tests/other_errors/instantiation_dupe.jou index 8f0cecf2..633b128b 100644 --- a/tests/other_errors/instantiation_dupe.jou +++ b/tests/other_errors/instantiation_dupe.jou @@ -1,5 +1,5 @@ class Foo: x: int -def foo() -> void: +def foo() -> None: wat = Foo{x=1, x=2} # Error: multiple values were given for field 'x' diff --git a/tests/other_errors/method_on_ptr_called_on_class.jou b/tests/other_errors/method_on_ptr_called_on_class.jou index 7059832b..4998d191 100644 --- a/tests/other_errors/method_on_ptr_called_on_class.jou +++ b/tests/other_errors/method_on_ptr_called_on_class.jou @@ -1,10 +1,10 @@ class Foo: x: int - def bar(self) -> void: + def bar(self) -> None: return -def asdf() -> void: +def asdf() -> None: f = Foo{x=1} f.bar() (&f)->bar() diff --git a/tests/other_errors/multiple_union_members_given.jou b/tests/other_errors/multiple_union_members_given.jou index 3a3eac1d..2102e366 100644 --- a/tests/other_errors/multiple_union_members_given.jou +++ b/tests/other_errors/multiple_union_members_given.jou @@ -7,7 +7,7 @@ class Foo: x: int y: int -def foo() -> void: +def foo() -> None: f = Foo{ x = 1, blah = "hey!", diff --git a/tests/other_errors/none_ptr.jou b/tests/other_errors/none_ptr.jou new file mode 100644 index 00000000..a3df7d0e --- /dev/null +++ b/tests/other_errors/none_ptr.jou @@ -0,0 +1,2 @@ +def foo(x: None*) -> int: # Error: 'None' cannot be used here because it is not a type + return 1 diff --git a/tests/other_errors/python_init_method.jou b/tests/other_errors/python_init_method.jou index 8ca93d78..aa852946 100644 --- a/tests/other_errors/python_init_method.jou +++ b/tests/other_errors/python_init_method.jou @@ -1,7 +1,7 @@ # This isn't special-cased, because it's not as tempting to try as __init__ in class. -def __init__() -> void: +def __init__() -> None: pass class Foo: - def __init__(self) -> void: # Error: Jou does not have a special __init__ method like Python + def __init__(self) -> None: # Error: Jou does not have a special __init__ method like Python pass diff --git a/tests/other_errors/redefine_imported_func.jou b/tests/other_errors/redefine_imported_func.jou index c698d578..695147fa 100644 --- a/tests/other_errors/redefine_imported_func.jou +++ b/tests/other_errors/redefine_imported_func.jou @@ -1,4 +1,4 @@ import "stdlib/io.jou" -def puts() -> void: # Error: a function named 'puts' already exists +def puts() -> None: # Error: a function named 'puts' already exists return diff --git a/tests/other_errors/return_void.jou b/tests/other_errors/return_void.jou new file mode 100644 index 00000000..b31c1b03 --- /dev/null +++ b/tests/other_errors/return_void.jou @@ -0,0 +1,2 @@ +def foo() -> void: # Error: void is not a valid return type, use '-> None' if the function does not return a value + pass diff --git a/tests/other_errors/self_assign_in_function.jou b/tests/other_errors/self_assign_in_function.jou index b205e75d..8fa0c83e 100644 --- a/tests/other_errors/self_assign_in_function.jou +++ b/tests/other_errors/self_assign_in_function.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: self = 0 # Error: 'self' cannot be used here diff --git a/tests/other_errors/self_assign_in_method.jou b/tests/other_errors/self_assign_in_method.jou index 0be9c89f..0fb071ef 100644 --- a/tests/other_errors/self_assign_in_method.jou +++ b/tests/other_errors/self_assign_in_method.jou @@ -1,3 +1,3 @@ class Foo: - def foo(self) -> void: + def foo(self) -> None: self = 0 # Error: cannot assign to self diff --git a/tests/other_errors/self_declare_local_var_in_function.jou b/tests/other_errors/self_declare_local_var_in_function.jou index 125c66b6..e92d7ff7 100644 --- a/tests/other_errors/self_declare_local_var_in_function.jou +++ b/tests/other_errors/self_declare_local_var_in_function.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: self: int # Error: 'self' cannot be used here diff --git a/tests/other_errors/self_declare_local_var_in_method.jou b/tests/other_errors/self_declare_local_var_in_method.jou index 946cd1a2..361c3a37 100644 --- a/tests/other_errors/self_declare_local_var_in_method.jou +++ b/tests/other_errors/self_declare_local_var_in_method.jou @@ -1,3 +1,3 @@ class Foo: - def bar(self) -> void: + def bar(self) -> None: self: int # Error: not a valid statement diff --git a/tests/other_errors/self_use_in_function.jou b/tests/other_errors/self_use_in_function.jou index 03532314..d0bab8c4 100644 --- a/tests/other_errors/self_use_in_function.jou +++ b/tests/other_errors/self_use_in_function.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = self # Error: 'self' cannot be used here diff --git a/tests/other_errors/string_doesnt_fit_to_array.jou b/tests/other_errors/string_doesnt_fit_to_array.jou index a9b43acf..511791bb 100644 --- a/tests/other_errors/string_doesnt_fit_to_array.jou +++ b/tests/other_errors/string_doesnt_fit_to_array.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x: byte[20] = "this is a long string" # Error: a string of 22 bytes (including '\0') does not fit into byte[20] diff --git a/tests/other_errors/unexpected_return_value.jou b/tests/other_errors/unexpected_return_value.jou index f1c1e69f..62a954de 100644 --- a/tests/other_errors/unexpected_return_value.jou +++ b/tests/other_errors/unexpected_return_value.jou @@ -1,2 +1,2 @@ -def f() -> void: - return 123 # Error: function 'f' cannot return a value because it was defined with '-> void' +def f() -> None: + return 123 # Error: function 'f' cannot return a value because it was defined with '-> None' diff --git a/tests/other_errors/using_void_function.jou b/tests/other_errors/using_function_with_none_return.jou similarity index 69% rename from tests/other_errors/using_void_function.jou rename to tests/other_errors/using_function_with_none_return.jou index 1fd1a1e5..a71a8221 100644 --- a/tests/other_errors/using_void_function.jou +++ b/tests/other_errors/using_function_with_none_return.jou @@ -1,5 +1,5 @@ -def f() -> void: +def f() -> None: return -def g() -> void: +def g() -> None: x = f() + 123 # Error: function 'f' does not return a value diff --git a/tests/other_errors/using_void_method.jou b/tests/other_errors/using_method_with_none_return.jou similarity index 72% rename from tests/other_errors/using_void_method.jou rename to tests/other_errors/using_method_with_none_return.jou index f7c8f47f..b54ff9d4 100644 --- a/tests/other_errors/using_void_method.jou +++ b/tests/other_errors/using_method_with_none_return.jou @@ -1,7 +1,7 @@ class Foo: - def f(self) -> void: + def f(self) -> None: return -def g() -> void: +def g() -> None: foo = Foo{} x = foo.f() + 123 # Error: method 'f' does not return a value diff --git a/tests/other_errors/var_shadow.jou b/tests/other_errors/var_shadow.jou index bbebc246..ecb5e30c 100644 --- a/tests/other_errors/var_shadow.jou +++ b/tests/other_errors/var_shadow.jou @@ -1,4 +1,4 @@ global foo: byte* -def foo() -> void: +def foo() -> None: foo: int = 1 # Error: a variable named 'foo' already exists diff --git a/tests/should_succeed/argument.jou b/tests/should_succeed/argument.jou index ce6b4f86..2099d3c0 100644 --- a/tests/should_succeed/argument.jou +++ b/tests/should_succeed/argument.jou @@ -1,10 +1,10 @@ import "stdlib/io.jou" # TODO: should there be a warning for this? Not sure. -def unused_arg(asd: bool) -> void: +def unused_arg(asd: bool) -> None: return -def putchar3(ch: int) -> void: +def putchar3(ch: int) -> None: putchar(ch) putchar(ch) putchar(ch) diff --git a/tests/should_succeed/array.jou b/tests/should_succeed/array.jou index 7e40104f..56b47ffb 100644 --- a/tests/should_succeed/array.jou +++ b/tests/should_succeed/array.jou @@ -5,11 +5,11 @@ def make_array() -> int[3]: return [4, 5, 6] # Arrays are passed by value. -def do_nothing(a: int[3]) -> void: +def do_nothing(a: int[3]) -> None: ++a[0] # Use a pointer instead if you want to modify the array. -def increment(a: int*) -> void: +def increment(a: int*) -> None: ++a[0] def main() -> int: diff --git a/tests/should_succeed/class.jou b/tests/should_succeed/class.jou index f62b5bbf..f0a83a36 100644 --- a/tests/should_succeed/class.jou +++ b/tests/should_succeed/class.jou @@ -4,7 +4,7 @@ class Foo: num: int text: byte* -def increment(f: Foo*) -> void: +def increment(f: Foo*) -> None: ++f->num def main() -> int: diff --git a/tests/should_succeed/compile_time_if.jou b/tests/should_succeed/compile_time_if.jou index 98b6e817..1374e312 100644 --- a/tests/should_succeed/compile_time_if.jou +++ b/tests/should_succeed/compile_time_if.jou @@ -4,11 +4,11 @@ import "stdlib/io.jou" # Ideally only the declares would need compile-time if statements. if WINDOWS: declare CreateDirectoryA(lpPathName: byte*, lpSecurityAttributes: void*) -> int - def make_foo() -> void: + def make_foo() -> None: CreateDirectoryA("tmp\\tests\\foo", NULL) else: declare mkdir(pathname: byte*, mode: int) -> int - def make_foo() -> void: + def make_foo() -> None: # python uses 777 as default perms, see help(os.mkdir) mkdir("tmp/tests/foo", 0o777) diff --git a/tests/should_succeed/compiler_cli.jou b/tests/should_succeed/compiler_cli.jou index 0d1e2eee..df9b3a8c 100644 --- a/tests/should_succeed/compiler_cli.jou +++ b/tests/should_succeed/compiler_cli.jou @@ -4,7 +4,7 @@ import "stdlib/process.jou" import "stdlib/io.jou" -def run_jou(command: byte*) -> void: +def run_jou(command: byte*) -> None: if WINDOWS: jou_exe = "jou.exe" else: diff --git a/tests/should_succeed/file.jou b/tests/should_succeed/file.jou index dbfd89b7..99925608 100644 --- a/tests/should_succeed/file.jou +++ b/tests/should_succeed/file.jou @@ -1,7 +1,7 @@ import "stdlib/io.jou" import "stdlib/process.jou" -def write_hello_123() -> void: +def write_hello_123() -> None: f = fopen("tmp/tests/hello.txt", "w") if f == NULL: printf("can't write tmp/tests/hello.txt\n") @@ -12,7 +12,7 @@ def write_hello_123() -> void: fprintf(f, "o %d\n", 123) fclose(f) -def read_hello_123() -> void: +def read_hello_123() -> None: f = fopen("tmp/tests/hello.txt", "r") if f == NULL: printf("can't read tmp/tests/hello.txt\n") diff --git a/tests/should_succeed/global.jou b/tests/should_succeed/global.jou index e8e9bc90..51a5949a 100644 --- a/tests/should_succeed/global.jou +++ b/tests/should_succeed/global.jou @@ -2,7 +2,7 @@ import "stdlib/io.jou" global x: int -def increment_x() -> void: +def increment_x() -> None: x++ def main() -> int: diff --git a/tests/should_succeed/if_elif_else.jou b/tests/should_succeed/if_elif_else.jou index 97fdb827..0991a4e4 100644 --- a/tests/should_succeed/if_elif_else.jou +++ b/tests/should_succeed/if_elif_else.jou @@ -1,6 +1,6 @@ import "stdlib/io.jou" -def foo(x: int) -> void: +def foo(x: int) -> None: printf("<") if x > 10: printf("Big") diff --git a/tests/should_succeed/implicit_conversions.jou b/tests/should_succeed/implicit_conversions.jou index cfffb425..4e928c22 100644 --- a/tests/should_succeed/implicit_conversions.jou +++ b/tests/should_succeed/implicit_conversions.jou @@ -5,21 +5,21 @@ def foo1(x: byte) -> int: return x # Function arguments -def foo2(x: byte) -> void: +def foo2(x: byte) -> None: putchar(x) # Local variables -def foo3(x: int) -> void: +def foo3(x: int) -> None: x = 'c' putchar(x) # Local variables, with a given type -def foo4() -> void: +def foo4() -> None: x: int = 'd' putchar(x) # https://github.com/Akuli/jou/issues/50 -def issue50() -> void: +def issue50() -> None: x = 128 as byte y: int = x printf("%d %d\n", x, y) diff --git a/tests/should_succeed/import_cycle.jou b/tests/should_succeed/import_cycle.jou index 9e7e5aea..88ca31b6 100644 --- a/tests/should_succeed/import_cycle.jou +++ b/tests/should_succeed/import_cycle.jou @@ -1,7 +1,7 @@ import "stdlib/io.jou" import "./imported/cycle.jou" -def a(x: int) -> void: +def a(x: int) -> None: printf("a %d\n", x) if x > 0: b(x-1) diff --git a/tests/should_succeed/imported/bar.jou b/tests/should_succeed/imported/bar.jou index 411588d2..54979029 100644 --- a/tests/should_succeed/imported/bar.jou +++ b/tests/should_succeed/imported/bar.jou @@ -9,12 +9,12 @@ class Point: def get_sum(self) -> int: return self->x + self->y - def increment_y(self) -> void: + def increment_y(self) -> None: self->y += 1 enum FooBar: Foo Bar -def bar(point: Point) -> void: +def bar(point: Point) -> None: printf("Bar Bar %d %d\n", point.x, point.y) diff --git a/tests/should_succeed/imported/cycle.jou b/tests/should_succeed/imported/cycle.jou index 26cb56b8..eab37a1d 100644 --- a/tests/should_succeed/imported/cycle.jou +++ b/tests/should_succeed/imported/cycle.jou @@ -3,7 +3,7 @@ import "stdlib/io.jou" import "../import_cycle.jou" -def b(x: int) -> void: +def b(x: int) -> None: printf("b %d\n", x) if x > 0: a(x-1) diff --git a/tests/should_succeed/linked_list.jou b/tests/should_succeed/linked_list.jou index 2a305247..744f22d0 100644 --- a/tests/should_succeed/linked_list.jou +++ b/tests/should_succeed/linked_list.jou @@ -5,19 +5,19 @@ class Node: value: byte next: Node* - def print(self) -> void: + def print(self) -> None: putchar(self->value) if self->next != NULL: self->next->print() else: putchar('\n') -def prepend(list: Node**, value: byte) -> void: +def prepend(list: Node**, value: byte) -> None: new_first: Node* = malloc(sizeof *new_first) *new_first = Node{value = value, next = *list} *list = new_first -def free_list(list: Node*) -> void: +def free_list(list: Node*) -> None: while list != NULL: next = list->next free(list) diff --git a/tests/should_succeed/method.jou b/tests/should_succeed/method.jou index 21592758..697228b9 100644 --- a/tests/should_succeed/method.jou +++ b/tests/should_succeed/method.jou @@ -7,7 +7,7 @@ class Foo: def get_sum(self) -> int: return self->x + self->y - def increment_x(self) -> void: + def increment_x(self) -> None: self->x++ class Foo3: diff --git a/tests/should_succeed/pointer.jou b/tests/should_succeed/pointer.jou index 348bb009..250c4ca1 100644 --- a/tests/should_succeed/pointer.jou +++ b/tests/should_succeed/pointer.jou @@ -1,22 +1,22 @@ import "stdlib/io.jou" import "stdlib/mem.jou" -def putchar_pointer(ch: int*) -> void: +def putchar_pointer(ch: int*) -> None: putchar(*ch) putchar(*&*ch) -def putchar2(ch: int) -> void: +def putchar2(ch: int) -> None: putchar_pointer(&ch) -def myputs1(s: byte*) -> void: +def myputs1(s: byte*) -> None: for i = 0; s[i] != '\0'; i++: putchar(s[i]) -def myputs2(s: byte*) -> void: +def myputs2(s: byte*) -> None: while *s != '\0': putchar(*s++) -def foo(ptr: int*) -> void: +def foo(ptr: int*) -> None: if ptr == NULL: printf("Got NULL\n") else: diff --git a/tests/should_succeed/return_void.jou b/tests/should_succeed/return_none.jou similarity index 81% rename from tests/should_succeed/return_void.jou rename to tests/should_succeed/return_none.jou index d776f044..84a884e5 100644 --- a/tests/should_succeed/return_void.jou +++ b/tests/should_succeed/return_none.jou @@ -1,11 +1,11 @@ import "stdlib/io.jou" -def foo() -> void: +def foo() -> None: putchar('h') putchar('i') putchar('\n') -def should_do_nothing() -> void: +def should_do_nothing() -> None: return putchar('x') # Warning: this code will never run diff --git a/tests/should_succeed/sizeof.jou b/tests/should_succeed/sizeof.jou index 4d7d318c..3196c5a2 100644 --- a/tests/should_succeed/sizeof.jou +++ b/tests/should_succeed/sizeof.jou @@ -11,7 +11,7 @@ class Foo: c: byte # See issue #224. -def ensure_sizeof_isnt_too_small_in_a_weird_corner_case() -> void: +def ensure_sizeof_isnt_too_small_in_a_weird_corner_case() -> None: value = Foo{a=1, b=2, c='x'} # We need the heap allocation, because otherwise the optimizer happens to make things work. ptr = malloc(50) as Foo* diff --git a/tests/should_succeed/undefined_value_warning.jou b/tests/should_succeed/undefined_value_warning.jou index 0ad86984..4e589fe6 100644 --- a/tests/should_succeed/undefined_value_warning.jou +++ b/tests/should_succeed/undefined_value_warning.jou @@ -1,16 +1,16 @@ import "stdlib/io.jou" -def maybe_undefined(n: int) -> void: +def maybe_undefined(n: int) -> None: for i = 0; i < n; i++: message = "Hi" puts(message) # Warning: the value of 'message' may be undefined -def surely_undefined_loop() -> void: +def surely_undefined_loop() -> None: while False: message = "Hi" # Warning: this code will never run puts(message) # Warning: the value of 'message' is undefined -def surely_undefined_annotation() -> void: +def surely_undefined_annotation() -> None: x: byte* puts(x) # Warning: the value of 'x' is undefined diff --git a/tests/should_succeed/union.jou b/tests/should_succeed/union.jou index 0f8c2f57..8aef0fc6 100644 --- a/tests/should_succeed/union.jou +++ b/tests/should_succeed/union.jou @@ -11,7 +11,7 @@ class TaggedFoo: small: int big: long - def print(self) -> void: + def print(self) -> None: if self->is_big: printf("Big %lld\n", self->big) else: diff --git a/tests/should_succeed/unreachable_warning.jou b/tests/should_succeed/unreachable_warning.jou index 2bb95182..116ac47d 100644 --- a/tests/should_succeed/unreachable_warning.jou +++ b/tests/should_succeed/unreachable_warning.jou @@ -1,35 +1,35 @@ import "stdlib/io.jou" import "stdlib/process.jou" -def after_return() -> void: +def after_return() -> None: puts("hey1") # Output: hey1 return puts("hey2") # Warning: this code will never run -def after_infinite_loop() -> void: +def after_infinite_loop() -> None: while True: puts("hi") puts("yooooo wat") # Warning: this code will never run -def after_infinite_loop_with_variable() -> void: +def after_infinite_loop_with_variable() -> None: flag = True while flag: puts("hi") puts("yooooo wat") # Warning: this code will never run -def after_infinite_loop_with_variable_set_after_loop() -> void: +def after_infinite_loop_with_variable_set_after_loop() -> None: flag = True while flag: puts("hi") flag = False # Warning: this code will never run -def noreturn_function_called() -> void: +def noreturn_function_called() -> None: abort() x = 1 # Warning: this code will never run y = 2 # https://github.com/Akuli/jou/issues/18 -def lots_of_unreachable_code() -> void: +def lots_of_unreachable_code() -> None: return i = 0 # Warning: this code will never run while True: diff --git a/tests/syntax_error/2bad.jou b/tests/syntax_error/2bad.jou index 5c7bfac7..c1ff5846 100644 --- a/tests/syntax_error/2bad.jou +++ b/tests/syntax_error/2bad.jou @@ -1,3 +1,3 @@ -def x() -> void: +def x() -> None: 2bad = "oh no" # Error: invalid number or variable name "2bad" return 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/arg_default.jou b/tests/syntax_error/arg_default.jou index 0c42df9e..c11a50c9 100644 --- a/tests/syntax_error/arg_default.jou +++ b/tests/syntax_error/arg_default.jou @@ -1,2 +1,2 @@ -def foo(num: int = 1) -> void: # Error: arguments cannot have default values +def foo(num: int = 1) -> None: # Error: arguments cannot have default values return 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 diff --git a/tests/syntax_error/bad_argument_name.jou b/tests/syntax_error/bad_argument_name.jou index 71cdc4a2..ee427c16 100644 --- a/tests/syntax_error/bad_argument_name.jou +++ b/tests/syntax_error/bad_argument_name.jou @@ -1,2 +1,2 @@ -def f(5) -> void: # Error: expected an argument name, got an integer +def f(5) -> None: # Error: expected an argument name, got an integer return diff --git a/tests/syntax_error/bad_array.jou b/tests/syntax_error/bad_array.jou index 10a91b94..f0df8472 100644 --- a/tests/syntax_error/bad_array.jou +++ b/tests/syntax_error/bad_array.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = [1 2] # Error: expected a ']' to end the array, got an integer diff --git a/tests/syntax_error/bad_field.jou b/tests/syntax_error/bad_field.jou index cc176381..0762f864 100644 --- a/tests/syntax_error/bad_field.jou +++ b/tests/syntax_error/bad_field.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: bar.(1+2) # Error: expected a field or method name, got '(' diff --git a/tests/syntax_error/bad_function_name_after_def.jou b/tests/syntax_error/bad_function_name_after_def.jou index 35b44828..2c7ae9ee 100644 --- a/tests/syntax_error/bad_function_name_after_def.jou +++ b/tests/syntax_error/bad_function_name_after_def.jou @@ -1,2 +1,2 @@ -def 69() -> void: # Error: expected a function name, got an integer +def 69() -> None: # Error: expected a function name, got an integer return diff --git a/tests/syntax_error/c_and.jou b/tests/syntax_error/c_and.jou index 95231832..23dadec7 100644 --- a/tests/syntax_error/c_and.jou +++ b/tests/syntax_error/c_and.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: if x && y: # Error: use 'and' instead of '&&' pass diff --git a/tests/syntax_error/c_not.jou b/tests/syntax_error/c_not.jou index ede4175c..b1394b3c 100644 --- a/tests/syntax_error/c_not.jou +++ b/tests/syntax_error/c_not.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: if !x: # Error: use 'not' instead of '!' pass diff --git a/tests/syntax_error/c_or.jou b/tests/syntax_error/c_or.jou index 72304af3..eea3b378 100644 --- a/tests/syntax_error/c_or.jou +++ b/tests/syntax_error/c_or.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: if x || y: # Error: use 'or' instead of '||' pass diff --git a/tests/syntax_error/call_missing_comma.jou b/tests/syntax_error/call_missing_comma.jou index 728c63b2..5e62716c 100644 --- a/tests/syntax_error/call_missing_comma.jou +++ b/tests/syntax_error/call_missing_comma.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: printf("hello %d\n" 1) # Error: expected a ')', got an integer diff --git a/tests/syntax_error/class_init_js_syntax.jou b/tests/syntax_error/class_init_js_syntax.jou index d83107ee..63fd412e 100644 --- a/tests/syntax_error/class_init_js_syntax.jou +++ b/tests/syntax_error/class_init_js_syntax.jou @@ -2,5 +2,5 @@ class Foo: x: int # attempting to use javascript-style for initing class -def foo() -> void: +def foo() -> None: foo = Foo{x: 1} # Error: expected '=' followed by a value for field 'x', got ':' diff --git a/tests/syntax_error/dot_after_e.jou b/tests/syntax_error/dot_after_e.jou index 9fbeaa72..4a4ffc74 100644 --- a/tests/syntax_error/dot_after_e.jou +++ b/tests/syntax_error/dot_after_e.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = 1e2.3 # Error: invalid number or variable name "1e2.3" diff --git a/tests/syntax_error/dotdotdot_dotdotdot.jou b/tests/syntax_error/dotdotdot_dotdotdot.jou index 0bfdf1da..46c50dba 100644 --- a/tests/syntax_error/dotdotdot_dotdotdot.jou +++ b/tests/syntax_error/dotdotdot_dotdotdot.jou @@ -1 +1 @@ -declare foo(..., ...) -> void # Error: if '...' is used, it must be the last parameter +declare foo(..., ...) -> None # Error: if '...' is used, it must be the last parameter diff --git a/tests/syntax_error/double_assignment.jou b/tests/syntax_error/double_assignment.jou index e2655336..6df5ea47 100644 --- a/tests/syntax_error/double_assignment.jou +++ b/tests/syntax_error/double_assignment.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = y = 7 # Error: only one variable can be assigned at a time diff --git a/tests/syntax_error/double_with_letters_after.jou b/tests/syntax_error/double_with_letters_after.jou index cb4bd3dc..b1b4dc45 100644 --- a/tests/syntax_error/double_with_letters_after.jou +++ b/tests/syntax_error/double_with_letters_after.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = 123.456hello # Error: invalid number or variable name "123.456hello" diff --git a/tests/syntax_error/ee.jou b/tests/syntax_error/ee.jou index 7d8c6b83..9548a756 100644 --- a/tests/syntax_error/ee.jou +++ b/tests/syntax_error/ee.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = 1ee2.3 # Error: invalid number or variable name "1ee2.3" diff --git a/tests/syntax_error/first_line_indent.jou b/tests/syntax_error/first_line_indent.jou index 07048ef2..9ca329a2 100644 --- a/tests/syntax_error/first_line_indent.jou +++ b/tests/syntax_error/first_line_indent.jou @@ -1,4 +1,4 @@ - def foo() -> void: # Error: expected an expression, got more indentation + def foo() -> None: # Error: expected an expression, got more indentation return # TODO: this error message is not very good... diff --git a/tests/syntax_error/import_after_def.jou b/tests/syntax_error/import_after_def.jou index ce419491..9088cddf 100644 --- a/tests/syntax_error/import_after_def.jou +++ b/tests/syntax_error/import_after_def.jou @@ -1,4 +1,4 @@ -def foo() -> void: +def foo() -> None: return import "stdlib/io.jou" # Error: imports must be in the beginning of the file diff --git a/tests/syntax_error/indexing.jou b/tests/syntax_error/indexing.jou index a5a7208d..51517191 100644 --- a/tests/syntax_error/indexing.jou +++ b/tests/syntax_error/indexing.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: asd[lol 123] # Error: expected a ']', got an integer diff --git a/tests/syntax_error/mismatched_close_brace.jou b/tests/syntax_error/mismatched_close_brace.jou index 66911363..cf2faf01 100644 --- a/tests/syntax_error/mismatched_close_brace.jou +++ b/tests/syntax_error/mismatched_close_brace.jou @@ -1 +1 @@ -def foo(} -> void: # Error: '}' without a matching '{' +def foo(} -> None: # Error: '}' without a matching '{' diff --git a/tests/syntax_error/missing_field_names.jou b/tests/syntax_error/missing_field_names.jou index e33c31e3..26ee6d13 100644 --- a/tests/syntax_error/missing_field_names.jou +++ b/tests/syntax_error/missing_field_names.jou @@ -2,5 +2,5 @@ class Point: x: int y: int -def foo() -> void: +def foo() -> None: p = Point{1, 2} # Error: expected a field name, got an integer diff --git a/tests/syntax_error/missing_number_after_e.jou b/tests/syntax_error/missing_number_after_e.jou index 7fc900c6..21311bbc 100644 --- a/tests/syntax_error/missing_number_after_e.jou +++ b/tests/syntax_error/missing_number_after_e.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = 123e # Error: invalid number or variable name "123e" diff --git a/tests/syntax_error/missing_number_after_eminus.jou b/tests/syntax_error/missing_number_after_eminus.jou index f76320da..3f4d56cc 100644 --- a/tests/syntax_error/missing_number_after_eminus.jou +++ b/tests/syntax_error/missing_number_after_eminus.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = 123e- # Error: invalid number or variable name "123e-" diff --git a/tests/syntax_error/missing_return_type.jou b/tests/syntax_error/missing_return_type.jou index 03724936..fb381a64 100644 --- a/tests/syntax_error/missing_return_type.jou +++ b/tests/syntax_error/missing_return_type.jou @@ -1,2 +1,2 @@ -def foo(): # Error: return type must be specified with '->', or with '-> void' if the function doesn't return anything +def foo(): # Error: return type must be specified with '->', or with '-> None' if the function doesn't return anything return diff --git a/tests/syntax_error/missing_second_equal_sign.jou b/tests/syntax_error/missing_second_equal_sign.jou index f0016f33..17182b2d 100644 --- a/tests/syntax_error/missing_second_equal_sign.jou +++ b/tests/syntax_error/missing_second_equal_sign.jou @@ -1,4 +1,4 @@ -def foo() -> void: +def foo() -> None: x = 1 # TODO: improve the error message? if x = 1: # Error: expected ':' followed by a new line with more indentation, got '=' diff --git a/tests/syntax_error/missing_self.jou b/tests/syntax_error/missing_self.jou index bc9d53b1..b48aa2db 100644 --- a/tests/syntax_error/missing_self.jou +++ b/tests/syntax_error/missing_self.jou @@ -1,5 +1,5 @@ class Foo: - def bar() -> void: # Error: missing self, should be 'def bar(self, ...)' + def bar() -> None: # Error: missing self, should be 'def bar(self, ...)' return def main() -> int: diff --git a/tests/syntax_error/self_outside_class.jou b/tests/syntax_error/self_outside_class.jou index d5b557cb..857deb9a 100644 --- a/tests/syntax_error/self_outside_class.jou +++ b/tests/syntax_error/self_outside_class.jou @@ -1,2 +1,2 @@ -def foo(self) -> void: # Error: 'self' cannot be used here +def foo(self) -> None: # Error: 'self' cannot be used here return diff --git a/tests/syntax_error/self_take_arg.jou b/tests/syntax_error/self_take_arg.jou index c39c22bb..e27296af 100644 --- a/tests/syntax_error/self_take_arg.jou +++ b/tests/syntax_error/self_take_arg.jou @@ -1,5 +1,5 @@ class Foo: - def bar(self, x: int) -> void: + def bar(self, x: int) -> None: return def main() -> int: diff --git a/tests/syntax_error/too_many_closing_parens.jou b/tests/syntax_error/too_many_closing_parens.jou index 15a97a5f..aa96a119 100644 --- a/tests/syntax_error/too_many_closing_parens.jou +++ b/tests/syntax_error/too_many_closing_parens.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: bar(1)) # Error: ')' without a matching '(' diff --git a/tests/syntax_error/unnecessary_quote_escape_byte.jou b/tests/syntax_error/unnecessary_quote_escape_byte.jou index d49d4d06..4d9c540c 100644 --- a/tests/syntax_error/unnecessary_quote_escape_byte.jou +++ b/tests/syntax_error/unnecessary_quote_escape_byte.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = '\"' # Error: double quotes shouldn't be escaped in byte literals diff --git a/tests/syntax_error/unnecessary_quote_escape_string.jou b/tests/syntax_error/unnecessary_quote_escape_string.jou index 110a2fa8..0d05226e 100644 --- a/tests/syntax_error/unnecessary_quote_escape_string.jou +++ b/tests/syntax_error/unnecessary_quote_escape_string.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = "hello \'world" # Error: single quotes shouldn't be escaped in strings diff --git a/tests/too_long/huge_int.jou b/tests/too_long/huge_int.jou index fbabd4e8..0e3cd235 100644 --- a/tests/too_long/huge_int.jou +++ b/tests/too_long/huge_int.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = 123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123 # Error: number is too long: 12312312312312312312... diff --git a/tests/too_long/int.jou b/tests/too_long/int.jou index bc2e2178..28fe57f4 100644 --- a/tests/too_long/int.jou +++ b/tests/too_long/int.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: x = 1000000000 # no error y = 1000000000000000 # Error: value does not fit in a signed 32-bit integer diff --git a/tests/too_long/long.jou b/tests/too_long/long.jou index 8857f213..0bf382a4 100644 --- a/tests/too_long/long.jou +++ b/tests/too_long/long.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: x = 1000000000000000L # no error y = 100000000000000000000L # Error: value does not fit in a signed 64-bit integer diff --git a/tests/too_long/name.jou b/tests/too_long/name.jou index f99f7875..0d44ac6b 100644 --- a/tests/too_long/name.jou +++ b/tests/too_long/name.jou @@ -1,2 +1,2 @@ -def asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd() -> void: # Error: name is too long: asdasdasdasdasdasdas... +def asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd() -> None: # Error: name is too long: asdasdasdasdasdasdas... return diff --git a/tests/too_long/short.jou b/tests/too_long/short.jou index 4c2c5c29..948ca0ae 100644 --- a/tests/too_long/short.jou +++ b/tests/too_long/short.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: x = 10000S # no error y = 100000S # Error: value does not fit in a signed 16-bit integer diff --git a/tests/wrong_type/arg.jou b/tests/wrong_type/arg.jou index a76f562a..9b9b5bf6 100644 --- a/tests/wrong_type/arg.jou +++ b/tests/wrong_type/arg.jou @@ -1,5 +1,5 @@ -def foo(x: int*) -> void: +def foo(x: int*) -> None: return -def bar() -> void: +def bar() -> None: foo(1) # Error: first argument of function foo(x: int*) should have type int*, not int diff --git a/tests/wrong_type/arg_with_varargs.jou b/tests/wrong_type/arg_with_varargs.jou index 27de3b3f..15759ce3 100644 --- a/tests/wrong_type/arg_with_varargs.jou +++ b/tests/wrong_type/arg_with_varargs.jou @@ -1,4 +1,4 @@ import "stdlib/io.jou" -def foo() -> void: +def foo() -> None: printf(1) # Error: first argument of function printf(pattern: byte*, ...) should have type byte*, not int diff --git a/tests/wrong_type/array_mixed_types.jou b/tests/wrong_type/array_mixed_types.jou index 00f763f8..2255304f 100644 --- a/tests/wrong_type/array_mixed_types.jou +++ b/tests/wrong_type/array_mixed_types.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = [1, "hey", "ho", 123] # Error: array items have different types (int, byte*) diff --git a/tests/wrong_type/array_mixed_types_ptr.jou b/tests/wrong_type/array_mixed_types_ptr.jou index 3efe3e55..4791a156 100644 --- a/tests/wrong_type/array_mixed_types_ptr.jou +++ b/tests/wrong_type/array_mixed_types_ptr.jou @@ -1,4 +1,4 @@ -def foo() -> void: +def foo() -> None: # When we make an array of int* and void*: # - we could cast int* to void*, and get an array of void* # - we could cast void* to int*, and get an array of int* diff --git a/tests/wrong_type/arrow_operator_not_class.jou b/tests/wrong_type/arrow_operator_not_class.jou index ac68b59f..d2e6fcdf 100644 --- a/tests/wrong_type/arrow_operator_not_class.jou +++ b/tests/wrong_type/arrow_operator_not_class.jou @@ -1,4 +1,4 @@ -def foo() -> void: +def foo() -> None: num = 1 pointer = &num x = pointer->lol # Error: left side of the '->' operator must be a pointer to a class, not int* diff --git a/tests/wrong_type/arrow_operator_not_pointer.jou b/tests/wrong_type/arrow_operator_not_pointer.jou index 72a915a9..79a816f7 100644 --- a/tests/wrong_type/arrow_operator_not_pointer.jou +++ b/tests/wrong_type/arrow_operator_not_pointer.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: num = 1 x = num->lol # Error: left side of the '->' operator must be a pointer to a class, not int diff --git a/tests/wrong_type/arrow_operator_not_pointer_method.jou b/tests/wrong_type/arrow_operator_not_pointer_method.jou index ba008e6a..b9b91ddf 100644 --- a/tests/wrong_type/arrow_operator_not_pointer_method.jou +++ b/tests/wrong_type/arrow_operator_not_pointer_method.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: num = 1 x = num->lol() # Error: left side of the '->' operator must be a pointer, not int diff --git a/tests/wrong_type/assign_void.jou b/tests/wrong_type/assign_none_return.jou similarity index 66% rename from tests/wrong_type/assign_void.jou rename to tests/wrong_type/assign_none_return.jou index b83c3d94..c89a4d93 100644 --- a/tests/wrong_type/assign_void.jou +++ b/tests/wrong_type/assign_none_return.jou @@ -1,5 +1,5 @@ -def foo() -> void: +def foo() -> None: return -def bar() -> void: +def bar() -> None: x = foo() # Error: function 'foo' does not return a value diff --git a/tests/wrong_type/assign_with_type.jou b/tests/wrong_type/assign_with_type.jou index 3bf5fcc0..30c89cf8 100644 --- a/tests/wrong_type/assign_with_type.jou +++ b/tests/wrong_type/assign_with_type.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x: int = "hey" # Error: initial value for variable of type int cannot be of type byte* diff --git a/tests/wrong_type/brace_init_arg.jou b/tests/wrong_type/brace_init_arg.jou index d36d78a6..81954336 100644 --- a/tests/wrong_type/brace_init_arg.jou +++ b/tests/wrong_type/brace_init_arg.jou @@ -1,5 +1,5 @@ class Foo: x: int -def foo() -> void: +def foo() -> None: wat = Foo{x="hey"} # Error: value for field 'x' of class Foo must be of type int, not byte* diff --git a/tests/wrong_type/cannot_be_indexed.jou b/tests/wrong_type/cannot_be_indexed.jou index 204b1578..0a812c7f 100644 --- a/tests/wrong_type/cannot_be_indexed.jou +++ b/tests/wrong_type/cannot_be_indexed.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = 1["hey"] # Error: value of type int cannot be indexed diff --git a/tests/wrong_type/class_member_assign.jou b/tests/wrong_type/class_member_assign.jou index 8e42b161..b35aba72 100644 --- a/tests/wrong_type/class_member_assign.jou +++ b/tests/wrong_type/class_member_assign.jou @@ -1,6 +1,6 @@ class Foo: x: int -def blah() -> void: +def blah() -> None: f = Foo{x = 1} f.x = "hey" # Error: cannot assign a value of type byte* to field 'x' of type int diff --git a/tests/wrong_type/class_member_init.jou b/tests/wrong_type/class_member_init.jou index 42c95ab8..053c3f0f 100644 --- a/tests/wrong_type/class_member_init.jou +++ b/tests/wrong_type/class_member_init.jou @@ -1,5 +1,5 @@ class Foo: x: int -def blah() -> void: +def blah() -> None: f = Foo{x = "hey"} # Error: value for field 'x' of class Foo must be of type int, not byte* diff --git a/tests/wrong_type/dot_operator.jou b/tests/wrong_type/dot_operator.jou index e557c8ca..971fb8b9 100644 --- a/tests/wrong_type/dot_operator.jou +++ b/tests/wrong_type/dot_operator.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: x = 123 y = x.lolwat # Error: left side of the '.' operator must be an instance of a class, not int diff --git a/tests/wrong_type/explicit_array_to_pointer_cast.jou b/tests/wrong_type/explicit_array_to_pointer_cast.jou index b9fc9998..abd7f027 100644 --- a/tests/wrong_type/explicit_array_to_pointer_cast.jou +++ b/tests/wrong_type/explicit_array_to_pointer_cast.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: x = [1, 2, 3] y = x as byte* # Error: cannot cast from type int[3] to byte* diff --git a/tests/wrong_type/float_and_double.jou b/tests/wrong_type/float_and_double.jou index 460a96ae..b4a1d515 100644 --- a/tests/wrong_type/float_and_double.jou +++ b/tests/wrong_type/float_and_double.jou @@ -1,5 +1,5 @@ -def foo(x: float) -> void: +def foo(x: float) -> None: return -def bar() -> void: +def bar() -> None: foo(12.34 + 56F) # Error: first argument of function foo(x: float) should have type float, not double diff --git a/tests/wrong_type/index.jou b/tests/wrong_type/index.jou index 8a763126..f2ad91e9 100644 --- a/tests/wrong_type/index.jou +++ b/tests/wrong_type/index.jou @@ -1,2 +1,2 @@ -def foo() -> void: +def foo() -> None: x = "hey"["hey"] # Error: the index inside [...] must be an integer, not byte* diff --git a/tests/wrong_type/inplace_add_doesnt_go_back.jou b/tests/wrong_type/inplace_add_doesnt_go_back.jou index 5487e79c..96edbce7 100644 --- a/tests/wrong_type/inplace_add_doesnt_go_back.jou +++ b/tests/wrong_type/inplace_add_doesnt_go_back.jou @@ -1,4 +1,4 @@ -def foo() -> void: +def foo() -> None: x: byte = 'a' x += 123 as byte # no error x += 123 # Error: addition produced a value of type int which cannot be assigned back to byte diff --git a/tests/wrong_type/inplace_add_str_int.jou b/tests/wrong_type/inplace_add_str_int.jou index 22d377ee..18acf968 100644 --- a/tests/wrong_type/inplace_add_str_int.jou +++ b/tests/wrong_type/inplace_add_str_int.jou @@ -1,3 +1,3 @@ -def foo(s: byte*) -> void: +def foo(s: byte*) -> None: # The "Jou way" would be: s = &s[5] s += 5 # Error: wrong types: cannot add byte* and int diff --git a/tests/wrong_type/inplace_mul_str_str.jou b/tests/wrong_type/inplace_mul_str_str.jou index 8c182ec1..fbcc2314 100644 --- a/tests/wrong_type/inplace_mul_str_str.jou +++ b/tests/wrong_type/inplace_mul_str_str.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: x = "hello" x *= "world" # Error: wrong types: cannot multiply byte* and byte* diff --git a/tests/wrong_type/instantiate_enum.jou b/tests/wrong_type/instantiate_enum.jou index 578ed7f3..5381d97e 100644 --- a/tests/wrong_type/instantiate_enum.jou +++ b/tests/wrong_type/instantiate_enum.jou @@ -2,5 +2,5 @@ enum Foo: Bar Baz -def asdf() -> void: +def asdf() -> None: f = Foo{x=1} # Error: the Foo{...} syntax is only for classes, but Foo is an enum diff --git a/tests/wrong_type/main_returns_none.jou b/tests/wrong_type/main_returns_none.jou new file mode 100644 index 00000000..ce41b97c --- /dev/null +++ b/tests/wrong_type/main_returns_none.jou @@ -0,0 +1,2 @@ +def main() -> None: # Error: the main() function must return int + return diff --git a/tests/wrong_type/plusplus.jou b/tests/wrong_type/plusplus.jou index 79906205..b155b8ca 100644 --- a/tests/wrong_type/plusplus.jou +++ b/tests/wrong_type/plusplus.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: yep = True ++yep # Error: cannot increment a value of type bool diff --git a/tests/wrong_type/pointer_assignment.jou b/tests/wrong_type/pointer_assignment.jou index 7750a939..932ac4b0 100644 --- a/tests/wrong_type/pointer_assignment.jou +++ b/tests/wrong_type/pointer_assignment.jou @@ -1,4 +1,4 @@ -def foo() -> void: +def foo() -> None: x = 1 y = &x *y = "hey" # Error: cannot place a value of type byte* into a pointer of type int* diff --git a/tests/wrong_type/pointer_eq.jou b/tests/wrong_type/pointer_eq.jou index 7ff989bc..3ab8b039 100644 --- a/tests/wrong_type/pointer_eq.jou +++ b/tests/wrong_type/pointer_eq.jou @@ -1,4 +1,4 @@ -def foo() -> void: +def foo() -> None: x: int* = NULL y: byte* = NULL z = (x==y) # Error: wrong types: cannot compare int* and byte* diff --git a/tests/wrong_type/var_assignment.jou b/tests/wrong_type/var_assignment.jou index 1d5c71b8..4db6e1e1 100644 --- a/tests/wrong_type/var_assignment.jou +++ b/tests/wrong_type/var_assignment.jou @@ -1,3 +1,3 @@ -def foo() -> void: +def foo() -> None: x = 1 x = "hey" # Error: cannot assign a value of type byte* to a variable of type int diff --git a/tests/wrong_type/void_main.jou b/tests/wrong_type/void_main.jou deleted file mode 100644 index a5c6d157..00000000 --- a/tests/wrong_type/void_main.jou +++ /dev/null @@ -1,2 +0,0 @@ -def main() -> void: # Error: the main() function must return int - return