예제 #1
0
        public void TestPopComparison()
        {
            var scope = new InterpreterScope();

            var array    = new ArrayExpression();
            var funcCall = new FunctionCallExpression("happy", new ExpressionBase[] { new IntegerConstantExpression(1) });

            array.Entries.Add(new ComparisonExpression(funcCall, ComparisonOperation.Equal, new IntegerConstantExpression(2)));
            scope.DefineVariable(new VariableDefinitionExpression("arr"), array);

            var happyFunc = new FunctionDefinitionExpression("happy");

            happyFunc.Parameters.Add(new VariableDefinitionExpression("num1"));
            happyFunc.Expressions.Add(new ReturnExpression(new VariableExpression("num1")));
            scope.AddFunction(happyFunc);

            var entry = Evaluate("array_pop(arr)", scope);

            Assert.That(entry, Is.InstanceOf <ComparisonExpression>());

            var comparison = (ComparisonExpression)entry;

            Assert.That(comparison.Left, Is.InstanceOf <FunctionCallExpression>());
            Assert.That(((FunctionCallExpression)comparison.Left).FunctionName.Name, Is.EqualTo("happy"));
            Assert.That(comparison.Right, Is.InstanceOf <IntegerConstantExpression>());
            Assert.That(((IntegerConstantExpression)comparison.Right).Value, Is.EqualTo(2));
        }
예제 #2
0
        internal static int LoadFunction(Script script, SourceCode source, ByteCode bytecode, bool usesGlobalEnv)
        {
            var lcontext = CreateLoadingContext(script, source);

            try
            {
                FunctionDefinitionExpression fnx;

                fnx = new FunctionDefinitionExpression(lcontext, usesGlobalEnv);

                int beginIp;

                using (bytecode.EnterSource(null))
                {
                    bytecode.Emit_Nop($"Begin function {source.Name}");
                    beginIp = fnx.CompileBody(bytecode, source.Name);
                    bytecode.Emit_Nop($"End function {source.Name}");
                }

                return(beginIp);
            }
            catch (SyntaxErrorException ex)
            {
                ex.DecorateMessage(script);
                ex.Rethrow();
                throw;
            }
        }
예제 #3
0
        public void TestReplaceVariablesIndexFunctionCall()
        {
            var input     = "function func(i) => 6";
            var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(input));

            tokenizer.Match("function");
            var functionDefinition = (FunctionDefinitionExpression)FunctionDefinitionExpression.Parse(tokenizer);

            var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new IntegerConstantExpression(2) });
            var value        = new IntegerConstantExpression(98);

            var variable = new VariableExpression("variable");
            var dict     = new DictionaryExpression();

            dict.Entries.Add(new DictionaryExpression.DictionaryEntry {
                Key = new IntegerConstantExpression(6), Value = value
            });

            var scope = new InterpreterScope();

            scope.AssignVariable(variable, dict);
            scope.AddFunction(functionDefinition);

            var expr = new IndexedVariableExpression(variable, functionCall);

            ExpressionBase result;

            Assert.That(expr.ReplaceVariables(scope, out result), Is.True);
            Assert.That(result, Is.InstanceOf <IntegerConstantExpression>());
            Assert.That(((IntegerConstantExpression)result).Value, Is.EqualTo(98));
        }
예제 #4
0
        internal static int LoadFunction(Script script, SourceCode source, ByteCode bytecode, bool usesGlobalEnv)
        {
            ScriptLoadingContext lcontext = CreateLoadingContext(script, source);

            try
            {
                FunctionDefinitionExpression fnx;

                using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.AstCreation))
                    fnx = new FunctionDefinitionExpression(lcontext, usesGlobalEnv);

                int beginIp = -1;

                //var srcref = new SourceRef(source.SourceID);

                using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Compilation))
                    using (bytecode.EnterSource(null))
                    {
                        bytecode.Emit_Nop(string.Format("Begin function {0}", source.Name));
                        beginIp = fnx.CompileBody(bytecode, source.Name);
                        bytecode.Emit_Nop(string.Format("End function {0}", source.Name));
                    }

                //Debug_DumpByteCode(bytecode, source.SourceID);

                return(beginIp);
            }
            catch (SyntaxErrorException ex)
            {
                ex.DecorateMessage(script);
                ex.Rethrow();
                throw;
            }
        }
