Пример #1
0
    TypeAst FuncType(TypeAst baseType, bool mutable)
    {
        if (mutable)
        {
            throw new Exception("func code cannot be mutable");
        }

        Token open = Match(TokenKind.LeftParen);

        bool           vaArg      = false;
        List <TypeAst> paramTypes = new List <TypeAst>();

        while (current.kind is not TokenKind.Eof and not TokenKind.RightParen)
        {
            if (current.kind is TokenKind.DotDotDot)
            {
                vaArg = true;
                break;
            }

            paramTypes.Add(Type());

            if (current.kind is not TokenKind.RightParen)
            {
                Match(TokenKind.Comma);
            }
        }

        Match(TokenKind.RightParen);

        return(new FuncTypeAst(baseType, open, paramTypes.ToArray(), vaArg));
    }
Пример #2
0
    VarAst Var(string[] metadata, Visibility visibility, bool mutable, TypeAst type, Token name, string?asmName)
    {
        scope.DefineVar(name.text);
        if (asmName is null)
        {
            if (current.kind is TokenKind.Colon)
            {
                Next();
                asmName = Match(TokenKind.Str).text;
            }
            else
            {
                asmName = $"Syv${name.text}";
            }
        }

        ExprAst initializer = new ExprAst(Token.devault);

        if (current.kind is TokenKind.Eql)
        {
            Next();
            initializer = Expr();
        }

        EndLine();
        return(new VarAst(metadata, visibility, mutable, type, name, asmName, initializer));
    }
Пример #3
0
    TypeAst TypeExt(TypeAst baseType)
    {
        bool mutable = false;

        if (current.kind is TokenKind.MutableKeyword)
        {
            mutable = true;
            Next();
        }

        switch (current.kind)
        {
        case TokenKind.Star:
            return(TypeExt(PtrType(baseType, mutable)));

        case TokenKind.LeftBracket:
            return(TypeExt(ArrayType(baseType, mutable)));

        case TokenKind.LeftParen:
            return(TypeExt(FuncType(baseType, mutable)));

        default:
            return(baseType);
        }
    }
Пример #4
0
    ExprAst PostExpr(ExprAst operand)
    {
Loop:
        if (postOps.Contains(current.kind))
        {
            Token token = Next();
            Enum  op    = PostOpcode(token.kind);
            operand = new PostExprAst(token, op, operand);
            goto Loop;
        }
        if (current.kind is TokenKind.LeftParen)
        {
            Token open = Next();

            List <ExprAst> args = new List <ExprAst>();
            while (current.kind is not TokenKind.Eof and not TokenKind.RightParen)
            {
                args.Add(Expr());
                if (current.kind is not TokenKind.RightParen)
                {
                    Match(TokenKind.Comma);
                }
            }

            Match(TokenKind.RightParen);
            operand = new CallExprAst(operand, open, args.ToArray());
            goto Loop;
        }
        if (current.kind is TokenKind.Dot)
        {
            Next();
            Token name = Match(TokenKind.Identifier);
            operand = new MemberExprAst(operand, name);
            goto Loop;
        }
        if (current.kind is TokenKind.AsKeyword)
        {
            Token   keywrd = Next();
            TypeAst to     = Type();
            operand = new BitCastExprAst(operand, keywrd, to);
            goto Loop;
        }
        if (current.kind is TokenKind.ToKeyword)
        {
            Token   keywrd = Next();
            TypeAst to     = Type();
            operand = new CastExprAst(operand, keywrd, to);
            goto Loop;
        }
        if (current.kind is TokenKind.LeftBracket)
        {
            Token   open = Next();
            ExprAst idx  = Expr();
            Match(TokenKind.RightBracket);
            operand = new IndexExprAst(operand, open, idx);
            goto Loop;
        }

        return(operand);
    }
