Example #1
0
        internal ScriptFunctionObject AsyncFunctionCreate(FunctionKind kind, [NotNull] IReadOnlyList <ExpressionNode> parameters, [NotNull] BaseNode body, [NotNull] LexicalEnvironment scope, bool strict)
        {
            //https://tc39.github.io/ecma262/#sec-async-functions-abstract-operations-async-function-create
            var function = FunctionAllocate(Realm.AsyncFunctionPrototype, strict, FunctionKind.Async);

            return(FunctionInitialise(function, kind, parameters, body, scope));
        }
Example #2
0
 internal ScriptFunctionObject([NotNull] Realm realm, [NotNull] ScriptObject prototype, bool extensible, FunctionKind functionKind, ConstructorKind constructorKind, bool strict) :
     base(realm, prototype, extensible, SpecialObjectType.None)
 {
     FunctionKind    = functionKind;
     ConstructorKind = constructorKind;
     Strict          = strict;
 }
Example #3
0
 private void ChangePosition(Direction direction)                                                                                 //改变选择框位置
 {
     if (direction == Direction.up)                                                                                               //如果选择向上移动选择框
     {
         transform.position += new Vector3(0, (Mathf.Abs(transform.position.y - maxHeight) < 0.1f) ? (-interval * 4) : interval); //如果不是选择第一个功能,选择框上移,否则回到最后一个
         if (currentFunction == FunctionKind.explode)                                                                             //如果是第一种功能
         {
             currentFunction = FunctionKind.magnet;                                                                               //回到最后一种功能
         }
         else
         {
             currentFunction--;//选择上一种功能
         }
     }
     else if (direction == Direction.down)                                                                                        //如果选择向下移动选择框
     {
         transform.position += new Vector3(0, (Mathf.Abs(transform.position.y - minHeight) < 0.1f) ? (interval * 4) : -interval); //如果不是选择最后一个功能,选择框下移,否则回到第一个
         if (currentFunction == FunctionKind.magnet)                                                                              //如果是最后一种功能
         {
             currentFunction = FunctionKind.explode;                                                                              //回到第一种功能
         }
         else
         {
             currentFunction++;//选择下一种功能
         }
     }
 }
Example #4
0
        internal ScriptFunctionObject GeneratorFunctionCreate(FunctionKind kind, [NotNull] IReadOnlyList <ExpressionNode> parameters, [NotNull] BaseNode body, [NotNull] LexicalEnvironment scope, bool strict)
        {
            //https://tc39.github.io/ecma262/#sec-generatorfunctioncreate

            var function = FunctionAllocate(Realm.Generator, strict, FunctionKind.Generator);

            return(FunctionInitialise(function, kind, parameters, body, scope));
        }
Example #5
0
        // VIS subscript(parms) -> type {
        //    get {
        //    }
        //    set { // newValue:type is implicit
        //    }
        // }
        // get is mandatory, set is optional

        public SLSubscript(Visibility vis, FunctionKind funcKind, SLType type,
                           SLParameterList parms, SLCodeBlock getter, SLCodeBlock setter)
        {
            Visibility = vis;
            Type       = Exceptions.ThrowOnNull(type, nameof(type));
            Parameters = Exceptions.ThrowOnNull(parms, nameof(parms));
            GetterBody = Exceptions.ThrowOnNull(getter, nameof(getter));
            SetterBody = setter;             // can be null

            List <string> elems = new List <string> ();

            if (vis != Visibility.None)
            {
                elems.Add(SLFunc.ToVisibilityString(vis) + " ");
            }
            if ((funcKind & FunctionKind.Final) != 0)
            {
                elems.Add("final ");
            }
            if ((funcKind & FunctionKind.Override) != 0)
            {
                elems.Add("override ");
            }
            if ((funcKind & FunctionKind.Required) != 0)
            {
                elems.Add("required ");
            }
            if ((funcKind & FunctionKind.Static) != 0)
            {
                elems.Add("static ");
            }
            if ((funcKind & FunctionKind.Class) != 0)
            {
                elems.Add("class ");
            }
            elems.Add("subscript ");

            AddRange(elems.Select((el, i) => i == 0 ? (ICodeElement) new SimpleLineElement(el, false, true, true) : new SimpleElememt(el)));
            Add(Parameters);
            Add(SimpleElememt.Spacer);
            Add(new SimpleElememt("->"));
            Add(SimpleElememt.Spacer);
            Add(Type);
            SLCodeBlock block = new SLCodeBlock(null);

            block.Add(new SimpleElememt("get"));
            block.Add(SimpleElememt.Spacer);
            block.Add(GetterBody);
            if (SetterBody != null)
            {
                block.Add(new SimpleElememt("set"));
                block.Add(SimpleElememt.Spacer);
                block.Add(SetterBody);
            }
            Add(block);
        }
Example #6
0
        internal ScriptFunctionObject FunctionCreate(FunctionKind kind, [NotNull] IReadOnlyList <ExpressionNode> parameters, [NotNull] BaseNode body, [NotNull] LexicalEnvironment scope, bool strict, ScriptObject prototype = null)
        {
            if (prototype == null)
            {
                prototype = RunningExecutionContext.Realm.FunctionPrototype;
            }

            var function = FunctionAllocate(prototype, strict, kind == FunctionKind.Normal ? FunctionKind.Normal : FunctionKind.NonConstructor);

            return(FunctionInitialise(function, kind, parameters, body, scope));
        }
Example #7
0
        private static double CalculateFunction(FunctionKind functionKind, double first, double second)
        {
            switch (functionKind)
            {
            case FunctionKind.Increase:
                return(first + second);

            case FunctionKind.Decrease:
                return(first - second);

            default:
                throw new ArgumentOutOfRangeException(nameof(functionKind));
            }
        }
