@@ -340,7 +340,7 @@ fn void Parser.parseTopLevel(Parser* p) {
340340 p.error("assert can only be used inside a function");
341341 break;
342342 case KW_fn:
343- p.parseFuncDecl(is_public);
343+ p.parseFuncDecl(is_public, false );
344344 break;
345345 case KW_import:
346346 p.error("no imports allowed after declarations");
@@ -448,43 +448,97 @@ fn void Parser.applyAttributes(Parser* p, Decl* d, u32 count) {
448448 if (count) p.builder.applyAttributes(d, count);
449449}
450450
451- fn void Parser.parseFuncDecl(Parser* p, bool is_public) {
451+ fn u32 Parser.createLocalName(Parser* p, u32 name, SrcLoc loc) {
452+ char[128] buf;
453+ snprintf(buf, sizeof(buf), "%s__%d", p.pool.idx2str(name), loc);
454+ return p.pool.addStr(buf, true);
455+ }
456+
457+ fn Expr* Parser.parseLocalFuncExpr(Parser* p) {
458+ SrcLoc loc = p.tok.loc;
459+ FunctionDecl* f = p.parseFuncDecl(false, true);
460+ Decl* d = f.asDecl();
461+ u32 name = d.getNameIdx();
462+ u32 local_name = p.createLocalName(name, loc);
463+ d.setNameIdx(local_name);
464+ p.builder.addSymbol(local_name, d);
465+ Expr* fexpr = p.builder.actOnIdentifier(loc, local_name).asExpr();
466+ return fexpr;
467+ }
468+
469+ fn Stmt* Parser.parseLocalFuncStmt(Parser* p) {
470+ SrcLoc loc = p.tok.loc;
471+ FunctionDecl* f = p.parseFuncDecl(false, true);
472+ Decl* d = f.asDecl();
473+ u32 name = d.getNameIdx();
474+ u32 local_name = p.createLocalName(name, loc);
475+ d.setNameIdx(local_name);
476+ p.builder.addSymbol(local_name, d);
477+ Expr* fexpr = p.builder.actOnIdentifier(loc, local_name).asExpr();
478+ // TODO: use auto typing
479+ TypeRefHolder ref.init();
480+ ref.setVoid(loc);
481+ ref.addPointer();
482+ VarDecl* decl = p.builder.actOnVarDecl(name, loc, &ref, loc, fexpr, false, false);
483+ return p.builder.actOnDeclStmt(&decl, 1);
484+ }
485+
486+ fn FunctionDecl* Parser.parseFuncDecl(Parser* p, bool is_public, bool is_local) {
487+ u32 func_name = 0;
488+ SrcLoc func_loc = p.tok.loc;
489+ Ref prefix_ref;
490+ Ref* prefix = nil;
491+
452492 p.consumeToken();
453493
454494 TypeRefHolder rtype.init();
455495 // Note: dont check arrays in this phase, but in Analyser
456496 p.parseTypeSpecifier(&rtype);
457497
458- p.expectIdentifier();
459- u32 func_name = p.tok.name_idx;
460- SrcLoc func_loc = p.tok.loc;
461- p.consumeToken();
462-
463- Ref prefix_ref;
464- Ref* prefix = nil;
465- if (p.tok.kind == Kind.Dot) {
466- p.consumeToken();
498+ if (p.tok.kind == Kind.Identifier || !is_local) {
467499 p.expectIdentifier();
468-
469- prefix_ref.loc = func_loc;
470- prefix_ref.name_idx = func_name;
471- prefix_ref.decl = nil;
472- prefix = &prefix_ref;
473500 func_name = p.tok.name_idx;
474501 func_loc = p.tok.loc;
475502 p.consumeToken();
476- }
477503
478- if (!p.checkName(func_name, p.is_interface)) {
479- p.errorAt(func_loc, "a function name must start with a lower case character");
504+ if (p.tok.kind == Kind.Dot) {
505+ if (is_local) {
506+ p.error("local functions cannot be type functions");
507+ }
508+ p.consumeToken();
509+ p.expectIdentifier();
510+
511+ prefix_ref.loc = func_loc;
512+ prefix_ref.name_idx = func_name;
513+ prefix_ref.decl = nil;
514+ prefix = &prefix_ref;
515+ func_name = p.tok.name_idx;
516+ func_loc = p.tok.loc;
517+ p.consumeToken();
518+ }
519+
520+ if (!p.checkName(func_name, p.is_interface)) {
521+ p.errorAt(func_loc, "a function name must start with a lower case character");
522+ }
480523 }
481524
482525 DeclList params.init();
483526
484527 bool is_variadic = p.parseFunctionParams(¶ms, is_public, true);
485528
529+ if (p.tok.kind == Kind.LSquare && is_local) {
530+ // TODO: parse capture specification
531+ while (!p.tok.done && p.tok.kind != Kind.RSquare) {
532+ p.consumeToken();
533+ }
534+ p.expectAndConsume(Kind.RSquare);
535+ }
536+
486537 FunctionDecl* f;
487538 if (p.tok.kind == Kind.KW_template) {
539+ if (is_local) {
540+ p.error("local functions cannot be template functions");
541+ }
488542 p.consumeToken();
489543 p.expectIdentifier();
490544
@@ -510,28 +564,31 @@ fn void Parser.parseFuncDecl(Parser* p, bool is_public) {
510564 prefix,
511565 (VarDecl**)params.getDecls(),
512566 params.size(),
513- is_variadic);
567+ is_variadic, is_local );
514568 }
515569
516570 params.free();
517571
518- u32 num_attr = p.parseOptionalAttributes();
519- p.applyAttributes((Decl*)f, num_attr);
572+ if (!is_local) {
573+ u32 num_attr = p.parseOptionalAttributes();
574+ p.applyAttributes((Decl*)f, num_attr);
575+ }
520576
521577 if (p.is_interface) {
522578 if (p.tok.kind == Kind.Semicolon) {
523579 // function without body (eg. i32 printf(..); ) is allowed
524580 p.consumeToken();
525- return;
581+ return f ;
526582 }
527583
528584 // mark functions with bodies in interface files as 'inline'
529585 f.setAttrInline();
530586 }
531587
532- p.stmt_list_count = 0;
588+ if (!is_local) p.stmt_list_count = 0;
533589 CompoundStmt* body = p.parseCompoundStmt();
534590 p.builder.actOnFunctionBody(f, body);
591+ return f;
535592}
536593
537594fn bool Parser.parseFunctionParams(Parser* p, DeclList* params, bool is_public, bool accept_default) {
0 commit comments