Example #1
0
        private FunctionSymbol BindFunctionDeclaration(FunctionDeclarationNode node)
        {
            var seenParameterNames = new HashSet <string>();

            var parameters = new List <ParameterSymbol>();

            foreach (var parameterNode in node.ParametersDeclaration.Parameters)
            {
                var parameterName = parameterNode.MainToken.Text;
                var parameterType = BindTypeClause(parameterNode.Type);
                if (seenParameterNames.Add(parameterName))
                {
                    var parameter = new ParameterSymbol(parameterName, parameterType);
                    parameters.Add(parameter);
                }
                else
                {
                    diagnostics.ReportParameterAlreadyDeclared(parameterNode.MainToken, parameterName);
                }
            }

            var type = BindTypeClause(node.ReturnType) ?? BuiltinTypes.Void;

            var function = new FunctionSymbol(node.FunctionName.Text, parameters, type, node);

            if (Scope.TryDeclareFunction(function))
            {
                return(function);
            }

            diagnostics.ReportSymbolAlreadyDeclared(node.FunctionName, function.Name, "Function");
            return(null);
        }
 public static void Walk([NotNull] FunctionDeclarationNode functionDeclaration, [NotNull] IList <string> list)
 {
     if (functionDeclaration.Id != null)
     {
         list.Add(functionDeclaration.Id.Name);
     }
 }
Example #3
0
        public override IEnumerable <(SyntaxNode, SyntaxDiagnostic)> Run(NamedDeclarationNode node)
        {
            if (node.VisibilityKeywordToken?.Kind != SyntaxTokenKind.PubKeyword)
            {
                yield break;
            }

            var type = node switch
            {
                ConstantDeclarationNode _ => "constant",
                FunctionDeclarationNode _ => "function",
                ExternalDeclarationNode _ => "function",
                _ => throw DebugAssert.Unreachable(),
            };

            var ident = node.NameToken;

            if (ident.IsMissing)
            {
                yield break;
            }

            var diag = CheckDocAttribute(node.Attributes, ident.Location, $"Public {type} {ident} is undocumented");

            if (diag != null)
            {
                yield return(node, diag);
            }
        }
    public static GraphNode ToGraphNode(FunctionDeclarationNode node)
    {
        var root = new GraphNode(node.GetHashCode(), "\"def " + node.Name.Representation + "\"");

        root.AddProperty("color", "indianred");
        root.AddProperty("tooltip", nameof(FunctionDeclarationNode));

        var parameters = new GraphNode(node.Parameters.GetHashCode(), "\"param\"");

        parameters.AddProperty("tooltip", "parameters");

        foreach (var parameter in node.Parameters)
        {
            var paramNode = new GraphNode(parameter.GetHashCode(), parameter.Representation);

            paramNode.AddProperty("tooltip", "parameter");
            paramNode.AddProperty("color", "lightgrey");

            parameters.AddNode(paramNode);
        }

        root.AddNode(parameters);

        var body = ToGraphNode(node.Value);

        body.AddProperty("tooltip", "body");

        root.AddNode(body);

        return(root);
    }
        private FunctionDeclarationNode BuildFunctionDeclarationNode(
            LexSpan lFunc,
            LexSpan ident,
            LexSpan lPar,
            SyntaxNodeOrToken parameters,
            LexSpan rPar,
            SyntaxNodeOrToken type,
            SyntaxNodeOrToken body,
            LexSpan end,
            LexSpan rFunc)
        {
            var exp = new FunctionDeclarationNode();

            exp.AddNode(new FunctionToken(lFunc));
            exp.AddNode(new IdentToken(ident));
            exp.AddNode(new ParenToken(lPar));
            exp.AddNode(parameters);
            exp.AddNode(new ParenToken(rPar));
            exp.AddNode(type);
            exp.AddNode(body);
            exp.AddNode(new EndToken(end));
            exp.AddNode(new FunctionToken(rFunc));

            return(exp);
        }
        public override string VisitFunctionDeclaration(FunctionDeclarationNode faDeclarationNode)
        {
            var str = "";
            var procedureDeclaration = faDeclarationNode;
            //var str = $"{AddSpaces()}public void {procedureDeclaration.ProcedureId}\r\n";
            // str += AddSpaces() + "{\r\n";
            var symbols = procedureDeclaration.Annotations["SymbolTable"] as ScopedSymbolTable;

            current = symbols;
            var param = CreateParameters(procedureDeclaration, symbols);

            var type = typesConverter.GetTypeName(procedureDeclaration.ReturnType.TypeValue);

            if (procedureDeclaration.Annotations.ContainsKey("Nested"))
            {
                str += $"{AddSpaces()}{type} {procedureDeclaration.FunctionName}({param})\r\n";
            }
            else
            {
                str += $"{AddSpaces()}public static {type} {procedureDeclaration.FunctionName}({param})\r\n";
            }
            //CurrentScope = new ScopedSymbolTable(procedureDeclaration.ProcedureId, CurrentScope);

            str += VisitBlock(procedureDeclaration.Block);

            if (procedureDeclaration.Annotations.ContainsKey("Nested"))
            {
                //str = str.Remove(str.Length - 2);
                //str += ";\r\n";
            }
            //CurrentScope = CurrentScope.ParentScope;
            current = symbols.ParentScope;
            //str += AddSpaces() + "}\r\n";
            return(str);
        }