Example #8
0
        public SLFunc(Visibility vis, FunctionKind funcKind, SLType type, SLIdentifier name, SLParameterList parms, SLCodeBlock body, bool isOptional = false)
        {
            GenericParams = new SLGenericTypeDeclarationCollection();
            Visibility    = vis;
            ReturnType    = type;
            bool isConstructor = (funcKind & FunctionKind.Constructor) != 0;

            Name          = isConstructor ? new SLIdentifier(isOptional ? "init?" : "init") : Exceptions.ThrowOnNull(name, nameof(name));
            Parameters    = parms ?? new SLParameterList();
            Body          = Exceptions.ThrowOnNull(body, nameof(body));
            FuncKind      = funcKind;
            IsConstructor = isConstructor;
            IsOptional    = isOptional;
        }
Example #9
0
        private static double ChannelOperation(FunctionKind functionKind, double channel, double amount, ColorFunctionUnits units)
        {
            switch (units)
            {
            case ColorFunctionUnits.Absolute:
                return(CalculateFunction(functionKind, channel, amount));

            case ColorFunctionUnits.Relative:
                return(CalculateFunction(functionKind, channel, channel * amount));

            case ColorFunctionUnits.Percentage:
                return(CalculateFunction(functionKind, channel, channel * amount / 100.0));

            default:
                throw new ArgumentOutOfRangeException(nameof(units));
            }
        }
Example #10
0
        public Signature(
            string name,
            FunctionKind kind,
            IEnumerable <TypeVariableConstraint> typeVariableConstraints,
            IEnumerable <LongVariableConstraint> longVariableConstraints,
            TypeSignature returnType,
            IEnumerable <TypeSignature> argumentTypes,
            bool variableArity)
        {
            if (String.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }

            this.Name = name;
            this.Kind = kind;
            this.TypeVariableConstraints = typeVariableConstraints;
            this.LongVariableConstraints = longVariableConstraints;
            this.ReturnType    = returnType;
            this.ArgumentTypes = argumentTypes;
            this.VariableArity = variableArity;
        }
        public static Argument GenerateArgument(this Generator generator, FunctionKind functionKind, Cursor functionCursor, uint argumentIndex)
        {
            var functionType = functionCursor.GetTypeInfo();
            var paramCursor  = functionCursor.GetArgument(argumentIndex);
            var type         = functionType.GetArgType(argumentIndex);

            var nativeName = paramCursor.GetSpelling();

            if (string.IsNullOrEmpty(nativeName))
            {
                nativeName = "param" + argumentIndex;
            }

            var name = NameConversions.ToClrName(nativeName, NameConversion.Parameter);

            Argument argument = new Argument();

            argument.Name       = name;
            argument.NativeName = nativeName;
            argument.Type       = type.ToClrType(functionKind);
            return(argument);
        }
Example #12
0
        private Stmt.Function Function(FunctionKind kind)
        {
            // If method name is preceded with "class", it can be called as a static method/getter.
            bool isStaticMethod = (kind == FunctionKind.METHOD && Match(CLASS));

            Token name = Consume(IDENTIFIER, $"Expect {FunctionKindNames[kind]} name.");

            // try to match a getter.
            if (kind == FunctionKind.METHOD && Match(LEFT_BRACE))
            {
                kind = FunctionKind.GETTER;
                List <Stmt> getterBody = Block();
                return(new Stmt.Function(name, new List <Token>(), getterBody, isStaticMethod, isGetter: true));
            }

            Consume(LEFT_PAREN, $"Expect '(' after {FunctionKindNames[kind]} name.");

            var parameters = new List <Token>();

            if (!IsCurrentTokenType(RIGHT_PAREN))
            {
                do
                {
                    if (parameters.Count >= 8)
                    {
                        Error(Peek(), "Cannot have more than 8 parameters.");
                    }
                    parameters.Add(Consume(IDENTIFIER, "Expect parameter name."));
                } while (Match(COMMA));
            }

            Consume(RIGHT_PAREN, "Expect ')' after parameters.");
            Consume(LEFT_BRACE, $"Expect '{{' before {FunctionKindNames[kind]} body.");
            List <Stmt> body = Block();

            return(new Stmt.Function(name, parameters, body, isStaticMethod, isGetter: false));
        }
Example #13
0
        public static FunctionObject FunctionAllocate(IValue prototype, bool strict, FunctionKind functionKind)
        {
            if (!(prototype is Object))
            {
                throw new InvalidOperationException("FunctionObject.FunctionAllocate: non-object prototype is not allowed.");
            }
            bool needsConstruct = functionKind == FunctionKind.Normal;

            if (functionKind == FunctionKind.NonConstructor)
            {
                functionKind = FunctionKind.Normal;
            }
            var F = new FunctionObject();

            if (needsConstruct)
            {
                F.ConstructorKind = ConstructorKind.Base;
            }
            F.Strict       = strict;
            F.FunctionKind = functionKind;
            F.SetPrototypeOf(prototype);
            F.Realm = Interpreter.Instance().RunningExecutionContext().Realm;
            return(F);
        }
