function pointers and callbacks

This commit is contained in:
2026-06-15 21:09:46 +02:00
parent 3b7c3fcbd0
commit f5605fd3ec
21 changed files with 1927 additions and 122 deletions
+48 -6
View File
@@ -90,7 +90,7 @@ is_type_token :: proc(kind: token.Kind) -> bool {
.Keyword_C_Short, .Keyword_C_Ushort, .Keyword_C_Int, .Keyword_C_Uint,
.Keyword_C_Long, .Keyword_C_Ulong, .Keyword_C_Longlong, .Keyword_C_Ulonglong,
.Keyword_C_Float, .Keyword_C_Double, .Keyword_C_Longdouble,
.Keyword_Void, .Identifier, .Question, .At, .Star, .Left_Bracket:
.Keyword_Void, .Keyword_C_Func, .Identifier, .Question, .At, .Star, .Left_Bracket:
return true
}
return false
@@ -291,6 +291,25 @@ parse_type :: proc(parser: ^Parser) -> ast.Type_Syntax {
case .Keyword_Void:
advance(parser)
return types.VOID
case .Keyword_C_Func:
advance(parser)
if _, ok := allow(parser, .Left_Paren); !ok {
source.add(parser.diagnostics, current(parser).span, "expected '(' after c_func type")
return types.INVALID
}
params, variadic := parse_params(parser)
if _, ok := allow(parser, .Right_Paren); !ok {
source.add(parser.diagnostics, current(parser).span, "expected ')' after function type parameters")
}
result := parse_type(parser)
param_types := make([]types.Type, len(params), parser.module.allocator)
for param, index in params {
param_types[index] = param.type
}
function_type := types.function(&parser.module.type_store, param_types, result, true, variadic)
delete(param_types, parser.module.allocator)
delete(params, parser.module.allocator)
return function_type
case .Identifier:
first := advance(parser)
name := first
@@ -334,11 +353,7 @@ skip_parenthesized :: proc(parser: ^Parser) -> source.Span {
return span_from(start.span, end.span)
}
parse_call :: proc(parser: ^Parser, qualifier: symbol.Id, first, name: token.Token, nesting: int) -> ast.Expr_Id {
if nesting >= MAX_EXPRESSION_NESTING {
span := skip_parenthesized(parser)
return invalid_expr(parser, span, "expression nesting exceeds 256 levels")
}
parse_call_args :: proc(parser: ^Parser, nesting: int) -> ([]ast.Expr_Id, token.Token) {
left_paren := advance(parser)
parser.delimiter_depth += 1
defer parser.delimiter_depth -= 1
@@ -359,6 +374,15 @@ parse_call :: proc(parser: ^Parser, qualifier: symbol.Id, first, name: token.Tok
source.add(parser.diagnostics, current(parser).span, "expected ')' after call arguments")
right_paren = left_paren
}
return args[:], right_paren
}
parse_call :: proc(parser: ^Parser, qualifier: symbol.Id, first, name: token.Token, nesting: int) -> ast.Expr_Id {
if nesting >= MAX_EXPRESSION_NESTING {
span := skip_parenthesized(parser)
return invalid_expr(parser, span, "expression nesting exceeds 256 levels")
}
args, right_paren := parse_call_args(parser, nesting)
return add_expr(parser, ast.Expr{
kind=.Call,
span=source.Span{file=name.span.file, start=first.span.start, end=right_paren.span.end},
@@ -735,6 +759,24 @@ parse_expression_bp :: proc(parser: ^Parser, minimum_binding_power, nesting: int
}
continue
}
if current(parser).kind == .Left_Paren {
if nesting >= MAX_EXPRESSION_NESTING {
span := skip_parenthesized(parser)
left = invalid_expr(parser, span, "expression nesting exceeds 256 levels")
continue
}
left_expr := parser.module.exprs[left]
args, right_paren := parse_call_args(parser, nesting)
left = add_expr(parser, ast.Expr{
kind=.Call,
span=span_from(left_expr.span, right_paren.span),
args=args,
left=left,
right=ast.INVALID_EXPR,
diagnostic=source.INVALID_DIAGNOSTIC,
})
continue
}
left_power, right_power, ok := infix_binding_power(current(parser).kind)
if !ok || left_power < minimum_binding_power {
break