Example #7
0
        public FunctionSymbol(string name, IEnumerable <ParameterSymbol> parameters, TypeSymbol type, FunctionDeclarationNode declaration = null) : base(name)
        {
            Parameters  = parameters ?? throw new ArgumentNullException(nameof(parameters));
            Type        = type ?? throw new ArgumentNullException(nameof(type));
            Declaration = declaration;

            Key = SymbolKey.FromFunction(name, parameters.Select(p => p.Type));
        }
Example #8
0
        public override dynamic Visit(FunctionDeclarationNode node)
        {
            EnterScope(node.Scope);
            node.Statement.Accept(this);
            ExitScope();

            return(null);
        }
Example #9
0
        private void InvokeNativeFunction(FunctionDeclarationNode currentFunction)
        {
            var nativeArguments = CurrentContextScopeVariables.Select(variable => variable.Value).ToArray();

            currentFunction.NativeBody.DynamicInvoke(nativeArguments);
            CurrentContextScopeVariables.Add(new Variable {
                Name = "$return", Value = 0
            });
        }
Example #10
0
        public FunctionDeclarationNode IsFunctionDeclaration(GeneralDeclarationNode generalDecla)
        {
            StackContext.Context.CanDeclareReturn = true;

            var position = new Token {
                Row = _parser.CurrentToken.Row, Column = _parser.CurrentToken.Column
            };

            var functionNode = new FunctionDeclarationNode {
                Identifier = generalDecla, Position = position
            };

            if (!_parser.Utilities.CompareTokenType(TokenType.OpenParenthesis))
            {
                throw new Exception("Open parenthesis expected at row: " + _parser.CurrentToken.Row + " , column: " + _parser.CurrentToken.Column);
            }

            _parser.Utilities.NextToken();

            List <GeneralDeclarationNode> parameters = new List <GeneralDeclarationNode>();

            ParameterList(parameters);

            functionNode.Parameters = parameters;

            if (!_parser.Utilities.CompareTokenType(TokenType.CloseParenthesis))
            {
                throw new Exception("Close parenthesis expected at row: " + _parser.CurrentToken.Row + " , column: " + _parser.CurrentToken.Column);
            }

            _parser.Utilities.NextToken();

            if (_parser.Utilities.CompareTokenType(TokenType.OpenCurlyBracket))
            {
                _parser.Utilities.NextToken();

                var sentences = _parser.ListOfSpecialSentences();
                functionNode.Sentences = sentences;
            }

            if (_parser.Utilities.CompareTokenType(TokenType.CloseCurlyBracket))
            {
                _parser.Utilities.NextToken();
            }
            else
            {
                throw new Exception("Close function body symbol expected at row: " + _parser.CurrentToken.Row + " , column: " + _parser.CurrentToken.Column);
            }

            functionNode.Position = _parser.CurrentToken;

            StackContext.Context.CanDeclareReturn = false;

            return(functionNode);
        }
Example #11
0
 public void Visit(Node node)
 {
     if (node is ClassDeclarationNode)
     {
         VisitSubnodes(node);
     }
     else if (node is CodeBlock)
     {
         VisitSubnodes(node);
     }
     else if (node is ExpressionNode)
     {
         throw new System.Exception("Expression is not valid outside function body.");
     }
     else if (node is ForNode)
     {
         throw new System.Exception("For Statement is not valid outside function body.");
     }
     else if (node is FunctionCallNode)
     {
         throw new System.Exception("Function Call is not valid outside function body.");
     }
     else if (node is FunctionDeclarationNode)
     {
         FunctionDeclarationNode funcDecl = (FunctionDeclarationNode)node;
         symbolTable.AddSymbol(funcDecl.Name);
         FunctionVisitor visitor = new FunctionVisitor(symbolTable);
         symbolTable.BeginScope();
         foreach (string param in funcDecl.Parameters)
         {
             symbolTable.AddSymbol(param);
         }
         visitor.Visit(funcDecl.Children[0]);
         symbolTable.EndScope();
     }
     else if (node is IfNode)
     {
         throw new System.Exception("If Statement is not valid outside function body.");
     }
     else if (node is ReturnNode)
     {
         throw new System.Exception("Return Statement is not valid outside function body.");
     }
     else if (node is ScopeNode)
     {
         VisitSubnodes(node);
     }
     else if (node is WhileNode)
     {
         throw new System.Exception("While Statement is not valid outside function body.");
     }
 }