Example #14
0
 protected Function(FunctionKind kind, int address, AstBody body)
 {
     Kind    = kind;
     Address = address;
     Body    = body;
 }
        /// <summary>
        /// 发送一个信息请求,一次性返回服务器回复内容
        /// 内容均为UTF-8编码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="functionKind">请求种类</param>
        /// <param name="addition1">字符串1,不需要写入空串</param>
        /// <param name="addition2">字符串2,不需要写入空串</param>
        /// <param name="bitmap"></param>
        /// <returns>服务器返回的结果</returns>
        public static FunctionWords SendNewsAndReceiveAnswer(this object sender, FunctionKind functionKind = FunctionKind.none, string addition1 = "", string addition2 = "", Bitmap bitmap = null)
        {
            //连接服务器
            IPAddress iPAddress    = IPAddress.Parse(serverIp);
            Socket    clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                clientSocket.Connect(new IPEndPoint(iPAddress, serverPort));//连接服务器
            }
            catch (Exception ex)
            {
                MessageBox.Show("临时请求发送失败,异常信息:\n" + ex.Message);
                clientSocket.Close();
                return(null);
            }

            //确认发送消息内容
            byte[] requestMessage = null;
            switch (functionKind)
            {
            case FunctionKind.SeekForImage:                     //开始+账号+结尾
                if (!addition1.EndsWith(".com"))
                {
                    Console.WriteLine("发送信息格式错误:1");
                    clientSocket.Close();
                    return(null);
                }
                requestMessage = MessageProtocol.AddBytes(MessageProtocol.GetStartBytes(functionKind), MessageProtocol.GetTxtBytes(addition1), MessageProtocol.GetEndBytes());
                break;

            case FunctionKind.VerifyAccount:                    //开始+账户+密码+结尾
                if (!addition1.EndsWith(".com") || addition2 == "")
                {
                    Console.WriteLine("发送信息格式错误:2");
                    clientSocket.Close();
                    return(null);
                }
                requestMessage = MessageProtocol.AddBytes(MessageProtocol.GetStartBytes(functionKind), MessageProtocol.GetTxtBytes(addition1), MessageProtocol.GetTxtBytes(addition2), MessageProtocol.GetEndBytes());
                break;

            case FunctionKind.SeekForUserName:                  //开始+账号+结尾
                requestMessage = MessageProtocol.AddBytes(MessageProtocol.GetStartBytes(functionKind), MessageProtocol.GetTxtBytes(addition1), MessageProtocol.GetEndBytes());
                break;

            case FunctionKind.SeekForNewGroupAccount:           //开始+结尾
                requestMessage = MessageProtocol.AddBytes(MessageProtocol.GetStartBytes(functionKind), MessageProtocol.GetEndBytes());
                break;

            case FunctionKind.QueryMemberOfGroup:               //开始+群号+结尾
                if (addition1.EndsWith(".com"))
                {
                    Console.WriteLine("发送信息格式错误:4");
                    clientSocket.Close();
                    return(null);
                }
                requestMessage = MessageProtocol.AddBytes(MessageProtocol.GetStartBytes(functionKind), MessageProtocol.GetTxtBytes(addition1), MessageProtocol.GetEndBytes());
                break;

            default:
                Console.WriteLine("发送信息格式错误:5");
                clientSocket.Close();
                return(null);
            }

            //确定发送消息不为空
            if (requestMessage == null)
            {
                Console.WriteLine("发送信息格式错误:6");
                clientSocket.Close();
                return(null);
            }
            //发送请求
            clientSocket.Send(requestMessage, requestMessage.Length, SocketFlags.None);

            //开始接收返回值
            Byte[]        realDataReceived = new Byte[0];
            FunctionWords functionWords    = new FunctionWords();

            try
            {
                //开始读取,遇到结束标识跳出
                while (true)
                {
                    //确保头部四字节数据完整
                    while (realDataReceived.Length < 4)
                    {
                        Byte[] RecvArray        = new Byte[bufferSize];            //用于存放接收信息
                        int    dataLengthInFact = clientSocket.Receive(RecvArray); //接收信息
                        if (dataLengthInFact <= 0)                                 //服务器主动断开连接
                        {
                            errorTimes++;
                            if (errorTimes > 3)
                            {
                                MessageBox.Show("远程服务器主动退出,立即中断操作。错误:7");
                                return(null);
                            }
                        }
                        else
                        {
                            errorTimes = 0;
                        }
                        realDataReceived = MessageProtocol.AddBytes(realDataReceived, RecvArray.Take(dataLengthInFact).ToArray());
                    }
                    BlockInformation blockInformation = realDataReceived.ReadBlockInformation(0);

                    //确保尾部数据完整
                    while (realDataReceived.Length < blockInformation.lengthOfAll)
                    {
                        Byte[] RecvArray        = new Byte[bufferSize];            //用于存放接收信息
                        int    dataLengthInFact = clientSocket.Receive(RecvArray); //接收信息
                        realDataReceived = MessageProtocol.AddBytes(realDataReceived, RecvArray.Take(dataLengthInFact).ToArray());
                    }

                    switch (blockInformation.blockKind)
                    {
                    case BlockKind.Start:
                        functionWords.functionKind = blockInformation.functionKind;
                        break;

                    case BlockKind.Txt:     //读取字符串
                        functionWords.stringList.Add(realDataReceived.ToTxt(4, blockInformation.LengthOfValue));
                        break;

                    case BlockKind.Image:
                        functionWords.bitmapList.Add(realDataReceived.ToBitmap(4, blockInformation.LengthOfValue));
                        break;

                    case BlockKind.File:     //预留接口
                        Console.WriteLine("功能尚未开放,错误:7");
                        clientSocket.Close();
                        return(null);

                    case BlockKind.End:     //读取到块结尾,说明一个功能语句读取完毕
                        goto EndBlock;
                    }
                    realDataReceived = realDataReceived.Skip(blockInformation.lengthOfAll).ToArray();   //去除字节数组中已经读过的部分
                }
                EndBlock :;
            }
            catch (Exception ex)
            {
                Console.WriteLine("连接错误,异常信息:8" + ex.Message);
                return(null);
            }

            if (functionKind != functionWords.functionKind)
            {
                Console.WriteLine("服务器返回了错误的答复:9");
                clientSocket.Close();
                return(null);
            }

            return(functionWords);
        }
Example #16
0
        /// <summary>
        /// 转化为可传输的开始字节流
        /// </summary>
        /// <param name="functionKind"></param>
        /// <returns></returns>
        public static Byte[] GetStartBytes(FunctionKind functionKind)
        {
            int numberHeader = ((int)functionKind) * 10 + (int)BlockKind.Start;

            return(BitConverter.GetBytes(numberHeader));
        }
Example #17
0
 /// <summary>
 /// 转化为可传输的开始字节流
 /// 拓展方法
 /// </summary>
 /// <param name="functionKind"></param>
 /// <returns></returns>
 public static Byte[] ToStartBytes(this FunctionKind functionKind)
 {
     return(GetStartBytes(functionKind));
 }
