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)); }
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; }
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++;//选择下一种功能 } } }
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)); }
// 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); }
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)); }
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)); } }
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; }
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)); } }
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); }
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)); }
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); }
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); }
/// <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)); }
/// <summary> /// 转化为可传输的开始字节流 /// 拓展方法 /// </summary> /// <param name="functionKind"></param> /// <returns></returns> public static Byte[] ToStartBytes(this FunctionKind functionKind) { return(GetStartBytes(functionKind)); }
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); }
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)); }
public static FunctionKind currentFunction; //当前选择的砖块功能 private void Start() //初始化 { currentFunction = FunctionKind.explode; //默认从爆炸功能开始 }
internal static ParseDelegate ParseFunction(FunctionKind kind) { return(new ParseDelegate((ParseInfo info, ref int index) => Parse(info, ref index, kind))); }
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); }
private GlulxFunction(FunctionKind kind, int address, AstBody body) : base(kind, address, body) { }
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); }
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(); } }