Esempio n. 1
0
        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);
        }
Esempio n. 2
0
 public InlineOperationMethodDeclarationNode newInlineOperationMethodDeclarationNode(ESSymbol className, ESSymbol selector, InlineOperation operation)
 {
     return(new InlineOperationMethodDeclarationNode(this, className, selector, operation));
 }