Example #18
0
        internal ScriptFunctionObject FunctionInitialise([NotNull] ScriptFunctionObject function, FunctionKind kind, [NotNull] IReadOnlyList <ExpressionNode> parameters, [NotNull] BaseNode body, [NotNull] LexicalEnvironment scope)
        {
            //https://tc39.github.io/ecma262/#sec-functioninitialize
            Debug.Assert(function.IsExtensible && function.GetOwnProperty("length") == null);
            var length = ExpectedArgumentCount(parameters);

            DefinePropertyOrThrow(function, "length", new PropertyDescriptor(length, false, false, true));

            var strict = function.Strict;

            function.Environment      = scope;
            function.FormalParameters = parameters;
            function.ECMAScriptCode   = new FunctionNode(body);
            function.ScriptOrModule   = GetActiveScriptOrModule();
            if (kind == FunctionKind.Arrow)
            {
                function.ThisMode = ThisMode.Lexical;
            }
            else if (strict)
            {
                function.ThisMode = ThisMode.Strict;
            }
            else
            {
                function.ThisMode = ThisMode.Global;
            }
            return(function);
        }
Example #19
0
        internal static ScriptFunctionObject FunctionAllocate([NotNull] ScriptObject functionPrototype, bool strict, FunctionKind functionKind)
        {
            //https://tc39.github.io/ecma262/#sec-functionallocate
            Debug.Assert(functionPrototype != null);
            var needsConstruct = functionKind == FunctionKind.Normal;

            if (functionKind == FunctionKind.NonConstructor)
            {
                functionKind = FunctionKind.Normal;
            }

            return(new ScriptFunctionObject(functionPrototype.Realm, functionPrototype, true, functionKind, needsConstruct ? ConstructorKind.Base : ConstructorKind.None, strict));
        }
        private Completion CreateDynamicFunction(Object?newTarget, FunctionKind kind, IReadOnlyList <IValue> arguments)
        {
            if (Interpreter.Instance().ExecutionContextStackSize() < 2)
            {
                throw new InvalidOperationException("Spec 19.2.1.1.1 step 1");
            }
            var callerContext = Interpreter.Instance().SecondExecutionContext();
            var callerRealm   = callerContext.Realm;
            var calleeRealm   = Interpreter.Instance().CurrentRealm();

            //TODO HostEnsureCanCompileStrings
            if (newTarget == null)
            {
                newTarget = this;
            }
            Func <Parser.Parser, AST.FunctionStatementList> goal;
            Func <Intrinsics, Object> fallbackProto;

            switch (kind)
            {
            case FunctionKind.Normal:
                goal          = (p) => p.ParseFunctionBody();
                fallbackProto = i => i.FunctionPrototype;
                break;

            default:
                throw new NotImplementedException("Async and/or generators");
            }
            var    argCount = arguments.Count;
            var    P        = "";
            string bodyText;

            if (argCount == 0)
            {
                bodyText = "";
            }
            else if (argCount == 1)
            {
                var bodyComp = arguments[0].ToJsString();
                if (bodyComp.IsAbrupt())
                {
                    return(bodyComp);
                }
                bodyText = (bodyComp.value as StringValue) !.@string;
            }
            else
            {
                var firstArg = arguments[0];
                var pComp    = firstArg.ToJsString();
                if (pComp.IsAbrupt())
                {
                    return(pComp);
                }
                P = (pComp.value as StringValue) !.@string;
                int k = 1;
                for (; k < argCount - 1; k++)
                {
                    var nextArg           = arguments[k];
                    var nextArgStringComp = nextArg.ToJsString();
                    if (nextArgStringComp.IsAbrupt())
                    {
                        return(nextArgStringComp);
                    }
                    var nextArgString = (nextArgStringComp.value as StringValue) !.@string;
                    P += "," + nextArgString;
                }
                var bodyComp = arguments[k].ToJsString();
                if (bodyComp.IsAbrupt())
                {
                    return(bodyComp);
                }
                bodyText = (bodyComp.value as StringValue) !.@string;
            }
            AST.FormalParameters?parameters = new AST.FormalParameters();
            try
            {
                if (!string.IsNullOrEmpty(P))
                {
                    parameters = new Parser.Parser(P).ParseFormalParameters();
                }
                if (parameters == null)
                {
                    throw new Parser.ParseFailureException($"parameters {P} could not be parsed.");
                }
            }
            catch (Parser.ParseFailureException e)
            {
                return(Completion.ThrowSyntaxError($"Failed to parse parameters \"{P}\".\n{e.Message}"));
            }
            AST.FunctionStatementList body;
            try
            {
                body = goal(new Parser.Parser(bodyText));
            }
            catch (Parser.ParseFailureException e)
            {
                return(Completion.ThrowSyntaxError($"Failed to parse body \"{bodyText}\".\n{e.Message}"));
            }
            //TODO detect strict mode: ContainsUseStrict
            bool strict = body.IsStrictMode;

            if (!parameters.IsSimpleParameterList() && strict)
            {
                return(Completion.ThrowSyntaxError($"parameters must be simple in strict mode. \"{P}\""));
            }
            //TODO implement tree walking for checking if parameters or body contains a SuperCall or SuperProperty
            //TODO generator yield, async await errors
            var protoComp = Utils.GetPrototypeFromConstructor(newTarget, fallbackProto);

            if (protoComp.IsAbrupt())
            {
                return(protoComp);
            }
            var proto  = protoComp.value;
            var F      = FunctionObject.FunctionAllocate(proto !, strict, kind);
            var realmF = F.Realm;
            var scope  = realmF.GlobalEnv;

            FunctionObject.FunctionInitialize(F, FunctionCreateKind.Normal, parameters, body, scope);
            //TODO generator, async generator
            if (kind == FunctionKind.Normal)
            {
                F.MakeConstructor();
            }
            F.SetFunctionName("anonymous");
            return(Completion.NormalCompletion(F));
        }