Пример #5
0
    TypeAst ArrayType(TypeAst baseType, bool mutable)
    {
        Token   open   = Match(TokenKind.LeftBracket);
        ExprAst length = Expr();

        Match(TokenKind.RightBracket);

        return(new ArrayTypeAst(baseType, mutable, open, length));
    }
Пример #6
0
    DeclFuncAst DeclFunc(string[] metadata, Visibility visibility, bool mutable, TypeAst retType, Token name)
    {
        scope.DefineFunc(name.text);
        List <ParamAst> paramz = new List <ParamAst>();

        Match(TokenKind.LeftParen);
        bool vaArg = false;

        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);
            if (current.kind is not TokenKind.RightParen)
            {
                Match(TokenKind.Comma);
            }
        }

        Match(TokenKind.RightParen);

        string asmName;

        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("Syf$");
            sb.Append(name.text);
            foreach (ParamAst param in paramz)
            {
                sb.Append(';');
                sb.Append(param.type.name);
            }

            asmName = sb.ToString();
        }

        MaybeEndLine();

        // TODO: class fn decls
        return(new DeclFuncAst(metadata, visibility, mutable, retType, name, asmName, paramz.ToArray(), vaArg));
    }
Пример #7
0
    SizeofExprAst SizeofExpr()
    {
        Token name = Match(TokenKind.Identifier);

        Match(TokenKind.LeftParen);
        TypeAst type = Type();

        Match(TokenKind.RightParen);

        return(new SizeofExprAst(name, type));
    }
Пример #8
0
    DeclVarAst DeclVar(string[] metadata, Visibility visibility, bool mutable, TypeAst type, Token name)
    {
        scope.DefineVar(name.text);
        string asmName = $"Syv${name.text}";

        if (current.kind is TokenKind.Colon)
        {
            Next();
            name = Match(TokenKind.Str);
        }
        return(new DeclVarAst(metadata, visibility, mutable, type, name, asmName));
    }
Пример #9
0
    UsingAst Using(Visibility visibility)
    {
        Token   keywrd   = Match(TokenKind.UsingKeyword);
        TypeAst realType = Type();

        Match(TokenKind.AsKeyword);
        string alias = Name();

        EndLine();

        return(new UsingAst(visibility, keywrd, realType, alias));
    }
Пример #10
0
    FuncAst Func(string className, FieldAst[] fields)
    {
        string[] metadata = MetaData();

        Visibility visibility;

        switch (current.kind)
        {
        case TokenKind.PublicKeyword:
            Next();
            visibility = LLVMDefaultVisibility;
            break;

        case TokenKind.PrivateKeyword:
            Next();
            visibility = LLVMHiddenVisibility;
            break;

        case TokenKind.ProtectedKeyword:
            Next();
            visibility = LLVMProtectedVisibility;
            break;

        default:
            visibility = LLVMDefaultVisibility;
            break;
        }
        ;

        bool mutable;

        if (mutable = current.kind is TokenKind.MutableKeyword)
        {
            Next();
        }

        TypeAst retType = Type();
        Token   name    = Match(TokenKind.Identifier);
        string  asmName = $"{className}.{name.text}";

        EnterScope();
        scope.DefineVar("this");
        foreach (FieldAst field in fields)
        {
            scope.DefineVar(field.name);
        }
        FuncAst func = Func(metadata, visibility, mutable, retType, name, asmName, false);

        ExitScope();
        return(func);
    }
Пример #11
0
    GroupExprAst GroupExpr(TypeAst groupType)
    {
        Token open = Match(TokenKind.LeftBrace);

        List <ExprAst> members = new List <ExprAst>();

        while (current.kind is not TokenKind.Eof and not TokenKind.RightBrace)
        {
            members.Add(Expr());

            if (current.kind is not TokenKind.RightBrace)
            {
                Match(TokenKind.Comma);
            }
        }
        Match(TokenKind.RightBrace);
        return(new GroupExprAst(groupType, open, members.ToArray()));
    }