예제 #5
0
        public void TestReplaceVariablesMethodCall()
        {
            var input     = "function func(i) { j = i }";
            var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(input));

            tokenizer.Match("function");
            var functionDefinition = (FunctionDefinitionExpression)FunctionDefinitionExpression.Parse(tokenizer);

            var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new IntegerConstantExpression(2) });
            var value1       = new IntegerConstantExpression(98);
            var expr         = new DictionaryExpression();

            expr.Entries.Add(new DictionaryExpression.DictionaryEntry {
                Key = functionCall, Value = value1
            });

            var scope = new InterpreterScope();

            scope.AddFunction(functionDefinition);

            ExpressionBase result;

            Assert.That(expr.ReplaceVariables(scope, out result), Is.False);
            Assert.That(result, Is.InstanceOf <ParseErrorExpression>());
            Assert.That(((ParseErrorExpression)result).Message, Is.EqualTo("func did not return a value"));
        }
예제 #6
0
        public void TestReplaceVariablesFunctionCall()
        {
            var input     = "function func(i) => 6";
            var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(input));

            tokenizer.Match("function");
            var functionDefinition = (FunctionDefinitionExpression)FunctionDefinitionExpression.Parse(tokenizer);

            var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new IntegerConstantExpression(2) });
            var value1       = new IntegerConstantExpression(98);
            var expr         = new DictionaryExpression();

            expr.Entries.Add(new DictionaryExpression.DictionaryEntry {
                Key = functionCall, Value = value1
            });

            var scope = new InterpreterScope();

            scope.AddFunction(functionDefinition);

            ExpressionBase result;

            Assert.That(expr.ReplaceVariables(scope, out result), Is.True);
            Assert.That(result, Is.InstanceOf <DictionaryExpression>());
            var dictResult = (DictionaryExpression)result;

            Assert.That(dictResult.Entries.Count, Is.EqualTo(1));
            Assert.That(dictResult.Entries[0].Key, Is.EqualTo(new IntegerConstantExpression(6)));
            Assert.That(dictResult.Entries[0].Value, Is.EqualTo(value1));
        }
예제 #7
0
        public void TestAddAndGetFunction()
        {
            var function = new FunctionDefinitionExpression("test");
            var scope    = new InterpreterScope();

            scope.AddFunction(function);
            Assert.That(scope.GetFunction("test"), Is.SameAs(function));
        }
예제 #8
0
        private FunctionDefinitionExpression Parse(string input)
        {
            var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(input));

            tokenizer.Match("function");
            var expr = FunctionDefinitionExpression.Parse(tokenizer);

            Assert.That(expr, Is.InstanceOf <FunctionDefinitionExpression>());
            return((FunctionDefinitionExpression)expr);
        }
예제 #9
0
        public void TestParseErrorInsideDefinition()
        {
            var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer("function func() { if (j) { j = i } }"));

            tokenizer.Match("function");
            var expr = FunctionDefinitionExpression.Parse(tokenizer);

            Assert.That(expr, Is.InstanceOf <ParseErrorExpression>());
            Assert.That(((ParseErrorExpression)expr).Message, Is.EqualTo("Expected conditional statement following if"));
        }
        public void TestAppendStringNoParameters()
        {
            var expr = new FunctionDefinitionExpression("func");

            var builder = new StringBuilder();

            expr.AppendString(builder);
            Assert.That(builder.ToString(), Is.EqualTo("function func()"));
            // NOTE: does not output Expressions block
        }
 protected virtual Expression VisitFunctionDefinition(FunctionDefinitionExpression node)
 {
     node.Arguments.ForEach(arg => {
         if (arg.HasDefault)
         {
             Visit(arg.DefaultValue);
         }
     });
     Visit(node.Body);
     return(node);
 }
		public FunctionDefinitionStatement(LuaParser.Stat_localfuncdefContext context, ScriptLoadingContext lcontext)
			: base(context, lcontext)
		{
			m_Local = true;
			m_FuncSymbol = lcontext.Scope.TryDefineLocal(context.NAME().GetText());
			m_FuncDef = new FunctionDefinitionExpression(context.funcbody(), lcontext, context);

			m_SourceRef = BuildSourceRef(context.Start, context.Stop);

			m_FriendlyName = string.Format("{0} (local)", m_FuncSymbol.i_Name);
		}