Example #21
0
    public static FunctionKind currentFunction; //当前选择的砖块功能

    private void Start()                        //初始化
    {
        currentFunction = FunctionKind.explode; //默认从爆炸功能开始
    }
Example #22
0
 internal static ParseDelegate ParseFunction(FunctionKind kind)
 {
     return(new ParseDelegate((ParseInfo info, ref int index) => Parse(info, ref index, kind)));
 }
Example #23
0
        internal static ScriptValue CreateDynamicFunction([NotNull] ScriptObject constructor, ScriptObject newTarget, FunctionKind kind, [NotNull] ScriptArguments args)
        {
            //https://tc39.github.io/ecma262/#sec-createdynamicfunction

            var callerContext = args.Agent.RunningExecutionContext.Realm;
            var calleeRealm   = constructor.Realm;

            args.Agent.HostEnsureCanCompileStrings(callerContext, calleeRealm);

            if (newTarget == null)
            {
                newTarget = constructor;
            }

            string       startFunction;
            ScriptObject fallbackPrototype;

            switch (kind)
            {
            case FunctionKind.Normal:
                startFunction     = "function anonymous(";
                fallbackPrototype = newTarget.Realm.FunctionPrototype;
                break;

            case FunctionKind.Generator:
                startFunction     = "function *anonymous(";
                fallbackPrototype = newTarget.Realm.Generator;
                break;

            case FunctionKind.Async:
                startFunction     = "async function anonymous(";
                fallbackPrototype = newTarget.Realm.AsyncFunctionPrototype;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(kind), kind, null);
            }

            var    parameters = "";
            string bodyText;

            if (args.Count == 0)
            {
                bodyText = "";
            }
            else if (args.Count == 1)
            {
                bodyText = args.Agent.ToString(args[0]);
            }
            else
            {
                for (var k = 0; k < args.Count - 1; k++)
                {
                    if (k > 0)
                    {
                        parameters += ",";
                    }

                    parameters += args.Agent.ToString(args[k]);
                }

                bodyText = args.Agent.ToString(args[args.Count - 1]);
            }

            startFunction += parameters + "){" + bodyText + "}";
            var script       = (NodeScript)args.Agent.ParseScript(startFunction, null, false, false);
            var functionNode = (FunctionDeclarationNode)script.Node.Body[0];

            //TODO
            //Let strict be ContainsUseStrict of body.
            //If any static semantics errors are detected for parameters or body, throw a SyntaxError or a ReferenceError exception, depending on the type of the error. If strict is true, the Early Error rules for UniqueFormalParameters:FormalParameters are applied. Parsing and early error detection may be interweaved in an implementation-dependent manner.
            //If strict is true and IsSimpleParameterList of parameters is false, throw a SyntaxError exception.
            //If any element of the BoundNames of parameters also occurs in the LexicallyDeclaredNames of body, throw a SyntaxError exception.
            //If body Contains SuperCall is true, throw a SyntaxError exception.
            //If parameters Contains SuperCall is true, throw a SyntaxError exception.
            //If body Contains SuperProperty is true, throw a SyntaxError exception.
            //If parameters Contains SuperProperty is true, throw a SyntaxError exception.
            //If kind is "generator", then
            //    If parameters Contains YieldExpression is true, throw a SyntaxError exception.
            //If kind is "async", then
            //    If parameters Contains AwaitExpression is true, throw a SyntaxError exception.
            //If strict is true, then
            //    If BoundNames of parameters contains any duplicate elements, throw a SyntaxError exception.

            var prototype = Agent.GetPrototypeFromConstructor(newTarget, fallbackPrototype);
            var function  = Agent.FunctionAllocate(prototype, script.Strict, kind);

            args.Agent.FunctionInitialise(function, FunctionKind.Normal, functionNode.Parameters, functionNode.Body, function.Realm.GlobalEnvironment);

            if (kind == FunctionKind.Generator)
            {
                var generatorPrototype = args.Agent.ObjectCreate(args.Agent.Realm.GeneratorPrototype);
                args.Agent.DefinePropertyOrThrow(function, "prototype", new PropertyDescriptor(generatorPrototype, true, false, false));
            }
            else if (kind == FunctionKind.Normal)
            {
                args.Agent.MakeConstructor(function);
            }

            args.Agent.SetFunctionName(function, "anonymous");
            return(function);
        }
Example #24
0
 private GlulxFunction(FunctionKind kind, int address, AstBody body)
     : base(kind, address, body)
 {
 }
