@@ -332,7 +332,7 @@ fn void Parser.parseTopLevel(Parser* p) {
332332 p.error("assert can only be used inside a function");
333333 break;
334334 case KW_fn:
335- p.parseFuncDecl(is_public);
335+ p.parseFuncDecl(is_public, false );
336336 break;
337337 case KW_import:
338338 p.error("no imports allowed after declarations");
@@ -453,43 +453,97 @@ fn void Parser.parseParamOptionalAttributes(Parser* p, VarDecl* d) {
453453 p.expectAndConsume(Kind.RParen);
454454}
455455
456- fn void Parser.parseFuncDecl(Parser* p, bool is_public) {
456+ fn u32 Parser.createLocalName(Parser* p, u32 name, SrcLoc loc) {
457+ char[128] buf;
458+ snprintf(buf, sizeof(buf), "%s__%d", p.pool.idx2str(name), loc);
459+ return p.pool.addStr(buf, true);
460+ }
461+
462+ fn Expr* Parser.parseLocalFuncExpr(Parser* p) {
463+ SrcLoc loc = p.tok.loc;
464+ FunctionDecl* f = p.parseFuncDecl(false, true);
465+ Decl* d = f.asDecl();
466+ u32 name = d.getNameIdx();
467+ u32 local_name = p.createLocalName(name, loc);
468+ d.setNameIdx(local_name);
469+ p.builder.addSymbol(local_name, d);
470+ Expr* fexpr = p.builder.actOnIdentifier(loc, local_name).asExpr();
471+ return fexpr;
472+ }
473+
474+ fn Stmt* Parser.parseLocalFuncStmt(Parser* p) {
475+ SrcLoc loc = p.tok.loc;
476+ FunctionDecl* f = p.parseFuncDecl(false, true);
477+ Decl* d = f.asDecl();
478+ u32 name = d.getNameIdx();
479+ u32 local_name = p.createLocalName(name, loc);
480+ d.setNameIdx(local_name);
481+ p.builder.addSymbol(local_name, d);
482+ Expr* fexpr = p.builder.actOnIdentifier(loc, local_name).asExpr();
483+ // TODO: use auto typing
484+ TypeRefHolder ref.init();
485+ ref.setBuiltin(Void, loc);
486+ ref.addPointer();
487+ VarDecl* decl = p.builder.actOnVarDecl(name, loc, &ref, loc, fexpr, false, false);
488+ return p.builder.actOnDeclStmt(&decl, 1);
489+ }
490+
491+ fn FunctionDecl* Parser.parseFuncDecl(Parser* p, bool is_public, bool is_local) {
492+ u32 func_name = 0;
493+ SrcLoc func_loc = p.tok.loc;
494+ Ref prefix_ref;
495+ Ref* prefix = nil;
496+
457497 p.consumeToken();
458498
459499 TypeRefHolder rtype.init();
460500 // Note: dont check arrays in this phase, but in Analyser
461501 p.parseTypeSpecifier(&rtype);
462502
463- p.expectIdentifier();
464- u32 func_name = p.tok.name_idx;
465- SrcLoc func_loc = p.tok.loc;
466- p.consumeToken();
467-
468- Ref prefix_ref;
469- Ref* prefix = nil;
470- if (p.tok.kind == Kind.Dot) {
471- p.consumeToken();
503+ if (p.tok.kind == Kind.Identifier || !is_local) {
472504 p.expectIdentifier();
473-
474- prefix_ref.loc = func_loc;
475- prefix_ref.name_idx = func_name;
476- prefix_ref.decl = nil;
477- prefix = &prefix_ref;
478505 func_name = p.tok.name_idx;
479506 func_loc = p.tok.loc;
480507 p.consumeToken();
481- }
482508
483- if (!p.checkName(func_name, p.is_interface)) {
484- p.errorAt(func_loc, "a function name must start with a lower case character");
509+ if (p.tok.kind == Kind.Dot) {
510+ if (is_local) {
511+ p.error("local functions cannot be type functions");
512+ }
513+ p.consumeToken();
514+ p.expectIdentifier();
515+
516+ prefix_ref.loc = func_loc;
517+ prefix_ref.name_idx = func_name;
518+ prefix_ref.decl = nil;
519+ prefix = &prefix_ref;
520+ func_name = p.tok.name_idx;
521+ func_loc = p.tok.loc;
522+ p.consumeToken();
523+ }
524+
525+ if (!p.checkName(func_name, p.is_interface)) {
526+ p.errorAt(func_loc, "a function name must start with a lower case character");
527+ }
485528 }
486529
487530 DeclList params.init();
488531
489532 bool is_variadic = p.parseFunctionParams(¶ms, is_public, true);
490533
534+ if (p.tok.kind == Kind.LSquare && is_local) {
535+ // TODO: parse capture specification
536+ while (!p.tok.done && p.tok.kind != Kind.RSquare) {
537+ p.consumeToken();
538+ }
539+ p.expectAndConsume(Kind.RSquare);
540+ }
541+
491542 FunctionDecl* f;
492543 if (p.tok.kind == Kind.KW_template) {
544+ if (is_local) {
545+ p.error("local functions cannot be template functions");
546+ }
493547 p.consumeToken();
494548 p.expectIdentifier();
495549
@@ -515,28 +569,31 @@ fn void Parser.parseFuncDecl(Parser* p, bool is_public) {
515569 prefix,
516570 (VarDecl**)params.getDecls(),
517571 params.size(),
518- is_variadic);
572+ is_variadic, is_local );
519573 }
520574
521575 params.free();
522576
523- p.parseOptionalAttributes();
524- p.builder.applyAttributes((Decl*)f);
577+ if (!is_local) {
578+ p.parseOptionalAttributes();
579+ p.builder.applyAttributes((Decl*)f);
580+ }
525581
526582 if (p.is_interface) {
527583 if (p.tok.kind == Kind.Semicolon) {
528584 // function without body (eg. i32 printf(..); ) is allowed
529585 p.consumeToken();
530- return;
586+ return f ;
531587 }
532588
533589 // mark functions with bodies in interface files as 'inline'
534590 f.setAttrInline();
535591 }
536592
537- p.stmt_list_count = 0;
593+ if (!is_local) p.stmt_list_count = 0;
538594 CompoundStmt* body = p.parseCompoundStmt();
539595 p.builder.actOnFunctionBody(f, body);
596+ return f;
540597}
541598
542599fn bool Parser.parseFunctionParams(Parser* p, DeclList* params, bool is_public, bool accept_default) {
0 commit comments