/*
 * See LICENSE file in distribution for copyright and licensing information.
 */
package ioke.lang;

import gnu.math.IntNum;

import ioke.lang.exceptions.ControlFlow;

/**
 *
 * @author <a href="mailto:ola.bini@gmail.com">Ola Bini</a>
 */
public class Number extends IokeObject {
    private final IntNum value;

    public Number(Runtime runtime, String textRepresentation) {
        super(runtime, runtime.number.documentation);
        this.mimics(runtime.number);
        value = IntNum.valueOf(textRepresentation);
    }

    public Number(Runtime runtime, String textRepresentation, String description) {
        super(runtime, description);
        if(runtime.number != null) {
            this.mimics(runtime.number);
        }
        value = IntNum.valueOf(textRepresentation);
    }

    public Number(Runtime runtime, int javaNumber) {
        super(runtime, runtime.number.documentation);
        this.mimics(runtime.number);
        value = IntNum.make(javaNumber);
    }

    public Number(Runtime runtime, IntNum value) {
        super(runtime, runtime.number.documentation);
        this.mimics(runtime.number);
        this.value = value;
    }
    
    @Override
    IokeObject allocateCopy(Message m, IokeObject context) {
        return new Number(runtime, value);
    }

    public String asJavaString() {
        return value.toString();
    }

    public int asJavaInteger() {
        return value.intValue();
    }

    public String toString() {
        return asJavaString();
    }

    public Number convertToNumber(Message m, IokeObject context) {
        return this;
    }

    public void init() {
        this.mimics(runtime.mixins.comparing);

        registerMethod(new JavaMethod(runtime, "<=>", "compares this number against the argument, returning -1, 0 or 1 based on which one is larger") {
                public IokeObject activate(IokeObject context, Message message, IokeObject on) throws ControlFlow {
                    IokeObject arg = ((Message)message).getEvaluatedArgument(0, context);
                    if(!(arg instanceof Number)) {
                        arg = arg.convertToNumber(message, context);
                    }
                    return new Number(runtime, IntNum.compare(((Number)on).value,((Number)arg).value));
                }
            });

        registerMethod(new JavaMethod(runtime, "-", "returns the difference between this number and the argument") {
                public IokeObject activate(IokeObject context, Message message, IokeObject on) throws ControlFlow {
                    IokeObject arg = ((Message)message).getEvaluatedArgument(0, context);
                    if(!(arg instanceof Number)) {
                        arg = arg.convertToNumber(message, context);
                    }
                    return new Number(runtime, IntNum.sub(((Number)on).value,((Number)arg).value));
                }
            });

        registerMethod(new JavaMethod(runtime, "+", "returns the addition of this number and the argument") {
                public IokeObject activate(IokeObject context, Message message, IokeObject on) throws ControlFlow {
                    IokeObject arg = ((Message)message).getEvaluatedArgument(0, context);
                    if(!(arg instanceof Number)) {
                        arg = arg.convertToNumber(message, context);
                    }
                    return new Number(runtime, IntNum.add(((Number)on).value,((Number)arg).value));
                }
            });

        registerMethod(new JavaMethod(runtime, "asText", "Returns a text representation of the object") {
                public IokeObject activate(IokeObject context, Message message, IokeObject on) {
                    return new Text(runtime, ((Number)on).toString());
                }
            });

        registerMethod(new JavaMethod(runtime, "succ", "Returns the successor of this number") {
                public IokeObject activate(IokeObject context, Message message, IokeObject on) {
                    return new Number(runtime, IntNum.add(((Number)on).value,IntNum.one()));
                }
            });
    }
}// Number

@@ -4135,16 +4135,1595 @@
      %7D);
+%0A%0A        registerMethod(new JavaMethod(runtime, %22times%22, %22Expects one or two arguments. If one argument is given, executes it as many times as the value of the receiving number. If two arguments are given, the first will be an unevaluated name that will receive the current loop value on each repitition. the iteration length is limited to the positive maximum of a Java int%22) %7B%0A                public IokeObject activate(IokeObject context, Message message, IokeObject on) throws ControlFlow %7B%0A                    int num = ((Number)on).value.intValue();%0A                    switch(message.getArgumentCount()) %7B%0A                    case 0:%0A                        return runtime.nil;%0A                    case 1: %7B%0A                        IokeObject result = runtime.nil;%0A                        while(num %3E 0) %7B%0A                            result = message.getEvaluatedArgument(0, context);%0A                            num--;%0A                        %7D%0A                        return result;%0A                    %7D%0A                    default:%0A                        int ix = 0;%0A                        String name = ((Message)(message.getArg1())).getName();%0A                        IokeObject result = runtime.nil;%0A                        while(ix%3Cnum) %7B%0A                            context.setCell(name, new Number(runtime, IntNum.make(ix)));%0A                            result = message.getEvaluatedArgument(1, context);%0A                            ix++;%0A                        %7D%0A                        return result;%0A                    %7D%0A                %7D%0A            %7D);
 %0A    %7D%0A%7D

Add support for a times-method to repeat something n times