Example #25
0
        internal static Expression Parse(ParseInfo state, ref int index, FunctionKind kind)
        {
            string code     = state.Code;
            int    position = index;

            switch (kind)
            {
            case FunctionKind.AsyncAnonymousFunction:
            case FunctionKind.AnonymousFunction:
            case FunctionKind.AnonymousGenerator:
            {
                break;
            }

            case FunctionKind.Function:
            {
                if (!Parser.Validate(code, "function", ref position))
                {
                    return(null);
                }

                if (code[position] == '*')
                {
                    kind = FunctionKind.Generator;
                    position++;
                }
                else if ((code[position] != '(') && (!Tools.IsWhiteSpace(code[position])))
                {
                    return(null);
                }

                break;
            }

            case FunctionKind.Getter:
            {
                if (!Parser.Validate(code, "get ", ref position))
                {
                    return(null);
                }

                break;
            }

            case FunctionKind.Setter:
            {
                if (!Parser.Validate(code, "set ", ref position))
                {
                    return(null);
                }

                break;
            }

            case FunctionKind.MethodGenerator:
            case FunctionKind.Method:
            {
                if (Parser.Validate(code, "async", ref position))
                {
                    kind = FunctionKind.AsyncMethod;
                }

                if (code[position] == '*')
                {
                    kind = FunctionKind.MethodGenerator;
                    position++;
                }
                else if (kind == FunctionKind.MethodGenerator)
                {
                    throw new ArgumentException("mode");
                }

                break;
            }

            case FunctionKind.AsyncArrow:
            {
                if (!Parser.Validate(code, "async", ref position))
                {
                    return(null);
                }

                break;
            }

            case FunctionKind.Arrow:
            {
                break;
            }

            case FunctionKind.AsyncFunction:
            {
                if (!Parser.Validate(code, "async", ref position))
                {
                    return(null);
                }

                Tools.SkipSpaces(code, ref position);

                if (!Parser.Validate(code, "function", ref position))
                {
                    return(null);
                }

                break;
            }

            default:
                throw new NotImplementedException(kind.ToString());
            }

            Tools.SkipSpaces(state.Code, ref position);

            var       parameters                = new List <ParameterDescriptor>();
            CodeBlock body                      = null;
            string    name                      = null;
            bool      arrowWithSinglePrm        = false;
            int       nameStartPos              = 0;
            bool      containsDestructuringPrms = false;

            if (kind != FunctionKind.Arrow)
            {
                if (code[position] != '(')
                {
                    nameStartPos = position;
                    if (Parser.ValidateName(code, ref position, false, true, state.strict))
                    {
                        name = Tools.Unescape(code.Substring(nameStartPos, position - nameStartPos), state.strict);
                    }
                    else if ((kind == FunctionKind.Getter || kind == FunctionKind.Setter) && Parser.ValidateString(code, ref position, false))
                    {
                        name = Tools.Unescape(code.Substring(nameStartPos + 1, position - nameStartPos - 2), state.strict);
                    }
                    else if ((kind == FunctionKind.Getter || kind == FunctionKind.Setter) && Parser.ValidateNumber(code, ref position))
                    {
                        name = Tools.Unescape(code.Substring(nameStartPos, position - nameStartPos), state.strict);
                    }
                    else
                    {
                        ExceptionHelper.ThrowSyntaxError("Invalid function name", code, nameStartPos, position - nameStartPos);
                    }

                    Tools.SkipSpaces(code, ref position);

                    if (code[position] != '(')
                    {
                        ExceptionHelper.ThrowUnknownToken(code, position);
                    }
                }
                else if (kind == FunctionKind.Getter || kind == FunctionKind.Setter)
                {
                    ExceptionHelper.ThrowSyntaxError("Getter and Setter must have name", code, index);
                }
                else if (kind == FunctionKind.Method || kind == FunctionKind.MethodGenerator || kind == FunctionKind.AsyncMethod)
                {
                    ExceptionHelper.ThrowSyntaxError("Method must has name", code, index);
                }

                position++;
            }
            else if (code[position] != '(')
            {
                arrowWithSinglePrm = true;
            }
            else
            {
                position++;
            }

            Tools.SkipSpaces(code, ref position);

            if (code[position] == ',')
            {
                ExceptionHelper.ThrowSyntaxError(Strings.UnexpectedToken, code, position);
            }

            while (code[position] != ')')
            {
                if (parameters.Count == 255 || (kind == FunctionKind.Setter && parameters.Count == 1) || kind == FunctionKind.Getter)
                {
                    ExceptionHelper.ThrowSyntaxError(string.Format(Strings.TooManyArgumentsForFunction, name), code, index);
                }

                bool rest = Parser.Validate(code, "...", ref position);

                Expression destructor = null;
                int        n          = position;
                if (!Parser.ValidateName(code, ref position, state.strict))
                {
                    if (code[position] == '{')
                    {
                        destructor = (Expression)ObjectDefinition.Parse(state, ref position);
                    }
                    else if (code[position] == '[')
                    {
                        destructor = (Expression)ArrayDefinition.Parse(state, ref position);
                    }

                    if (destructor == null)
                    {
                        ExceptionHelper.ThrowUnknownToken(code, nameStartPos);
                    }

                    containsDestructuringPrms = true;
                }

                var pname     = Tools.Unescape(code.Substring(n, position - n), state.strict);
                var reference = new ParameterReference(pname, rest, state.lexicalScopeLevel + 1)
                {
                    Position = n,
                    Length   = position - n
                };
                var desc = reference.Descriptor as ParameterDescriptor;

                if (destructor != null)
                {
                    desc.Destructor = new ObjectDesctructor(destructor);
                }

                parameters.Add(desc);

                Tools.SkipSpaces(state.Code, ref position);
                if (arrowWithSinglePrm)
                {
                    position--;
                    break;
                }

                if (code[position] == '=')
                {
                    if (rest)
                    {
                        ExceptionHelper.ThrowSyntaxError("Rest parameters can not have an initializer", code, position);
                    }
                    do
                    {
                        position++;
                    }while (Tools.IsWhiteSpace(code[position]));
                    desc.initializer = ExpressionTree.Parse(state, ref position, false, false) as Expression;
                }

                if (code[position] == ',')
                {
                    if (rest)
                    {
                        ExceptionHelper.ThrowSyntaxError("Rest parameters must be the last in parameters list", code, position);
                    }
                    do
                    {
                        position++;
                    }while (Tools.IsWhiteSpace(code[position]));
                }
            }

            if (kind == FunctionKind.Setter)
            {
                if (parameters.Count != 1)
                {
                    ExceptionHelper.ThrowSyntaxError("Setter must has only one argument", code, index);
                }
            }

            position++;
            Tools.SkipSpaces(code, ref position);

            if (kind == FunctionKind.Arrow || kind == FunctionKind.AsyncArrow)
            {
                if (!Parser.Validate(code, "=>", ref position))
                {
                    ExceptionHelper.ThrowSyntaxError("Expected \"=>\"", code, position);
                }
                Tools.SkipSpaces(code, ref position);
            }

            if (code[position] != '{')
            {
                var oldFunctionScopeLevel = state.functionScopeLevel;
                state.functionScopeLevel = ++state.lexicalScopeLevel;

                try
                {
                    if (kind == FunctionKind.Arrow || kind == FunctionKind.AsyncArrow)
                    {
                        body = new CodeBlock(new CodeNode[]
                        {
                            new Return(ExpressionTree.Parse(state, ref position, processComma: false) as Expression)
                        })
                        {
                            _variables = new VariableDescriptor[0]
                        };

                        body.Position = body._lines[0].Position;
                        body.Length   = body._lines[0].Length;
                    }
                    else
                    {
                        ExceptionHelper.ThrowUnknownToken(code, position);
                    }
                }
                finally
                {
                    state.functionScopeLevel = oldFunctionScopeLevel;
                    state.lexicalScopeLevel--;
                }
            }
            else
            {
                var oldCodeContext = state.CodeContext;
                state.CodeContext &= ~(CodeContext.InExpression | CodeContext.Conditional | CodeContext.InEval);
                if (kind == FunctionKind.Generator || kind == FunctionKind.MethodGenerator || kind == FunctionKind.AnonymousGenerator)
                {
                    state.CodeContext |= CodeContext.InGenerator;
                }
                else if (kind == FunctionKind.AsyncFunction || kind == FunctionKind.AsyncMethod || kind == FunctionKind.AsyncAnonymousFunction || kind == FunctionKind.AsyncArrow)
                {
                    state.CodeContext |= CodeContext.InAsync;
                }
                state.CodeContext |= CodeContext.InFunction;

                var labels = state.Labels;
                state.Labels = new List <string>();
                state.AllowReturn++;
                try
                {
                    state.AllowBreak.Push(false);
                    state.AllowContinue.Push(false);
                    state.AllowDirectives = true;
                    body = CodeBlock.Parse(state, ref position) as CodeBlock;
                    if (containsDestructuringPrms)
                    {
                        var destructuringTargets = new List <VariableDescriptor>();
                        var assignments          = new List <Expression>();
                        for (var i = 0; i < parameters.Count; i++)
                        {
                            if (parameters[i].Destructor != null)
                            {
                                var targets = parameters[i].Destructor.GetTargetVariables();
                                for (var j = 0; j < targets.Count; j++)
                                {
                                    destructuringTargets.Add(new VariableDescriptor(targets[j].Name, state.functionScopeLevel));
                                }

                                assignments.Add(new Assignment(parameters[i].Destructor, parameters[i].references[0]));
                            }
                        }

                        var newLines = new CodeNode[body._lines.Length + 1];
                        System.Array.Copy(body._lines, 0, newLines, 1, body._lines.Length);
                        newLines[0] = new VariableDefinition(destructuringTargets.ToArray(), assignments.ToArray(), VariableKind.AutoGeneratedParameters);
                        body._lines = newLines;
                    }
                }
                finally
                {
                    state.CodeContext = oldCodeContext;
                    state.AllowBreak.Pop();
                    state.AllowContinue.Pop();
                    state.AllowDirectives = false;
                    state.Labels          = labels;
                    state.AllowReturn--;
                }

                if (kind == FunctionKind.Function && string.IsNullOrEmpty(name))
                {
                    kind = FunctionKind.AnonymousFunction;
                }
            }

            if (body._strict || (parameters.Count > 0 && parameters[parameters.Count - 1].IsRest) || kind == FunctionKind.Arrow)
            {
                for (var j = parameters.Count; j-- > 1;)
                {
                    for (var k = j; k-- > 0;)
                    {
                        if (parameters[j].Name == parameters[k].Name)
                        {
                            ExceptionHelper.ThrowSyntaxError("Duplicate names of function parameters not allowed in strict mode", code, index);
                        }
                    }
                }

                if (name == "arguments" || name == "eval")
                {
                    ExceptionHelper.ThrowSyntaxError("Functions name can not be \"arguments\" or \"eval\" in strict mode at", code, index);
                }

                for (int j = parameters.Count; j-- > 0;)
                {
                    if (parameters[j].Name == "arguments" || parameters[j].Name == "eval")
                    {
                        ExceptionHelper.ThrowSyntaxError("Parameters name cannot be \"arguments\" or \"eval\" in strict mode at", code, parameters[j].references[0].Position, parameters[j].references[0].Length);
                    }
                }
            }

            var func = new FunctionDefinition(name)
            {
                parameters = parameters.ToArray(),
                _body      = body,
                kind       = kind,
                Position   = index,
                Length     = position - index,
#if DEBUG
                trace = body.directives != null?body.directives.Contains("debug trace") : false
#endif
            };

            if (!string.IsNullOrEmpty(name))
            {
                func.Reference.ScopeLevel = state.lexicalScopeLevel;
                func.Reference.Position   = nameStartPos;
                func.Reference.Length     = name.Length;

                func.reference._descriptor.definitionScopeLevel = func.reference.ScopeLevel;
            }

            if (parameters.Count != 0)
            {
                var newVariablesCount = body._variables.Length + parameters.Count;

                for (var j = 0; j < body._variables.Length; j++)
                {
                    for (var k = 0; k < parameters.Count; k++)
                    {
                        if (body._variables[j].name == parameters[k].name)
                        {
                            newVariablesCount--;
                            break;
                        }
                    }
                }

                var newVariables = new VariableDescriptor[newVariablesCount];
                for (var j = 0; j < parameters.Count; j++)
                {
                    newVariables[j] = parameters[parameters.Count - j - 1]; // порядок определяет приоритет
                    for (var k = 0; k < body._variables.Length; k++)
                    {
                        if (body._variables[k] != null && body._variables[k].name == parameters[j].name)
                        {
                            if (body._variables[k].initializer != null)
                            {
                                newVariables[j] = body._variables[k];
                            }
                            else
                            {
                                body._variables[k].lexicalScope = false;
                            }
                            body._variables[k] = null;
                            break;
                        }
                    }
                }

                for (int j = 0, k = parameters.Count; j < body._variables.Length; j++)
                {
                    if (body._variables[j] != null)
                    {
                        newVariables[k++] = body._variables[j];
                    }
                }

                body._variables = newVariables;
            }

            if ((state.CodeContext & CodeContext.InExpression) == 0 && kind == FunctionKind.Function)
            // Позволяет делать вызов сразу при объявлении функции
            // (в таком случае функция не добавляется в контекст).
            // Если убрать проверку, то в тех сулчаях,
            // когда определение и вызов стоят внутри выражения,
            // будет выдано исключение, потому,
            // что тогда это уже не определение и вызов функции,
            // а часть выражения, которые не могут начинаться со слова "function".
            // За красивыми словами "может/не может" кроется другая хрень: если бы это было выражение,
            // то прямо тут надо было бы разбирать тот оператор, который стоит после определения функции,
            // что не разумно
            {
                var tindex = position;
                while (position < code.Length && Tools.IsWhiteSpace(code[position]) && !Tools.IsLineTerminator(code[position]))
                {
                    position++;
                }

                if (position < code.Length && code[position] == '(')
                {
                    var args = new List <Expression>();
                    position++;
                    for (; ;)
                    {
                        while (Tools.IsWhiteSpace(code[position]))
                        {
                            position++;
                        }
                        if (code[position] == ')')
                        {
                            break;
                        }
                        else if (code[position] == ',')
                        {
                            do
                            {
                                position++;
                            }while (Tools.IsWhiteSpace(code[position]));
                        }
                        args.Add(ExpressionTree.Parse(state, ref position, false, false));
                    }

                    position++;
                    index = position;
                    while (position < code.Length && Tools.IsWhiteSpace(code[position]))
                    {
                        position++;
                    }

                    if (position < code.Length && code[position] == ';')
                    {
                        ExceptionHelper.Throw((new SyntaxError("Expression can not start with word \"function\"")));
                    }

                    return(new Call(func, args.ToArray()));
                }
                else
                {
                    position = tindex;
                }
            }

            if ((state.CodeContext & CodeContext.InExpression) == 0 &&
                (kind != FunctionKind.Arrow || (state.CodeContext & CodeContext.InEval) == 0))
            {
                if (string.IsNullOrEmpty(name))
                {
                    ExceptionHelper.ThrowSyntaxError("Function must has name", state.Code, index);
                }

                state.Variables.Add(func.reference._descriptor);
            }

            index = position;
            return(func);
        }
