FuncAst Func(string[] metadata, Visibility visibility, bool mutable, TypeAst retType, Token name, string?asmName, bool asmNameIsName = true) { EnterScope(); bool vaArg = false; List <ParamAst> paramz = new List <ParamAst>(); Match(TokenKind.LeftParen); while (current.kind is not TokenKind.Eof and not TokenKind.RightParen) { if (current.kind is TokenKind.DotDotDot) { Next(); vaArg = true; break; } ParamAst param = Param(); paramz.Add(param); scope.DefineVar(param.name); if (current.kind is not TokenKind.RightParen) { Match(TokenKind.Comma); } } Match(TokenKind.RightParen); if (asmName is null || !asmNameIsName) { if (current.kind is TokenKind.Colon) { Next(); asmName = Match(TokenKind.Str).text; } else if (metadata.Contains("naked")) { asmName = name.text; } else { StringBuilder sb = new StringBuilder(mutable ? "Symf$" : "Syf$"); sb.Append(asmNameIsName ? name.text : asmName); foreach (ParamAst param in paramz) { sb.Append(';'); sb.Append(param.type.name); } asmName = sb.ToString(); } } // Single Expr Func if (current.kind is TokenKind.Arrow) { Next(); ExprAst expr = Expr(); MaybeEndLine(); return(new FuncAst(metadata, visibility, mutable, retType, name, asmName ?? name.text, paramz.ToArray(), vaArg, new StmtAst[] { new RetStmtAst(Token.devault, expr) })); } List <StmtAst> body = new List <StmtAst>(); Match(TokenKind.LeftBrace); while (current.kind is not TokenKind.Eof and not TokenKind.RightBrace) { body.Add(Stmt()); } ExitScope(); Match(TokenKind.RightBrace); MaybeEndLine(); scope.DefineFunc(name.text); return(new FuncAst(metadata, visibility, mutable, retType, name, asmName ?? name.text, paramz.ToArray(), vaArg, body.ToArray())); }
ExprAst PrimExpr() { switch (current.kind) { case TokenKind.Percent: Token op = Next(); return(new PreExprAst(PreOpcode(op.kind), op, PrimExpr())); case TokenKind.Identifier: { if (scope.VarExists(current.text)) { return(new VarExprAst(Next())); } if (current.text is "stalloc") { return(StallocExpr()); } if (current.text is "sizeof") { return(SizeofExpr()); } if (scope.FuncExists(current.text)) // fnptr overloads { return(new FuncPtrAst(Next())); } if (!IsType(current)) { BadCode.Report(new SyntaxError($"symbol '{current.text}' doesn't exist", current)); } TypeAst type = Type(); if (current.kind is TokenKind.LeftBracket) { return(ArrayExpr(eleType: type)); } return(GroupExpr(groupType: type)); } case TokenKind.LeftParen: Next(); if (IsType(current)) { TypeAst to = Type(); Token open = Match(TokenKind.RightParen); ExprAst value = PreExpr(); return(new CastExprAst(value, open, to)); } ExprAst expr = Expr(); Match(TokenKind.RightParen); return(expr); case TokenKind.LeftBracket: if (IsType(next)) { Next(); TypeAst to = Type(); Token open = Match(TokenKind.RightBracket); ExprAst value = PreExpr(); return(new BitCastExprAst(value, open, to)); } return(ArrayExpr()); default: return(LiteralExpr()); } }