Example #12
0
    public IEnumerable <StatementNode> Visit(FunctionDeclarationNode node)
    {
        IEnumerable <StatementNode> output = new List <StatementNode>();

        foreach (var param in node.Parameters)
        {
            if (param.HasDefaultValue)
            {
                output = output.Concat(Flatten(param.DefaultValue !));
            }
        }

        return(output.Concat(Visit(node.Body)).Append(node));
    }
Example #13
0
        public void DefineFunction(string functionName, Delegate functionReference)
        {
            var metaFunction = new FunctionDeclarationNode(functionName);
            var parameters   = functionReference.Method.GetParameters();

            foreach (var parameter in parameters)
            {
                var nativeParameterType = GetNativeType(parameter.ParameterType);
                metaFunction.AddParameter(new ParameterDeclarationNode(nativeParameterType, parameter.Name));
            }
            metaFunction.BodyType   = FunctionBodyType.Native;
            metaFunction.NativeBody = functionReference;
            Functions.Add(metaFunction);
        }
 private static void Walk([NotNull] Agent agent, [NotNull] FunctionDeclarationNode functionDeclaration, bool isStrict)
 {
     if (functionDeclaration.Async)
     {
         WalkAsyncFunction(agent, functionDeclaration.Id, functionDeclaration.Parameters, functionDeclaration.Body, isStrict || new FunctionNode(functionDeclaration.Body).IsStrict);
     }
     else if (functionDeclaration.Generator)
     {
         WalkGeneratorFunction(agent, functionDeclaration.Id, functionDeclaration.Parameters, functionDeclaration.Body, isStrict || new FunctionNode(functionDeclaration.Body).IsStrict);
     }
     else
     {
         WalkFunction(agent, functionDeclaration.Id, functionDeclaration.Parameters, functionDeclaration.Body, isStrict || new FunctionNode(functionDeclaration.Body).IsStrict);
     }
 }
Example #15
0
        public override dynamic Visit(FunctionDeclarationNode node)
        {
            var functionVisitor = new CfgVisitor(CurrentScope, _result);

            functionVisitor.Visit((StatementListNode)node.Statement);
            var cfg = new CFG
            {
                Blocks   = functionVisitor._blocks,
                Function = node.Function
            };

            _result.Add(cfg);
            //node.Statement.Accept(this);

            return(null);
        }
Example #16
0
        private GSharpMethod CompileMethod(FunctionDeclarationNode funcDecl, bool isInstanceMethod)
        {
            symbolTable.CurrentScope = symbolTable.CurrentScope.ChildScopes[currentScope++];
            GSharpMethod     methodBuilder = new GSharpMethod(funcDecl.Name, funcDecl.Parameters.Count, symbolTable.CurrentScope.SymbolCount, module);
            FunctionCompiler compiler      = new FunctionCompiler(symbolTable, methodBuilder);

            for (int i = 0; i < funcDecl.Parameters.Count; i++)
            {
                methodBuilder.Parameters[funcDecl.Parameters[i]] = symbolTable.GetSymbol(funcDecl.Parameters[i]).Index;
            }
            methodBuilder.IsInstanceMethod = isInstanceMethod;
            compiler.Visit(funcDecl.Children[0]);
            symbolTable.CurrentScope = symbolTable.CurrentScope.ParentScope;
            methodBuilder.EmitInstruction(OperationCode.LoadNull);
            methodBuilder.FinalizeLabels();
            return(methodBuilder);
        }
Example #17
0
        public override dynamic Visit(FunctionDeclarationNode node)
        {
            EnterScope(node.Statement.Scope);
            FunctionStack.Push(node);
            foreach (var par in node.Parameters)
            {
                par.Accept(this);
            }
            // node.Parameters.ForEach(p => p.Accept(this));
            node.Statement.Accept(this);
            FunctionStack.Pop();
            ExitScope();

            var type = node.Type.Accept(this);

            return(type);
        }
Example #18
0
        internal Function(Module module, FunctionDeclarationNode node)
            : base(module, node)
        {
            var parms        = ImmutableArray <Parameter> .Empty;
            var treeParams   = ImmutableArray <TreeParameter> .Empty;
            var treeVariadic = (TreeVariadicParameter?)null;
            var syms         = ImmutableArray <(SyntaxSymbol, TreeVariable)> .Empty;
            var i            = 0;

            foreach (var param in node.ParameterList.Parameters.Nodes)
            {
                var name     = param.NameToken.Text;
                var variadic = param.DotDotToken != null;

                parms = parms.Add(new Parameter(this, param.Attributes, name, i, variadic));

                TreeVariable variable;

                if (!variadic)
                {
                    var p = new TreeParameter(name);

                    variable   = p;
                    treeParams = treeParams.Add(p);
                }
                else
                {
                    variable = treeVariadic = new TreeVariadicParameter(name);
                }

                syms = syms.Add((param.GetAnnotation <SyntaxSymbol>("Symbol"), variable));

                i++;
            }

            Parameters = parms;
            Tree       = new TreeContext(module.Loader, this, treeParams, treeVariadic, ImmutableArray <TreeUpvalue> .Empty);
            _lowerer   = new SyntaxTreeLowerer(module.Loader, Tree, node.Body,
                                               node.GetAnnotation <ImmutableHashSet <SyntaxSymbol> >("Freezes"));

            foreach (var(sym, variable) in syms)
            {
                _lowerer.AddVariable(sym, variable);
            }
        }