Example #26
0
        public static string ToClrType(this TypeInfo type, FunctionKind functionKind = FunctionKind.Default)
        {
            if (type.Kind == TypeKind.Typedef && type.GetTypedefName() == "size_t")
            {
                return("UIntPtr");
            }

            if (type.Kind == TypeKind.Typedef && type.GetTypedefName() == "ssize_t")
            {
                return("IntPtr");
            }

            var canonical = type.GetCanonicalType();

            switch (canonical.Kind)
            {
            case TypeKind.Bool:
                return("bool");

            case TypeKind.UChar:
            case TypeKind.Char_U:
                return("byte");

            case TypeKind.SChar:
            case TypeKind.Char_S:
                return("sbyte");

            case TypeKind.UShort:
                return("ushort");

            case TypeKind.Short:
                return("short");

            case TypeKind.Float:
                return("float");

            case TypeKind.Double:
                return("double");

            case TypeKind.Int:
                return("int");

            case TypeKind.Enum:
                var enumName = type.GetTypeDeclaration().GetDisplayName();
                return(NameConversions.ToClrName(enumName, NameConversion.Type));

            case TypeKind.UInt:
                return("uint");

            case TypeKind.IncompleteArray:
                return("IntPtr");

            case TypeKind.Long:
                return("int");

            case TypeKind.ULong:
                return("uint");

            case TypeKind.LongLong:
                return("long");

            case TypeKind.ULongLong:
                return("ulong");

            case TypeKind.Void:
                return("void");

            case TypeKind.Pointer:
                // int LIBUSB_CALL libusb_init(libusb_context **ctx);
                // would map to Init(ref IntPtr),
                // whereas
                // void LIBUSB_CALL libusb_exit(libusb_context * ctx);
                // would map to Exit(IntPtr);
                var pointee = type.GetPointeeType();
                switch (pointee.Kind)
                {
                case TypeKind.Pointer:
                    // Double pointers are usually linked lists
                    var listType = pointee.GetPointeeType();

                    if (listType.Kind == TypeKind.Elaborated)
                    {
                        var pointee2Spelling = listType.GetNamedType().GetSpelling();
                        return($"{NameConversions.ToClrName(pointee2Spelling, NameConversion.Type)}**");
                    }
                    else
                    {
                        return("ref IntPtr");
                    }

                case TypeKind.Int:
                    return("ref int");

                case TypeKind.UChar:
                    return("byte*");

                case TypeKind.Typedef:
                    var typeDefName = pointee.GetTypedefName();

                    if (pointee.GetCanonicalType().Kind == TypeKind.Int)
                    {
                        return("ref int");
                    }
                    else if (typeDefName == "uint8_t")
                    {
                        return("byte*");
                    }
                    else if (functionKind == FunctionKind.Default)
                    {
                        return(NameConversions.ToClrName(pointee.GetTypedefName(), NameConversion.Type));
                    }
                    else
                    {
                        return("IntPtr");
                    }

                case TypeKind.Void:
                    return("IntPtr");

                case TypeKind.Elaborated:
                    var spelling = pointee.GetNamedType().GetSpelling();

                    if (spelling == "timeval")
                    {
                        return("ref UnixNativeTimeval");
                    }
                    else if (spelling == "libusb_context")
                    {
                        return("ref Context");
                    }
                    else
                    {
                        return($"{NameConversions.ToClrName(spelling, NameConversion.Type)}*");
                    }

                default:
                    return("IntPtr");
                }

            default:
                throw new NotSupportedException();
            }
        }