예제 #13
0
        public void TestGetParametersNone()
        {
            var functionDefinition = new FunctionDefinitionExpression("f");
            var scope        = new InterpreterScope();
            var functionCall = new FunctionCallExpression("f", new ExpressionBase[0]);

            ExpressionBase error;
            var            innerScope = functionCall.GetParameters(functionDefinition, scope, out error);

            Assert.That(innerScope, Is.Not.Null);
            Assert.That(error, Is.Null);
            Assert.That(innerScope.VariableCount, Is.EqualTo(0));
        }
		public FunctionDefinitionStatement(LuaParser.Stat_funcdefContext context, ScriptLoadingContext lcontext)
			: base(context, lcontext)
		{
			m_Local = false;
			var node_funcname = context.funcname();
			var fnname = node_funcname.fnname;
			var methodaccessor = node_funcname.methodaccessor;
			var tableaccessor = node_funcname.funcnametableaccessor();

			string nameOfMethodAccessor = methodaccessor != null ? methodaccessor.Text : null;
			m_TableAccessors = tableaccessor != null ? tableaccessor.Select(s => s.NAME().GetText()).ToList() : new List<string>();

			m_SourceRef = BuildSourceRef(context.Start, context.Stop).SetNoBreakPoint();

			m_FuncDef = new FunctionDefinitionExpression(context.funcbody(), lcontext, context, nameOfMethodAccessor != null);

			if (nameOfMethodAccessor != null || m_TableAccessors.Count > 0)
			{
				m_FuncSymbol = lcontext.Scope.Find(fnname.Text);

				m_FriendlyName = fnname.Text + "." + string.Join(".", m_TableAccessors.ToArray());

				if (nameOfMethodAccessor != null)
					m_FriendlyName += ":" + nameOfMethodAccessor;
			}
			else
			{
				m_FuncSymbol = lcontext.Scope.Find(fnname.Text);
				m_FriendlyName = fnname.Text;
			}

			if (nameOfMethodAccessor != null)
			{
				m_MethodName = nameOfMethodAccessor;
			}
			else if (m_TableAccessors.Count > 0)
			{
				m_MethodName = m_TableAccessors[m_TableAccessors.Count - 1];
				m_TableAccessors.RemoveAt(m_TableAccessors.Count - 1);
			}
		}
예제 #15
0
        internal static int LoadFunction(Script script, SourceCode source, ByteCode bytecode, Table globalContext)
        {
            AntlrErrorListener listener = new AntlrErrorListener(source);

            try
            {
                LuaParser parser = CreateParser(script, new AntlrInputStream(source.Code), source.SourceID, p => p.singlefunc(), listener);

                ScriptLoadingContext         lcontext = CreateLoadingContext(script, source);
                FunctionDefinitionExpression fndef;

                using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.AstCreation))
                    fndef = new FunctionDefinitionExpression(parser.anonfunctiondef(), lcontext, false, globalContext);

                int beginIp = -1;

                // var srcref = new SourceRef(source.SourceID);

                using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Compilation))
                    using (bytecode.EnterSource(null))
                    {
                        bytecode.Emit_Nop(string.Format("Begin function {0}", source.Name));
                        beginIp = fndef.CompileBody(bytecode, source.Name);
                        bytecode.Emit_Nop(string.Format("End function {0}", source.Name));

                        Debug_DumpByteCode(bytecode, source.SourceID);
                    }

                return(beginIp);
            }
            catch (ParseCanceledException ex)
            {
                HandleParserError(ex, listener);
                throw;
            }
        }
예제 #16
0
        public void TestPopFunctionCall()
        {
            var scope = new InterpreterScope();

            var array = new ArrayExpression();

            array.Entries.Add(new FunctionCallExpression("happy", new ExpressionBase[] { new IntegerConstantExpression(1) }));
            scope.DefineVariable(new VariableDefinitionExpression("arr"), array);

            var happyFunc = new FunctionDefinitionExpression("happy");

            happyFunc.Parameters.Add(new VariableDefinitionExpression("num1"));
            happyFunc.Expressions.Add(new ReturnExpression(new VariableExpression("num1")));
            scope.AddFunction(happyFunc);

            var entry = Evaluate("array_pop(arr)", scope);

            // function call should not be evaluated when it's popped off the array
            Assert.That(entry, Is.InstanceOf <FunctionCallExpression>());
            Assert.That(((FunctionCallExpression)entry).FunctionName.Name, Is.EqualTo("happy"));
            Assert.That(((FunctionCallExpression)entry).Parameters.Count, Is.EqualTo(1));

            Assert.That(array.Entries.Count, Is.EqualTo(0));
        }
예제 #17
0
 private bool EvaluateFunctionDefinition(FunctionDefinitionExpression expression, InterpreterScope scope)
 {
     scope.AddFunction(expression);
     return(true);
 }