Example #19
0
        /// <summary>
        /// 函数定义
        /// </summary>
        /// <param name="node"></param>
        public void Visit(FunctionDeclarationNode node)
        {
            var builder = new StringBuilder();

            builder.Append("函数定义:");
            builder.AppendFormat("    函数名称:{0}\n", node.FunctionName);
            builder.Append("    函数参数:");
            foreach (var item in node.Parameters)
            {
                builder.Append(item);
            }
            builder.AppendLine("    函数体:");
            Console.WriteLine(builder.ToString());
            foreach (var item in node.SubNodes)
            {
                Visit((Object)item);
            }
        }
Example #20
0
                public override void Visit(FunctionDeclarationNode node)
                {
                    var scope = PushFunctionScope();

                    foreach (var param in node.ParameterList.Parameters.Nodes)
                    {
                        var name = param.NameToken;

                        if (name.IsMissing)
                        {
                            continue;
                        }

                        _scope.Define(SyntaxSymbolKind.Immutable, null, param, name.Text);

                        var duplicate = false;

                        foreach (var param2 in node.ParameterList.Parameters.Nodes)
                        {
                            if (param2 != param && param2.NameToken.Text == name.Text)
                            {
                                duplicate = true;
                                break;
                            }
                        }

                        if (!duplicate)
                        {
                            continue;
                        }

                        Error(param, SyntaxDiagnosticKind.DuplicateParameter, name.Location,
                              $"Function parameter '{name}' (of '{node.NameToken}') declared multiple times");
                    }

                    base.Visit(node);

                    node.SetAnnotation("Freezes", scope.GetFreezes());

                    PopScope();
                }
Example #21
0
        public void FunctionDeclarationNoParametersWithReturnTest()
        {
            const string Code = @"
            Func HelloWorld() As Int
            {
                Output(""Hello "" + x);
            }
            ";

            FunctionDeclarationNode func = MyAssert.NoError(() =>
            {
                var lexemes = new Lexer(Code).LexAll();
                var parser  = new ProgramParser(lexemes, Code);
                return(parser.ParseFunctionDeclaration());
            });

            Assert.NotNull(func);
            Assert.AreEqual("HelloWorld", func !.Identifier);
            Assert.AreEqual(0, func.ParameterNodes.Count);
            Assert.NotNull(func.ReturnTypeNode);
            Assert.AreEqual(1, func.BodyNode.Count);
        }
