public virtual void CheckArgumentsOverload(IList <Function> @group, DFSM stateMachine) { var typeCheckStates = stateMachine.Q.Except(stateMachine.F).ToList(); var finalStates = stateMachine.F; // Create a set of unique parameter types. var uniqueTypes = @group.SelectMany(method => method.Parameters) .Select(p => p.Type).Distinct().ToList(); // Type check states. for (var i = 0; i < typeCheckStates.Count; i++) { NewLineIfNeeded(); if (i > 0) { Unindent(); WriteLine($"typecheck{i}:"); Indent(); } var state = typeCheckStates[i]; var transitions = stateMachine.Delta.Where(t => t.StartState == state).ToArray(); foreach (var transition in transitions) { NewLineIfNeeded(); var isInitialState = stateMachine.Q0.Contains(state); var paramIndex = isInitialState ? 0 : int.Parse(transition.StartState.Split(' ').Last().Split('_').Last()) + 1; var type = uniqueTypes[(int)transition.Symbol]; var condition = GenerateTypeCheckForParameter(paramIndex, type); WriteLine($"if ({condition})"); var nextState = typeCheckStates.Contains(transition.EndState) ? $"typecheck{typeCheckStates.FindIndex(s => s == transition.EndState)}" : $"overload{finalStates.FindIndex(s => s == transition.EndState)}"; WriteLineIndent($"goto {nextState};"); NewLine(); } WriteLine("goto error;"); NeedNewLine(); NeedNewLine(); } NewLineIfNeeded(); }
public virtual void GenerateOverloadCalls(IList <Function> @group, DFSM stateMachine) { // Final states. for (var i = 0; i < stateMachine.F.Count; i++) { NewLineIfNeeded(); var function = @group[i]; WriteLine($"// {function.Signature}"); Unindent(); WriteLine($"overload{i}:"); Indent(); WriteOpenBraceAndIndent(); { GenerateFunctionCall(function); } UnindentAndWriteCloseBrace(); NeedNewLine(); } }
private void CheckArgumentsOverload(IList <Function> @group, DFSM stateMachine) { var typeCheckStates = stateMachine.Q.Except(stateMachine.F).ToList(); var finalStates = stateMachine.F; // Create a set of unique parameter types. var uniqueTypes = @group.SelectMany(method => method.Parameters) .Select(p => p.Type).Distinct().ToList(); // Type check states. for (var i = 0; i < typeCheckStates.Count; i++) { NewLineIfNeeded(); if (i > 0) { Unindent(); WriteLine($"typecheck{i}:"); Indent(); } var state = typeCheckStates[i]; var transitions = stateMachine.Delta.Where(t => t.StartState == state).ToArray(); foreach (var transition in transitions) { NewLineIfNeeded(); var isInitialState = stateMachine.Q0.Contains(state); var paramIndex = isInitialState ? 0 : int.Parse(transition.StartState.Split(' ').Last().Split('_').Last()) + 1; var type = uniqueTypes[(int)transition.Symbol]; var typeChecker = new NAPITypeCheckGen(paramIndex); type.Visit(typeChecker); var condition = typeChecker.Generate(); if (string.IsNullOrWhiteSpace(condition)) { throw new NotSupportedException(); } WriteLine($"if ({condition})"); var nextState = typeCheckStates.Contains(transition.EndState) ? $"typecheck{typeCheckStates.FindIndex(s => s == transition.EndState)}" : $"overload{finalStates.FindIndex(s => s == transition.EndState)}"; WriteLineIndent($"goto {nextState};"); NewLine(); } WriteLine("goto error;"); NeedNewLine(); NeedNewLine(); } NewLineIfNeeded(); // Error state. Unindent(); WriteLine($"error:"); Indent(); WriteLine("status = napi_throw_type_error(env, nullptr, \"Unsupported argument type\");"); WriteLine("assert(status == napi_ok);"); NewLine(); WriteLine("return nullptr;"); NewLine(); }
public virtual void CheckArgumentsOverload(List <Function> @group, DFSM stateMachine) { int GetParamIndex(Transition transition, string state) { var isInitialState = stateMachine.Q0.Contains(state); var paramIndex = isInitialState ? 0 : int.Parse(transition.StartState.Split(' ').Last().Split('_').Last()) + 1; return(paramIndex); } var typeCheckStates = stateMachine.Q.Except(stateMachine.F).ToList(); var finalStates = stateMachine.F; // Create a set of unique parameter types. var uniqueTypes = @group.SelectMany(method => method.Parameters) .Select(p => p.Type).Distinct().ToList(); // Type check states. for (var i = 0; i < typeCheckStates.Count; i++) { NewLineIfNeeded(); if (i > 0) { Unindent(); WriteLine($"typecheck{i}:"); Indent(); } var state = typeCheckStates[i]; var transitions = stateMachine.Delta.Where(t => t.StartState == state).ToArray(); // Deal with default parameters. var currentParamIndex = GetParamIndex(transitions.First(), state); var defaultParams = @group.Where(f => f.Parameters.Count > currentParamIndex) .Select(f => f.Parameters[currentParamIndex]) .Where(p => p.HasDefaultValue).ToArray(); // Check for an ambiguous case of overload resolution and throw. This does prevents some technically // legal overloads from being generated, so in the future this can be updated to just throw // a runtime error in JS instead, which would allow the ambiguous overloads to be called when // resolved with all explicit arguments. if (defaultParams.Length > 1) { throw new Exception($"Found ambiguity between default parameter overloads for: " + $"{@group.First().QualifiedOriginalName}"); } if (defaultParams.Length == 1) { WriteLine($"if (argc == {currentParamIndex})"); var overload = defaultParams.First().Namespace as Function; var index = @group.FindIndex(f => f == overload); WriteLineIndent($"goto overload{index};"); NewLine(); } foreach (var transition in transitions) { NewLineIfNeeded(); var paramIndex = GetParamIndex(transition, state); var type = uniqueTypes[transition.Symbol]; var condition = GenerateTypeCheckForParameter(paramIndex, type); WriteLine($"if ({condition})"); var nextState = typeCheckStates.Contains(transition.EndState) ? $"typecheck{typeCheckStates.FindIndex(s => s == transition.EndState)}" : $"overload{finalStates.FindIndex(s => s == transition.EndState)}"; WriteLineIndent($"goto {nextState};"); NewLine(); } WriteLine("goto error;"); NeedNewLine(); NeedNewLine(); } NewLineIfNeeded(); }