@@ -365,7 +365,7 @@ fn void Parser.parseTopLevel(Parser* p) {
365365 break;
366366 case KW_fn:
367367 if (p.tokenizer.c_mode) goto invalid_c;
368- p.parseFuncDecl(is_public);
368+ p.parseFuncDecl(is_public, false );
369369 break;
370370 case KW_import:
371371 p.error("no imports allowed after declarations");
@@ -497,27 +497,73 @@ fn void Parser.applyAttributes(Parser* p, Decl* d, u32 count) {
497497 if (count) p.builder.applyAttributes(d, count);
498498}
499499
500- fn void Parser.parseFuncDecl(Parser* p, bool is_public) {
501- p.consumeToken();
500+ fn u32 Parser.createLocalName(Parser* p, u32 name, SrcLoc loc, u32* plen) {
501+ char[128] buf;
502+ *plen = (u32)snprintf(buf, sizeof(buf), "%s__%d", p.pool.idx2str(name), loc);
503+ return p.pool.addStr(buf, true);
504+ }
505+
506+ fn Expr* Parser.parseLocalFuncExpr(Parser* p) {
507+ SrcLoc loc = p.tok.loc;
508+ FunctionDecl* f = p.parseFuncDecl(false, true);
509+ Decl* d = f.asDecl();
510+ u32 name = d.getNameIdx();
511+ u32 len;
512+ u32 local_name = p.createLocalName(name, loc, &len);
513+ d.setNameIdx(local_name);
514+ p.builder.addSymbol(local_name, d);
515+ return p.builder.actOnIdentifier(loc, local_name, len);
516+ }
517+
518+ fn Stmt* Parser.parseLocalFuncStmt(Parser* p) {
519+ SrcLoc loc = p.tok.loc;
520+ FunctionDecl* f = p.parseFuncDecl(false, true);
521+ Decl* d = f.asDecl();
522+ u32 name = d.getNameIdx();
523+ u32 len;
524+ u32 local_name = p.createLocalName(name, loc, &len);
525+ d.setNameIdx(local_name);
526+ p.builder.addSymbol(local_name, d);
527+ Expr* fexpr = p.builder.actOnIdentifier(loc, local_name, len);
528+ // TODO: use auto typing
529+ TypeRefHolder ref.init();
530+ ref.setVoid(loc);
531+ ref.addPointer();
532+ VarDecl* decl = p.builder.actOnVarDecl(name, loc, &ref, loc, fexpr, false, false);
533+ return p.builder.actOnDeclStmt(&decl, 1);
534+ }
535+
536+ fn FunctionDecl* Parser.parseFuncDecl(Parser* p, bool is_public, bool is_local) {
537+ u32 func_name = 0;
538+ SrcLoc func_loc = p.tok.loc;
539+ Ref prefix_ref;
540+ Ref* prefix = nil;
541+
542+ p.consumeToken(); // fn
502543
503544 TypeRefHolder rtype.init();
504545 // Note: dont check arrays in this phase, but in Analyser
505546 p.parseTypeSpecifier(&rtype);
506547
507- p.expectIdentifier();
508- u32 func_name = p.tok.name_idx;
509- SrcLoc func_loc = p.tok.loc;
510- p.consumeToken();
511-
512- p.parseFunctionDecl2(func_name, func_loc, is_public, &rtype);
548+ if (p.tok.kind == Identifier || !is_local) {
549+ p.expectIdentifier();
550+ func_name = p.tok.name_idx;
551+ func_loc = p.tok.loc;
552+ p.consumeToken();
553+ }
554+ return p.parseFunctionDecl2(func_name, func_loc, is_public, is_local, &rtype);
513555}
514556
515- fn void Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
516- bool is_public, TypeRefHolder* rtype)
557+ fn FunctionDecl* Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
558+ bool is_public, bool is_local , TypeRefHolder* rtype)
517559{
518560 Ref prefix_ref;
519561 Ref* prefix = nil;
562+
520563 if (p.tok.kind == Dot) {
564+ if (is_local) {
565+ p.error("local functions cannot be type functions");
566+ }
521567 p.consumeToken();
522568 p.expectIdentifier();
523569
@@ -530,16 +576,27 @@ fn void Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
530576 p.consumeToken();
531577 }
532578
533- if (!p.checkName(func_name, p.is_interface)) {
579+ if (func_name && !p.checkName(func_name, p.is_interface)) {
534580 p.errorAt(func_loc, "a function name must start with a lower case character");
535581 }
536582
537583 DeclList params.init();
538584
539585 bool is_variadic = p.parseFunctionParams(¶ms, is_public, true);
540586
587+ if (p.tok.kind == LSquare && is_local) {
588+ // TODO: parse capture specification
589+ while (!p.tok.done && p.tok.kind != RSquare) {
590+ p.consumeToken();
591+ }
592+ p.expectAndConsume(RSquare);
593+ }
594+
541595 FunctionDecl* f;
542596 if (p.tok.kind == KW_template) {
597+ if (is_local) {
598+ p.error("local functions cannot be template functions");
599+ }
543600 p.consumeToken();
544601 p.expectIdentifier();
545602
@@ -565,19 +622,21 @@ fn void Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
565622 prefix,
566623 (VarDecl**)params.getDecls(),
567624 params.size(),
568- is_variadic);
625+ is_variadic, is_local );
569626 }
570627
571628 params.free();
572629
573- u32 num_attr = p.parseOptionalAttributes();
574- p.applyAttributes((Decl*)f, num_attr);
630+ if (!is_local) {
631+ u32 num_attr = p.parseOptionalAttributes();
632+ p.applyAttributes((Decl*)f, num_attr);
633+ }
575634
576635 if (p.is_interface) {
577636 if (p.tok.kind == Semicolon) {
578637 // function without body (eg. i32 printf(..); ) is allowed
579638 p.consumeToken();
580- return;
639+ return f ;
581640 }
582641
583642 if (func_name != p.main_idx) {
@@ -586,9 +645,10 @@ fn void Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
586645 }
587646 }
588647
589- p.stmt_list_count = 0;
648+ if (!is_local) p.stmt_list_count = 0;
590649 CompoundStmt* body = p.parseCompoundStmt();
591650 p.builder.actOnFunctionBody(f, body);
651+ return f;
592652}
593653
594654fn bool Parser.parseFunctionParams(Parser* p, DeclList* params, bool is_public, bool accept_default) {
@@ -763,7 +823,7 @@ fn void Parser.parseVarDecl(Parser* p, bool is_public) {
763823 if (!p.tokenizer.c_mode) {
764824 p.error("function definitions require the 'fn' keyword");
765825 }
766- p.parseFunctionDecl2(name, loc, is_public, &ref);
826+ p.parseFunctionDecl2(name, loc, is_public, false, &ref);
767827 return;
768828 }
769829
@@ -773,7 +833,7 @@ fn void Parser.parseVarDecl(Parser* p, bool is_public) {
773833 // Either a function definition or an init call
774834 if (!p.tokenizer.c_mode)
775835 p.error("global variables cannot have an init call");
776- p.parseFunctionDecl2(name, loc, is_public, &ref);
836+ p.parseFunctionDecl2(name, loc, is_public, false, &ref);
777837 return;
778838 }
779839 p.error("global type variables not supported");
0 commit comments