diff --git a/ir/emit.cc b/ir/emit.cc index a0592cd2..f66b46d1 100644 --- a/ir/emit.cc +++ b/ir/emit.cc @@ -576,6 +576,12 @@ void HandleParseTreeNodeFunctionTypeParameters(ParseNodeIndex index, .returns = 1}); } +void HandleParseTreeNodeEmptyParenthesis(ParseNodeIndex index, + EmitContext& context) { + jasmin::Value v = type::Bottom; + context.Push(std::span(&v, 1), type::Type_); +} + void HandleParseTreeNodeEnumLiteralStart(ParseNodeIndex, EmitContext&) { NTH_UNIMPLEMENTED(); } diff --git a/ir/function.cc b/ir/function.cc index 17a601e9..11c404a0 100644 --- a/ir/function.cc +++ b/ir/function.cc @@ -125,4 +125,18 @@ void InvokeForeignFunction::consume(std::span input, } } +type::Type ConstructFunctionType::consume(std::span inputs) { + auto parameter = inputs[0].as(); + auto return_type = inputs[1].as(); + std::vector returns; + if (return_type != type::Bottom) { returns.push_back(return_type); } + if (parameter.kind() == type::Type::Kind::Parameters) { + return type::Function(parameter.AsParameters(), std::move(returns)); + } else { + return type::Function( + type::Parameters({{.name = Identifier("").value(), .type = parameter}}), + std::move(returns)); + } +} + } // namespace ic diff --git a/ir/function.h b/ir/function.h index 3c5b9872..045eccd1 100644 --- a/ir/function.h +++ b/ir/function.h @@ -102,17 +102,7 @@ struct ConstructParametersType : jasmin::Instruction { struct ConstructFunctionType : jasmin::Instruction { static std::string_view name() { return "construct-function-type"; } - static type::Type consume(std::span inputs) { - auto parameter = inputs[0].as(); - auto return_type = inputs[1].as(); - if (parameter.kind() == type::Type::Kind::Parameters) { - return type::Function(parameter.AsParameters(), std::vector{return_type}); - } else { - return type::Function(type::Parameters({{.name = Identifier("").value(), - .type = parameter}}), - std::vector{return_type}); - } - } + static type::Type consume(std::span inputs); }; struct ConstructOpaqueType : jasmin::Instruction { diff --git a/ir/ir.cc b/ir/ir.cc index 62bedea5..42c09b55 100644 --- a/ir/ir.cc +++ b/ir/ir.cc @@ -470,7 +470,9 @@ void HandleParseTreeNodeExpressionPrecedenceGroup( }); } NTH_REQUIRE(context.type_stack().group_count() >= 2); - type::Type return_type = context.type_stack().top()[0].type(); + std::span return_types = context.type_stack().top(); + std::optional return_type; + if (not return_types.empty()) { return_type = return_types[0].type(); } context.type_stack().pop(); type::Type parameters_type = context.type_stack().top()[0].type(); auto iter = context.Children(index).begin(); @@ -485,7 +487,8 @@ void HandleParseTreeNodeExpressionPrecedenceGroup( }); } - if (return_type != type::Type_) { + if (return_type and return_type != type::Type_) { + NTH_LOG("{}") <<= {return_type}; auto iter = context.Children(index).begin(); diag.Consume({ diag::Header(diag::MessageKind::Error), @@ -820,6 +823,12 @@ void HandleParseTreeNodeCallExpression(ParseNodeIndex index, IrContext& context, } } +void HandleParseTreeNodeEmptyParenthesis(ParseNodeIndex index, + IrContext& context, + diag::DiagnosticConsumer& diag) { + context.type_stack().push({}); +} + void HandleParseTreeNodeDeclaredIdentifier(ParseNodeIndex index, IrContext& context, diag::DiagnosticConsumer& diag) { diff --git a/parse/node.xmacro.h b/parse/node.xmacro.h index 80ec5b5f..fe508bf4 100644 --- a/parse/node.xmacro.h +++ b/parse/node.xmacro.h @@ -83,6 +83,7 @@ IC_XMACRO_PARSE_NODE_EXPRESSION(Identifier) IC_XMACRO_PARSE_NODE_EXPRESSION(ExpressionPrecedenceGroup) IC_XMACRO_PARSE_NODE_EXPRESSION(MemberExpression) IC_XMACRO_PARSE_NODE_EXPRESSION(EnumLiteral) +IC_XMACRO_PARSE_NODE_EXPRESSION(EmptyParenthesis) IC_XMACRO_PARSE_NODE_EXPRESSION(Scope) diff --git a/parse/parser.cc b/parse/parser.cc index e6550fd6..cd0dcfa2 100644 --- a/parse/parser.cc +++ b/parse/parser.cc @@ -509,6 +509,13 @@ void Parser::HandleParenthesizedExpression(ParseTree& tree) { if (current_token().kind() == Token::Kind::LeftParen) { ++iterator_; IgnoreAnyNewlines(); + if (current_token().kind() == Token::Kind::RightParen) { + auto state = pop_state(); + tree.append(ParseNode::Kind::EmptyParenthesis, state.token, + state.subtree_start); + ++iterator_; + return; + } ExpandState(Expression(tree), State::Kind::ClosingParenthesis); } else { NTH_UNIMPLEMENTED(); diff --git a/toolchain/stdlib/compat/c/errno.ic b/toolchain/stdlib/compat/c/errno.ic index 395ad637..2987d31f 100644 --- a/toolchain/stdlib/compat/c/errno.ic +++ b/toolchain/stdlib/compat/c/errno.ic @@ -3,5 +3,5 @@ let c ::= import "std.compat.c.types" let errno ::= builtin.foreign("errno", *c.int) -// let perror ::= builtin.foreign("perror", [*]char -> ()) +let perror ::= builtin.foreign("perror", [*]char -> ()) let strerror ::= builtin.foreign("strerror", c.int -> [*]char) diff --git a/toolchain/stdlib/compat/c/stdio.template.ic b/toolchain/stdlib/compat/c/stdio.template.ic index fae48e69..7cc92aff 100644 --- a/toolchain/stdlib/compat/c/stdio.template.ic +++ b/toolchain/stdlib/compat/c/stdio.template.ic @@ -25,11 +25,11 @@ let fopen ::= builtin.foreign("fopen", ([*]char, [*]char) -> *FILE) let freopen ::= builtin.foreign("freopen", ([*]char, [*]char, *FILE) -> *FILE) let fclose ::= builtin.foreign("fclose", *FILE -> c.int) let fflush ::= builtin.foreign("fflush", *FILE -> c.int) -// let setbuf ::= builtin.foreign("setbuf", (*FILE, [*]char) -> ()) -// let setvbuf ::= builtin.foreign("setvbuf", (*FILE, [*]char, c.int, c.size_t) -> c.int) +let setbuf ::= builtin.foreign("setbuf", (*FILE, [*]char) -> ()) +let setvbuf ::= builtin.foreign("setvbuf", (*FILE, [*]char, c.int, size_t) -> c.int) -// let fread ::= builtin.foreign("fread", ([*]byte, c.size_t, c.size_t, *FILE) -> c.size_t) -// let fwrite ::= builtin.foreign("fwrite", ([*]byte, c.size_t, c.size_t, *FILE) -> c.size_t) +let fread ::= builtin.foreign("fread", ([*]byte, size_t, size_t, *FILE) -> size_t) +let fwrite ::= builtin.foreign("fwrite", ([*]byte, size_t, size_t, *FILE) -> size_t) let fgetc ::= builtin.foreign("fgetc", *FILE -> c.int) let getc ::= builtin.foreign("getc", *FILE -> c.int) @@ -48,9 +48,9 @@ let fseek ::= builtin.foreign("fseek", (*FILE, c.long, c.int) -> c.int) let fsetpos ::= builtin.foreign("fsetpos", (*FILE, *fpos_t) -> c.int) let rewind ::= builtin.foreign("rewind", *FILE -> c.int) -// let clearerr ::= builtin.foreign("clearerr", *FILE -> ()) +let clearerr ::= builtin.foreign("clearerr", *FILE -> ()) let feof ::= builtin.foreign("feof", *FILE -> c.int) -// let ferror ::= builtin.foreign("ferror", *FILE -> ()) +let ferror ::= builtin.foreign("ferror", *FILE -> ()) let perror ::= builtin.foreign("perror", [*]char -> c.int) let remove ::= builtin.foreign("remove", [*]char -> c.int)