예제 #18
0
        public FunctionDefinitionStatement(ScriptLoadingContext lcontext, bool local, Token localToken)
            : base(lcontext)
        {
            // here lexer must be at the 'function' keyword
            Token funcKeyword = CheckTokenType(lcontext, TokenType.Function);

            funcKeyword = localToken ?? funcKeyword;             // for debugger purposes

            m_Local = local;

            if (m_Local)
            {
                Token name = CheckTokenType(lcontext, TokenType.Name);
                m_FuncSymbol   = lcontext.Scope.TryDefineLocal(name.Text);
                m_FriendlyName = string.Format("{0} (local)", name.Text);
                m_SourceRef    = funcKeyword.GetSourceRef(name);
            }
            else
            {
                Token  name      = CheckTokenType(lcontext, TokenType.Name);
                string firstName = name.Text;

                m_SourceRef = funcKeyword.GetSourceRef(name);

                m_FuncSymbol   = lcontext.Scope.Find(firstName);
                m_FriendlyName = firstName;

                if (lcontext.Lexer.Current.Type != TokenType.Brk_Open_Round)
                {
                    m_TableAccessors = new List <string>();

                    while (lcontext.Lexer.Current.Type != TokenType.Brk_Open_Round)
                    {
                        Token separator = lcontext.Lexer.Current;

                        if (separator.Type != TokenType.Colon && separator.Type != TokenType.Dot)
                        {
                            UnexpectedTokenType(separator);
                        }

                        lcontext.Lexer.Next();

                        Token field = CheckTokenType(lcontext, TokenType.Name);

                        m_FriendlyName += separator.Text + field.Text;
                        m_SourceRef     = funcKeyword.GetSourceRef(field);

                        if (separator.Type == TokenType.Colon)
                        {
                            m_MethodName = field.Text;
                            m_IsMethodCallingConvention = true;
                            break;
                        }
                        else
                        {
                            m_TableAccessors.Add(field.Text);
                        }
                    }

                    if (m_MethodName == null && m_TableAccessors.Count > 0)
                    {
                        m_MethodName = m_TableAccessors[m_TableAccessors.Count - 1];
                        m_TableAccessors.RemoveAt(m_TableAccessors.Count - 1);
                    }
                }
            }

            m_FuncDef = new FunctionDefinitionExpression(lcontext, m_IsMethodCallingConvention, false);
            lcontext.Source.Refs.Add(m_SourceRef);
        }
        public FunctionDefinitionStatement(ScriptLoadingContext lcontext, bool local, Token localToken) : base(lcontext)
        {
            // here lexer must be at the 'function' keyword
            var funcKeyword = CheckTokenType(lcontext, TokenType.Function);

            funcKeyword = localToken ?? funcKeyword; // for debugger purposes

            _local = local;

            if (_local)
            {
                var name = CheckTokenType(lcontext, TokenType.Name);
                _funcSymbol   = lcontext.Scope.TryDefineLocal(name.Text);
                _friendlyName = $"{name.Text} (local)";
                _sourceRef    = funcKeyword.GetSourceRef(name);
            }
            else
            {
                var    name      = CheckTokenType(lcontext, TokenType.Name);
                string firstName = name.Text;

                _sourceRef = funcKeyword.GetSourceRef(name);

                _funcSymbol   = lcontext.Scope.Find(firstName);
                _friendlyName = firstName;

                if (lcontext.Lexer.Current.Type != TokenType.Brk_Open_Round)
                {
                    _tableAccessors = new List <string>();

                    while (lcontext.Lexer.Current.Type != TokenType.Brk_Open_Round)
                    {
                        var separator = lcontext.Lexer.Current;

                        if (separator.Type != TokenType.Colon && separator.Type != TokenType.Dot)
                        {
                            UnexpectedTokenType(separator);
                        }

                        lcontext.Lexer.Next();

                        var field = CheckTokenType(lcontext, TokenType.Name);

                        _friendlyName += $"{separator.Text}{field.Text}";
                        _sourceRef     = funcKeyword.GetSourceRef(field);

                        if (separator.Type == TokenType.Colon)
                        {
                            _methodName = field.Text;
                            _isMethodCallingConvention = true;
                            break;
                        }

                        _tableAccessors.Add(field.Text);
                    }

                    if (_methodName == null && _tableAccessors.Count > 0)
                    {
                        _methodName = _tableAccessors[_tableAccessors.Count - 1];
                        _tableAccessors.RemoveAt(_tableAccessors.Count - 1);
                    }
                }
            }

            _funcDef = new FunctionDefinitionExpression(lcontext, _isMethodCallingConvention, false);
            lcontext.Source.Refs.Add(_sourceRef);
        }