public override AbstractSyntaxTreeNode applyToPrimitiveMethodDeclaration(PrimitiveMethodDeclaration operand) { var className = operand.SpecifiesClassName ? symbolFrom(operand.ClassNameSymbol) : null; var methodSelector = symbolFrom(operand.SelectorSymbol); Context.setRootScope(); Context.MethodSelector = methodSelector; PrimitiveMethodDeclarationNode method = null; Delegate primitiveFunction = null; var primitiveSpec = operand.PrimitiveSpecification; var primitiveSpecSelector = symbolFrom(primitiveSpec.SelectorSymbol); var primType = primitiveTypeFor(primitiveSpecSelector.PrimitiveValue); if (primType == null) { Context.markAsUncompilable(); compiler.handlePrimitiveSpeficationError( "Unknown/unsupported primitive specification format: " + primitiveSpecSelector.ToString(), primitiveSpec.Span); method = Context.newPrimitiveFunctionMethodDeclarationNode(className, Context.MethodSelector, primitiveFunction); } else { MethodOperationType opType = (MethodOperationType)primType; long requiredArity = -1; switch (opType) { case MethodOperationType.Function: primitiveFunction = primitiveFunctionFor(primitiveSpec.Arguments); method = Context.newPrimitiveFunctionMethodDeclarationNode(className, methodSelector, primitiveFunction); if (primitiveFunction == null) { requiredArity = methodSelector.NumArgs; } else { var methodInfo = primitiveFunction.Method; // Primitive functions can't be private or otherwise inaccessible. requiredArity = methodInfo.GetParameters().Length - 1; // The initial parameter of a primitive function is always the receiver of the message. } break; case MethodOperationType.Convert: case MethodOperationType.GetField: case MethodOperationType.GetProperty: requiredArity = 0; break; case MethodOperationType.SetField: case MethodOperationType.SetProperty: requiredArity = 1; break; case MethodOperationType.InvokeField: case MethodOperationType.InvokeProperty: case MethodOperationType.InvokeEvent: case MethodOperationType.InvokeMethod: requiredArity = methodSelector.NumArgs; // We can't know the actual required arity until run time. break; default: Context.markAsUncompilable(); compiler.handlePrimitiveSpeficationError( "Unknown/unsupported primitive specification format: " + primitiveSpecSelector.ToString(), primitiveSpec.Span); method = Context.newPrimitiveFunctionMethodDeclarationNode(className, methodSelector, primitiveFunction); break; } if (methodSelector.NumArgs != requiredArity) { Context.markAsUncompilable(); compiler.handlePrimitiveSpeficationError( "Method parameter arity mismatch: Method selector has " + methodSelector.NumArgs + " arguments, but the specified primitive function/operation requires " + requiredArity + " arguments.", primitiveSpec.Span); } if (method == null) { String operandName = null; primitiveSpec.messageArgumentsDo(argument => operandName = argument.asPathString('.')); if (opType == MethodOperationType.InvokeMethod && operandName == "new") { opType = MethodOperationType.CreateInstance; } var operation = new InlineOperation(opType, operandName); method = Context.newInlineOperationMethodDeclarationNode(className, methodSelector, operation); } } method.Body = generateExecutableCodeNodeForMethodDeclaration(operand); return(method); }
public InlineOperationMethodDeclarationNode newInlineOperationMethodDeclarationNode(ESSymbol className, ESSymbol selector, InlineOperation operation) { return(new InlineOperationMethodDeclarationNode(this, className, selector, operation)); }