Example #22
0
        internal Module(ModuleLoader loader, ModulePath path, ProgramNode node)
            : base(node.Attributes)
        {
            Loader = loader;
            Path   = path;

            var decls = ImmutableArray <Declaration> .Empty;

            foreach (var decl in node.Declarations)
            {
                if (decl is UseDeclarationNode)
                {
                    continue;
                }

                decls = decls.Add(decl switch
                {
                    ConstantDeclarationNode c => (Declaration) new Constant(this, c),
                    FunctionDeclarationNode f => new Function(this, f),
                    ExternalDeclarationNode e => new External(this, e),
                    TestDeclarationNode t => new Test(this, t),
                    _ => throw DebugAssert.Unreachable(),
                });
Example #23
0
 public virtual T VisitFunctionDeclaration(FunctionDeclarationNode faDeclarationNode)
 {
     throw new NotImplementedException();
 }
Example #24
0
        public ProgramNode ParseToAst()
        {
            _scopes.Push(new ProgramNode());

            while (!EndOfProgram)
            {
                var upcomingToken = PeekNextToken();
                if (upcomingToken is KeywordToken)
                {
                    var keyword     = (KeywordToken)NextToken();
                    var globalScope = _scopes.Count == 1; // There are constraints to what is available on the global scope
                    if (keyword.IsTypeKeyword)
                    {
                        var varType = keyword.ToVariableType();
                        //it must be followed by a identifier:
                        var name = ReadNextToken <IdentifierToken>();
                        //so see what it is (function or variable):
                        Token lookahead = PeekNextToken();
                        if (lookahead is OperatorToken && (((OperatorToken)lookahead).OperatorType == OperatorType.Assignment) || lookahead is StatementSeparatorToken) //variable declaration
                        {
                            if (lookahead is OperatorToken)
                            {
                                NextToken(); //skip the "="
                            }
                            _currentScope.AddStatement(new VariableDeclarationNode(varType, name.Content, ExpressionNode.CreateFromTokens(ReadUntilStatementSeparator())));
                        }
                        else if (lookahead is OpenBraceToken)
                        {
                            var lookaheadOpenBrace = lookahead as OpenBraceToken;
                            if (lookaheadOpenBrace.BraceType == BraceType.Square) //It is a list type declaration
                            {
                                //Ensure that the next token is the close square brace
                                NextToken(); //Go past the opening token
                                var secondLookahead = PeekNextToken();
                                if (secondLookahead is CloseBraceToken && ((CloseBraceToken)secondLookahead).BraceType == BraceType.Square)
                                {
                                    NextToken(); //Good, it matched, now skip that too
                                    //Add a list declaration node
                                    _currentScope.AddStatement(new ListDeclarationNode(varType, name.Content, ExpressionNode.CreateFromTokens(ReadUntilStatementSeparator())));
                                }
                                else
                                {
                                    throw new UnexpectedTokenException("Missing close square bracket in array declaration");
                                }
                            }
                            //If in the global scope, it can also be a function declaration
                            else if (globalScope && lookaheadOpenBrace.BraceType == BraceType.Round) //function definition
                            {
                                var func = new FunctionDeclarationNode(name.Content);
                                _currentScope.AddStatement(func);                                                                                //add the function to the old (root) scope...
                                _scopes.Push(func);                                                                                              //...and set it a the new scope!
                                                                                                                                                 //Read the argument list
                                NextToken();                                                                                                     //skip the opening brace
                                while (!(PeekNextToken() is CloseBraceToken && ((CloseBraceToken)PeekNextToken()).BraceType == BraceType.Round)) //TODO: Refactor using readUntilClosingBrace?
                                {
                                    var argType = ReadNextToken <KeywordToken>();
                                    if (!argType.IsTypeKeyword)
                                    {
                                        throw new ParsingException("Expected type keyword!");
                                    }
                                    var argName = ReadNextToken <IdentifierToken>();
                                    func.AddParameter(new ParameterDeclarationNode(argType.ToVariableType(), argName.Content));
                                    if (PeekNextToken() is ArgSeperatorToken) //TODO: Does this allow (int a int b)-style functions? (No arg-seperator!)
                                    {
                                        NextToken();                          //skip the sperator
                                    }
                                }
                                NextToken(); //skip the closing brace
                                var curlyBrace = ReadNextToken <OpenBraceToken>();
                                if (curlyBrace.BraceType != BraceType.Curly)
                                {
                                    throw new ParsingException("Wrong brace type found!");
                                }
                            }
                        }
                        else
                        {
                            throw new Exception("The parser encountered an unexpected token.");
                        }
                        //We can't have anything other than what's listed above on the global scope
                    }
                    //Not a type keyword. If on a local scope, it may be other keywords
                    else if (!globalScope)
                    {
                        switch (keyword.KeywordType)
                        {
                        case KeywordType.Return:
                            _currentScope.AddStatement(new ReturnStatementNode(ExpressionNode.CreateFromTokens(ReadUntilStatementSeparator())));
                            break;

                        case KeywordType.If:
                            var @if = new IfStatementNode(ExpressionNode.CreateFromTokens(ReadUntilClosingBrace(true)));
                            _currentScope.AddStatement(@if); //Add if statement to previous scope
                            _scopes.Push(@if);               //...and set it a the new scope!
                            NextToken();                     //skip the opening curly brace
                            break;

                        case KeywordType.While:
                            var @while = new WhileLoopNode(ExpressionNode.CreateFromTokens(ReadUntilClosingBrace(true)));
                            _currentScope.AddStatement(@while);
                            _scopes.Push(@while);
                            NextToken();     //skip the opening curly brace
                            break;

                        default:
                            throw new ParsingException("Unexpected keyword type.");
                        }
                    }
                    else //It was not a keyword, and it was a global scope
                    {
                        throw new ParsingException("Found non-type keyword on global scope.");
                    }
                }
                else if (upcomingToken is IdentifierToken && _scopes.Count > 1) //in a nested scope
                {
                    var identifierToken = upcomingToken as IdentifierToken;
                    NextToken();                                                                                          //Step past the identifier token
                    var nextToken = PeekNextToken();                                                                      //Read the next token
                    if (nextToken is OperatorToken && ((OperatorToken)nextToken).OperatorType == OperatorType.Assignment) //variable assignment
                    {
                        NextToken();                                                                                      //skip the "="
                        _currentScope.AddStatement(new VariableAssignmentNode(identifierToken.Content, ExpressionNode.CreateFromTokens(ReadUntilStatementSeparator())));
                    }
                    else if (nextToken is MemberAccessToken)
                    {
                        List <MemberAccessToken> memberAccessTokens = new List <MemberAccessToken>();
                        Token currentTestToken;
                        while ((currentTestToken = PeekNextToken()) is MemberAccessToken) //They can be stacked
                        {
                            NextToken();                                                  //Advance
                            memberAccessTokens.Add(currentTestToken as MemberAccessToken);
                        }
                        if (currentTestToken is OperatorToken && ((OperatorToken)currentTestToken).OperatorType == OperatorType.Assignment) //table member assignment
                        {
                            NextToken();                                                                                                    //skip the "="
                                                                                                                                            //Tokens until statement end have to be preloaded as a 'temporary workaround' to allow looking forward
                            var expressionTokens = ReadUntilStatementSeparator().ToList();
                            _currentScope.AddStatement(new TableAssignmentNode(TableQualifier.Create(identifierToken, memberAccessTokens), ExpressionNode.CreateFromTokens(expressionTokens)));
                        }
                        else if (currentTestToken is OpenBraceToken && ((OpenBraceToken)currentTestToken).BraceType == BraceType.Round)
                        {
                            //Member invocation
                            var fakeIdentifierToken = new IdentifierToken(identifierToken.Content); //So it will be parsed as a function call
                            var memberInvocationInternalFunctionCall = ExpressionNode.CreateFromTokens(new[] { fakeIdentifierToken }.Concat(ReadUntilStatementSeparator())) as FunctionCallExpressionNode;
                            _currentScope.AddStatement(new TableMemberInvocationNode(TableQualifier.Create(identifierToken, memberAccessTokens), memberInvocationInternalFunctionCall.Arguments));
                        }
                    }
                    else //lone expression (incl. function calls!)
                    {
                        _currentScope.AddStatement(ExpressionNode.CreateFromTokens(new[] { identifierToken }.Concat(ReadUntilStatementSeparator()))); //don't forget the name here!
                    }
                }
                else if (upcomingToken is CloseBraceToken)
                {
                    //Closing a scope
                    var brace = ReadNextToken <CloseBraceToken>();
                    if (brace.BraceType != BraceType.Curly)
                    {
                        throw new ParsingException("Wrong brace type found!");
                    }
                    _scopes.Pop(); //Scope has been closed!
                }
                else
                {
                    throw new UnexpectedTokenException("The parser ran into an unexpected token", upcomingToken);
                }
            }

            if (_scopes.Count != 1)
            {
                throw new ParsingException("The scopes are not correctly nested.");
            }

            return((ProgramNode)_scopes.Pop());
        }
Example #25
0
                public override void Visit(ProgramNode node)
                {
                    _path = CreatePath(node.Path);

                    foreach (var decl in node.Declarations)
                    {
                        if (!(decl is UseDeclarationNode use))
                        {
                            continue;
                        }

                        var path = CreateCorrectPath(use.Path);

                        if (path == null)
                        {
                            continue;
                        }

                        if (use.Alias is UseDeclarationAliasNode alias && !alias.NameToken.IsMissing)
                        {
                            var name      = alias.NameToken;
                            var duplicate = false;

                            foreach (var decl2 in node.Declarations)
                            {
                                if (decl2 is UseDeclarationNode use2 && use2.Alias is UseDeclarationAliasNode alias2 &&
                                    alias2 != alias && alias2.NameToken.Text == name.Text)
                                {
                                    duplicate = true;
                                    break;
                                }
                            }

                            if (!duplicate)
                            {
                                _aliases.Add(name.Text, path);
                            }
                            else
                            {
                                Error(alias, SyntaxDiagnosticKind.DuplicateUseDeclarationAlias, name.Location,
                                      $"Module alias '{name}' declared multiple times");
                            }
                        }

                        if (!(LoadModule(use, use.Path.ComponentTokens.Tokens[0].Location, path) is Module mod))
                        {
                            continue;
                        }

                        // Don't import symbols if the module is aliased.
                        if (use.Alias != null)
                        {
                            continue;
                        }

                        foreach (var mdecl in mod.Declarations)
                        {
                            if (!mdecl.IsPublic)
                            {
                                continue;
                            }

                            var sym = mdecl switch
                            {
                                Constant _ => SyntaxSymbolKind.Constant,
                                Function _ => SyntaxSymbolKind.Function,
                                External _ => SyntaxSymbolKind.External,
                                _ => (SyntaxSymbolKind?)null,
                            };

                            if (sym is SyntaxSymbolKind kind)
                            {
                                _scope.Define(kind, path, null, mdecl.Name);
                            }
                        }
                    }

                    foreach (var decl in node.Declarations)
                    {
                        if (!(decl is NamedDeclarationNode named) || decl is MissingNamedDeclarationNode)
                        {
                            continue;
                        }

                        var name = named.NameToken;

                        if (name.IsMissing)
                        {
                            continue;
                        }

                        if (name.Text.StartsWith('_'))
                        {
                            Error(named, SyntaxDiagnosticKind.InvalidDeclarationName, name.Location,
                                  $"Declaration '{name}' is invalid; declaration names cannot start with '_'");
                            continue;
                        }

                        var duplicate = false;

                        foreach (var decl2 in node.Declarations)
                        {
                            if (decl2 == decl || !(decl2 is NamedDeclarationNode named2) ||
                                decl2 is MissingNamedDeclarationNode)
                            {
                                continue;
                            }

                            var name2 = named2.NameToken;

                            if (name2.Text != name.Text)
                            {
                                continue;
                            }

                            duplicate = true;
                        }

                        if (duplicate)
                        {
                            Error(named, SyntaxDiagnosticKind.DuplicateDeclaration, name.Location,
                                  $"Declaration name '{name}' declared multiple times");
                            continue;
                        }

                        var sym = decl switch
                        {
                            ConstantDeclarationNode _ => SyntaxSymbolKind.Constant,
                            FunctionDeclarationNode _ => SyntaxSymbolKind.Function,
                            ExternalDeclarationNode _ => SyntaxSymbolKind.External,
                            _ => (SyntaxSymbolKind?)null,
                        };

                        if (sym is SyntaxSymbolKind kind)
                        {
                            _scope.Define(kind, _path, decl, name.Text);
                        }
                    }

                    foreach (var decl in node.Declarations)
                    {
                        if (!(decl is TestDeclarationNode test))
                        {
                            continue;
                        }

                        var name = test.NameToken;

                        if (name.Text.StartsWith('_'))
                        {
                            Error(test, SyntaxDiagnosticKind.InvalidDeclarationName, name.Location,
                                  $"Test name '{name}' is invalid; test names cannot start with '_'");
                            continue;
                        }

                        var duplicate = false;

                        foreach (var decl2 in node.Declarations)
                        {
                            if (decl2 != decl && decl2 is TestDeclarationNode test2 &&
                                test2.NameToken.Text == name.Text)
                            {
                                duplicate = true;
                                break;
                            }
                        }

                        if (duplicate)
                        {
                            Error(test, SyntaxDiagnosticKind.DuplicateDeclaration, name.Location,
                                  $"Test '{name}' declared multiple times");
                            continue;
                        }
                    }

                    base.Visit(node);
                }
Example #26
0
 public string Visit(FunctionDeclarationNode node)
 {
     var output = ASTHelper.PrintToken(node.Token) + ASTHelper.PrintToken(node.Name) + ASTHelper.PrintToken(node.OpeningParenthesis);
 public string VisitFunctionDeclaration(FunctionDeclarationNode faDeclarationNode)
 {
     throw new NotImplementedException();
 }
Example #28
0
 public abstract dynamic Visit(FunctionDeclarationNode node);
Example #29
0
        public ProgramNode ParseToAst()
        {
            scopes.Push(new ProgramNode());

            while (!eof())
            {
                if (peek() is KeywordToken)
                {
                    var keyword = (KeywordToken)next();

                    if (scopes.Count == 1) //we are a top level, the only valid keywords are variable types, starting a variable or function definition
                    {
                        if (keyword.IsTypeKeyword)
                        {
                            var varType = keyword.ToVariableType();
                            //it must be followed by a identifier:
                            var name = readToken <IdentifierToken>();
                            //so see what it is (function or variable):
                            Token lookahead = peek();
                            if (lookahead is OperatorToken && (((OperatorToken)lookahead).OperatorType == OperatorType.Assignment) || lookahead is StatementSperatorToken) //variable declaration
                            {
                                if (lookahead is OperatorToken)
                                {
                                    next(); //skip the "="
                                }
                                scopes.Peek().AddStatement(new VariableDeclarationNode(varType, name.Content, ExpressionNode.CreateFromTokens(readUntilStatementSeperator())));
                            }
                            else if (lookahead is OpenBraceToken && (((OpenBraceToken)lookahead).BraceType == BraceType.Round)) //function definition
                            {
                                var func = new FunctionDeclarationNode(name.Content);
                                scopes.Peek().AddStatement(func);                                                              //add the function to the old (root) scope...
                                scopes.Push(func);                                                                             //...and set it a the new scope!
                                //Read the argument list
                                next();                                                                                        //skip the opening brace
                                while (!(peek() is CloseBraceToken && ((CloseBraceToken)peek()).BraceType == BraceType.Round)) //TODO: Refactor using readUntilClosingBrace?
                                {
                                    var argType = readToken <KeywordToken>();
                                    if (!argType.IsTypeKeyword)
                                    {
                                        throw new ParsingException("Expected type keyword!");
                                    }
                                    var argName = readToken <IdentifierToken>();
                                    func.AddParameter(new ParameterDeclarationNode(argType.ToVariableType(), argName.Content));
                                    if (peek() is ArgSeperatorToken) //TODO: Does this allow (int a int b)-style functions? (No arg-seperator!)
                                    {
                                        next();                      //skip the sperator
                                    }
                                }
                                next(); //skip the closing brace
                                var curlyBrace = readToken <OpenBraceToken>();
                                if (curlyBrace.BraceType != BraceType.Curly)
                                {
                                    throw new ParsingException("Wrong brace type found!");
                                }
                            }
                            else
                            {
                                throw new Exception("The parser encountered an unexpected token.");
                            }
                        }
                        else
                        {
                            throw new ParsingException("Found non-type keyword on top level.");
                        }
                    }
                    else //we are in a nested scope
                    {
                        //TODO: Can we avoid the code duplication from above?
                        if (keyword.IsTypeKeyword) //local variable declaration!
                        {
                            var varType = keyword.ToVariableType();
                            //it must be followed by a identifier:
                            var name = readToken <IdentifierToken>();
                            //so see what it is (function or variable):
                            Token lookahead = peek();
                            if (lookahead is OperatorToken && (((OperatorToken)lookahead).OperatorType == OperatorType.Assignment) || lookahead is StatementSperatorToken) //variable declaration
                            {
                                if (lookahead is OperatorToken)
                                {
                                    next(); //skip the "="
                                }
                                scopes.Peek().AddStatement(new VariableDeclarationNode(varType, name.Content, ExpressionNode.CreateFromTokens(readUntilStatementSeperator())));
                            }
                        }
                        else
                        {
                            switch (keyword.KeywordType)
                            {
                            case KeywordType.Return:
                                scopes.Peek().AddStatement(new ReturnStatementNode(ExpressionNode.CreateFromTokens(readUntilStatementSeperator())));
                                break;

                            case KeywordType.If:
                                var @if = new IfStatementNode(ExpressionNode.CreateFromTokens(readUntilClosingBrace()));
                                scopes.Peek().AddStatement(@if);
                                scopes.Push(@if);
                                break;

                            case KeywordType.While:
                                var @while = new WhileLoopNode(ExpressionNode.CreateFromTokens(readUntilClosingBrace()));
                                scopes.Peek().AddStatement(@while);
                                scopes.Push(@while);
                                break;

                            default:
                                throw new ParsingException("Unexpected keyword type.");
                            }
                        }
                    }
                }
                else if (peek() is IdentifierToken && scopes.Count > 1) //in nested scope
                {
                    var name = readToken <IdentifierToken>();
                    if (peek() is OperatorToken && ((OperatorToken)peek()).OperatorType == OperatorType.Assignment) //variable assignment
                    {
                        next();                                                                                     //skip the "="
                        scopes.Peek().AddStatement(new VariableAssingmentNode(name.Content, ExpressionNode.CreateFromTokens(readUntilStatementSeperator())));
                    }
                    else //lone expression (incl. function calls!)
                    {
                        scopes.Peek().AddStatement(ExpressionNode.CreateFromTokens(new[] { name }.Concat(readUntilStatementSeperator()))); //don't forget the name here!
                    }
                }
                else if (peek() is CloseBraceToken)
                {
                    var brace = readToken <CloseBraceToken>();
                    if (brace.BraceType != BraceType.Curly)
                    {
                        throw new ParsingException("Wrong brace type found!");
                    }
                    scopes.Pop(); //Scope has been closed!
                }
                else
                {
                    throw new ParsingException("The parser ran into an unexpeted token.");
                }
            }

            if (scopes.Count != 1)
            {
                throw new ParsingException("The scopes are not correctly nested.");
            }

            return((ProgramNode)scopes.Pop());
        }
Example #30
0
        public void Accept(FunctionDeclarationNode node)
        {
            // Funcs are lowercase
            HassiumWarning.EnforceCasing(module, node.SourceLocation, node.Name, HassiumCasingType.Lower);

            var method = new HassiumMethod(module, node.Name);

            method.DocStr    = node.DocStr;
            method.IsPrivate = node.IsPrivate;
            methodStack.Push(method);
            method.SourceLocation       = node.SourceLocation;
            method.SourceRepresentation = node.ToString();
            method.Parent = classStack.Peek();

            table.EnterScope();

            foreach (var param in node.Parameters)
            {
                if (param.FunctionParameterType == FunctionParameterType.Enforced)
                {
                    methodStack.Push(new HassiumMethod(module));
                    methodStack.Peek().Parent = classStack.Peek();
                    param.Type.Visit(this);
                    emit(param.Type.SourceLocation, InstructionType.Return);
                    param.EnforcedType = methodStack.Pop();
                }
                method.Parameters.Add(param, table.AddSymbol(param.Name));
            }

            if (node.Body is CodeBlockNode)
            {
                node.Body.VisitChildren(this);
            }
            else
            {
                node.Body.Visit(this);
            }

            if (node.EnforcedReturnType != null)
            {
                methodStack.Push(new HassiumMethod(module));
                node.EnforcedReturnType.Visit(this);
                emit(node.EnforcedReturnType.SourceLocation, InstructionType.Return);
                method.ReturnType = methodStack.Pop();
            }

            table.LeaveScope();
            method = methodStack.Pop();

            if (classStack.Peek().ContainsAttribute(method.Name))
            {
                var attrib = classStack.Peek().BoundAttributes[method.Name];
                if (attrib is HassiumMultiFunc)
                {
                    (attrib as HassiumMultiFunc).Methods.Add(method);
                }
                else
                {
                    classStack.Peek().BoundAttributes.Remove(method.Name);
                    var multiFunc = new HassiumMultiFunc();
                    multiFunc.Methods.Add(attrib as HassiumMethod);
                    multiFunc.Methods.Add(method);
                    classStack.Peek().AddAttribute(method.Name, multiFunc);
                }
            }
            else
            {
                classStack.Peek().AddAttribute(method.Name, method);
            }
        }