@@ -377,7 +377,7 @@ fn void Parser.parseTopLevel(Parser* p) {
377377 break;
378378 case KW_fn:
379379 if (p.tokenizer.c_mode) goto invalid_c;
380- p.parseFuncDecl(is_public);
380+ p.parseFuncDecl(is_public, false );
381381 break;
382382 case KW_import:
383383 p.error("no imports allowed after declarations");
@@ -509,27 +509,73 @@ fn void Parser.applyAttributes(Parser* p, Decl* d, u32 count) {
509509 if (count) p.builder.applyAttributes(d, count);
510510}
511511
512- fn void Parser.parseFuncDecl(Parser* p, bool is_public) {
513- p.consumeToken();
512+ fn u32 Parser.createLocalName(Parser* p, u32 name, SrcLoc loc, u32* plen) {
513+ char[128] buf;
514+ *plen = (u32)snprintf(buf, sizeof(buf), "%s__%d", p.pool.idx2str(name), loc);
515+ return p.pool.addStr(buf, true);
516+ }
517+
518+ fn Expr* Parser.parseLocalFuncExpr(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+ return p.builder.actOnIdentifier(loc, local_name, len);
528+ }
529+
530+ fn Stmt* Parser.parseLocalFuncStmt(Parser* p) {
531+ SrcLoc loc = p.tok.loc;
532+ FunctionDecl* f = p.parseFuncDecl(false, true);
533+ Decl* d = f.asDecl();
534+ u32 name = d.getNameIdx();
535+ u32 len;
536+ u32 local_name = p.createLocalName(name, loc, &len);
537+ d.setNameIdx(local_name);
538+ p.builder.addSymbol(local_name, d);
539+ Expr* fexpr = p.builder.actOnIdentifier(loc, local_name, len);
540+ // TODO: use auto typing
541+ TypeRefHolder ref.init();
542+ ref.setVoid(loc);
543+ ref.addPointer();
544+ VarDecl* decl = p.builder.actOnVarDecl(name, loc, &ref, loc, fexpr, false, false);
545+ return p.builder.actOnDeclStmt(&decl, 1);
546+ }
547+
548+ fn FunctionDecl* Parser.parseFuncDecl(Parser* p, bool is_public, bool is_local) {
549+ u32 func_name = 0;
550+ SrcLoc func_loc = p.tok.loc;
551+ Ref prefix_ref;
552+ Ref* prefix = nil;
553+
554+ p.consumeToken(); // fn
514555
515556 TypeRefHolder rtype.init();
516557 // Note: dont check arrays in this phase, but in Analyser
517558 p.parseTypeSpecifier(&rtype);
518559
519- p.expectIdentifier();
520- u32 func_name = p.tok.name_idx;
521- SrcLoc func_loc = p.tok.loc;
522- p.consumeToken();
523-
524- p.parseFunctionDecl2(func_name, func_loc, is_public, &rtype);
560+ if (p.tok.kind == Identifier || !is_local) {
561+ p.expectIdentifier();
562+ func_name = p.tok.name_idx;
563+ func_loc = p.tok.loc;
564+ p.consumeToken();
565+ }
566+ return p.parseFunctionDecl2(func_name, func_loc, is_public, is_local, &rtype);
525567}
526568
527- fn void Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
528- bool is_public, TypeRefHolder* rtype)
569+ fn FunctionDecl* Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
570+ bool is_public, bool is_local , TypeRefHolder* rtype)
529571{
530572 Ref prefix_ref;
531573 Ref* prefix = nil;
574+
532575 if (p.tok.kind == Dot) {
576+ if (is_local) {
577+ p.error("local functions cannot be type functions");
578+ }
533579 p.consumeToken();
534580 p.expectIdentifier();
535581
@@ -542,16 +588,27 @@ fn void Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
542588 p.consumeToken();
543589 }
544590
545- if (!p.checkName(func_name, p.is_interface)) {
591+ if (func_name && !p.checkName(func_name, p.is_interface)) {
546592 p.errorAt(func_loc, "a function name must start with a lower case character");
547593 }
548594
549595 DeclList params.init();
550596
551597 bool is_variadic = p.parseFunctionParams(¶ms, is_public, true);
552598
599+ if (p.tok.kind == LSquare && is_local) {
600+ // TODO: parse capture specification
601+ while (!p.tok.done && p.tok.kind != RSquare) {
602+ p.consumeToken();
603+ }
604+ p.expectAndConsume(RSquare);
605+ }
606+
553607 FunctionDecl* f;
554608 if (p.tok.kind == KW_template) {
609+ if (is_local) {
610+ p.error("local functions cannot be template functions");
611+ }
555612 p.consumeToken();
556613 p.expectIdentifier();
557614
@@ -577,19 +634,21 @@ fn void Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
577634 prefix,
578635 (VarDecl**)params.getDecls(),
579636 params.size(),
580- is_variadic);
637+ is_variadic, is_local );
581638 }
582639
583640 params.free();
584641
585- u32 num_attr = p.parseOptionalAttributes();
586- p.applyAttributes((Decl*)f, num_attr);
642+ if (!is_local) {
643+ u32 num_attr = p.parseOptionalAttributes();
644+ p.applyAttributes((Decl*)f, num_attr);
645+ }
587646
588647 if (p.is_interface) {
589648 if (p.tok.kind == Semicolon) {
590649 // function without body (eg. i32 printf(..); ) is allowed
591650 p.consumeToken();
592- return;
651+ return f ;
593652 }
594653
595654 if (func_name != p.main_idx) {
@@ -598,9 +657,10 @@ fn void Parser.parseFunctionDecl2(Parser* p, u32 func_name, SrcLoc func_loc,
598657 }
599658 }
600659
601- p.stmt_list_count = 0;
660+ if (!is_local) p.stmt_list_count = 0;
602661 CompoundStmt* body = p.parseCompoundStmt();
603662 p.builder.actOnFunctionBody(f, body);
663+ return f;
604664}
605665
606666fn bool Parser.parseFunctionParams(Parser* p, DeclList* params, bool is_public, bool accept_default) {
@@ -775,7 +835,7 @@ fn void Parser.parseVarDecl(Parser* p, bool is_public) {
775835 if (!p.tokenizer.c_mode) {
776836 p.error("function definitions require the 'fn' keyword");
777837 }
778- p.parseFunctionDecl2(name, loc, is_public, &ref);
838+ p.parseFunctionDecl2(name, loc, is_public, false, &ref);
779839 return;
780840 }
781841
@@ -785,7 +845,7 @@ fn void Parser.parseVarDecl(Parser* p, bool is_public) {
785845 // Either a function definition or an init call
786846 if (!p.tokenizer.c_mode)
787847 p.error("global variables cannot have an init call");
788- p.parseFunctionDecl2(name, loc, is_public, &ref);
848+ p.parseFunctionDecl2(name, loc, is_public, false, &ref);
789849 return;
790850 }
791851 p.error("global type variables not supported");
0 commit comments