Пример #12
0
    ParamAst Param()
    {
        string[] metadata = MetaData();

        bool mutable;

        if (mutable = current.kind is TokenKind.MutableKeyword)
        {
            Next();
        }

        TypeAst type = Type();
        Token   token;
        string  name;

        if (current.kind is TokenKind.Identifier)
        {
            token = Next();
            name  = token.text;
        }
        else
        {
            token = type.token;
            name  = string.Empty;
        }

        ExprAst defaultExpr = new ExprAst(Token.devault);

        if (current.kind is TokenKind.Eql)
        {
            Next();
            defaultExpr = Expr();
        }

        return(new ParamAst(metadata, mutable, type, token, name, defaultExpr));
    }
Пример #13
0
    StmtAst Stmt()
    {
        switch (current.kind)
        {
        case TokenKind.LeftBrace:
            return(Block());

        case TokenKind.IfKeyword:
            return(If());

        case TokenKind.WhileKeyword:
            return(While());

        case TokenKind.ForKeyword:
            return(For());

        case TokenKind.BreakKeyword:
            return(Break());

        case TokenKind.BreakAllKeyword:
            return(BreakAll());

        case TokenKind.RetKeyword:
            return(Ret());
        }

        string[] metadata = MetaData();

        bool       illegal = true;
        Visibility visibility;

        switch (current.kind)
        {
        case TokenKind.PublicKeyword:
            Next();
            visibility = LLVMDefaultVisibility;
            break;

        case TokenKind.PrivateKeyword:
            Next();
            visibility = LLVMHiddenVisibility;
            break;

        case TokenKind.ProtectedKeyword:
            Next();
            visibility = LLVMProtectedVisibility;
            break;

        default:
            visibility = LLVMDefaultVisibility;
            illegal    = false;
            break;
        }
        ;

        bool mutable;

        if (mutable = current.kind is TokenKind.MutableKeyword)
        {
            Next();
        }

        if (current.kind is TokenKind.EnumKeyword)
        {
            return(Enum(metadata, visibility));
        }
        if (current.kind is TokenKind.StructKeyword)
        {
            return(Struct(metadata, visibility));
        }
        if (current.kind is TokenKind.ClassKeyword)
        {
            return(Class(metadata, visibility));
        }
        if (current.kind is TokenKind.UsingKeyword)
        {
            return(Using(visibility));
        }
        if (current.kind is TokenKind.LinkKeyword)
        {
            return(Link(visibility));
        }
        if (current.kind is TokenKind.DeclKeyword)
        {
            Next();
            TypeAst type = Type();
            Token   name = Match(TokenKind.Identifier);
            if (current.kind is TokenKind.LeftParen)
            {
                return(DeclFunc(metadata, visibility, mutable, retType: type, name));
            }
            return(DeclVar(metadata, visibility, mutable, type, name));
        }
        if (current.kind is TokenKind.Identifier && !(scope.VarExists(current.text) || scope.FuncExists(current.text)) && IsType(current))
        {
            TypeAst type    = Type();
            Token   name    = Match(TokenKind.Identifier);
            string? asmName = null;
            if (current.kind is TokenKind.Colon)
            {
                Next();
                asmName = Match(TokenKind.Str).text;
            }
            if (current.kind is TokenKind.LeftParen or TokenKind.LeftBrace or TokenKind.Arrow)
            {
                return(Func(metadata, visibility, mutable, retType: type, name, asmName));
            }
            return(Var(metadata, visibility, mutable, type, name, asmName));
        }

        if (!illegal)
        {
            return(ExprStmt());
        }

        throw new Exception("Illegal");
    }
Пример #14
0
    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()));
    }
Пример #15
0
    TypeAst PtrType(TypeAst baseType, bool mutable)
    {
        Token token = Match(TokenKind.Star);

        return(new PtrTypeAst(baseType, mutable, token));
    }
Пример #16
0
    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());
        }
    }