Skip to content

Commit

Permalink
[WIP] Nan is a separate builtin type
Browse files Browse the repository at this point in the history
  • Loading branch information
Akirathan committed Feb 22, 2023
1 parent dfea59c commit 3ae8afe
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 55 deletions.
14 changes: 9 additions & 5 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Numbers.enso
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ type Number
negative_infinity = Double.NEGATIVE_INFINITY

## A constant holding the floating-point Not-a-Number value.
nan : Decimal
nan : Nan
nan = Double.NaN

## Checks if the given number is the floating-point Not-a-Number value.
Expand All @@ -348,6 +348,7 @@ type Number
compared with itself, so `x == Number.nan` would not work.
is_nan : Boolean
is_nan self = case self of
_ : Nan -> True
_ : Decimal -> Double.isNaN self
_ -> False

Expand Down Expand Up @@ -941,10 +942,8 @@ type Integer

parse_builtin text radix = @Builtin_Method "Integer.parse"

Comparable.from (that:Number) =
case that.is_nan of
True -> Incomparable
False -> Default_Ordered_Comparator
@Builtin_Type
type Nan

## UNSTABLE

Expand All @@ -959,3 +958,8 @@ type Number_Parse_Error
to_display_text : Text
to_display_text =
"Could not parse " + self.text.to_text + " as a double."


Comparable.from (_:Nan) = Incomparable
Comparable.from (_:Integer) = Default_Ordered_Comparator
Comparable.from (_:Decimal) = Default_Ordered_Comparator
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ boolean doLongCheck(Type expectedType, long payload) {
@Specialization
boolean doDoubleCheck(Type expectedType, double payload) {
var numbers = EnsoContext.get(this).getBuiltins().number();
return checkParentTypes(numbers.getDecimal(), expectedType);
if (Double.isNaN(payload)) {
return checkParentTypes(numbers.getNaN(), expectedType);
} else {
return checkParentTypes(numbers.getDecimal(), expectedType);
}
}

@Specialization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.enso.interpreter.epb.runtime.PolyglotProxy;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.builtin.Builtins;
import org.enso.interpreter.runtime.builtin.Number;
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.error.PanicSentinel;
Expand All @@ -36,7 +37,12 @@ public static TypeOfNode build() {

@Specialization
Object doDouble(double value) {
return EnsoContext.get(this).getBuiltins().number().getDecimal();
var number = EnsoContext.get(this).getBuiltins().number();
if (Double.isNaN(value)) {
return number.getNaN();
} else {
return number.getDecimal();
}
}

@Specialization
Expand Down Expand Up @@ -110,7 +116,15 @@ Object doPolyglotNumber(
if (interop.fitsInInt(proxy)) {
return builtins.number().getInteger();
} else if (interop.fitsInDouble(proxy)) {
return builtins.number().getDecimal();
try {
if (Double.isNaN(interop.asDouble(proxy))) {
return builtins.number().getNaN();
} else {
return builtins.number().getDecimal();
}
} catch (UnsupportedMessageException e) {
throw new IllegalStateException(e);
}
} else {
return EnsoContext.get(this).getBuiltins().number();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.enso.interpreter.node.expression.builtin.number;

import org.enso.interpreter.dsl.BuiltinType;
import org.enso.interpreter.node.expression.builtin.Builtin;

@BuiltinType(name = "Standard.Base.Data.Numbers.Nan")
public class Nan extends Builtin {
@Override
protected Class<? extends Builtin> getSuperType() {
return Number.class;
}

@Override
protected boolean containsValues() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.enso.interpreter.node.expression.builtin.number.BigInteger;
import org.enso.interpreter.node.expression.builtin.number.Decimal;
import org.enso.interpreter.node.expression.builtin.number.Integer;
import org.enso.interpreter.node.expression.builtin.number.Nan;
import org.enso.interpreter.node.expression.builtin.number.SmallInteger;
import org.enso.interpreter.runtime.data.Type;

Expand All @@ -14,6 +15,7 @@ public class Number {
private final Builtin integer;
private final Builtin number;
private final Builtin decimal;
private final Builtin nan;

/** Creates builders for number Atom Constructors. */
public Number(Builtins builtins) {
Expand All @@ -23,6 +25,7 @@ public Number(Builtins builtins) {
number =
builtins.getBuiltinType(org.enso.interpreter.node.expression.builtin.number.Number.class);
decimal = builtins.getBuiltinType(Decimal.class);
nan = builtins.getBuiltinType(Nan.class);
}

/** @return the Int64 atom constructor. */
Expand All @@ -49,4 +52,8 @@ public Type getNumber() {
public Type getDecimal() {
return decimal.getType();
}

public Type getNaN() {
return nan.getType();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ static boolean hasType(Double receiver) {

@ExportMessage
static Type getType(Double receiver, @CachedLibrary("receiver") TypesLibrary thisLib) {
return EnsoContext.get(thisLib).getBuiltins().number().getDecimal();
if (receiver.isNaN()) {
return EnsoContext.get(thisLib).getBuiltins().number().getNaN();
} else {
return EnsoContext.get(thisLib).getBuiltins().number().getDecimal();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.enso.interpreter.runtime.type;

import com.oracle.truffle.api.dsl.TypeCheck;
import com.oracle.truffle.api.dsl.TypeSystem;
import com.oracle.truffle.api.interop.ArityException;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import org.enso.interpreter.node.expression.builtin.number.Nan;
import org.enso.interpreter.runtime.callable.UnresolvedConversion;
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
import org.enso.interpreter.runtime.callable.atom.Atom;
Expand Down Expand Up @@ -30,6 +32,7 @@
long.class,
boolean.class,
double.class,
Nan.class,
Text.class,
Function.class,
Atom.class,
Expand Down Expand Up @@ -59,6 +62,16 @@
})
public class Types {

@TypeCheck(Nan.class)
public static boolean isNan(Object value) {
return value instanceof Double dbl && dbl.isNaN();
}

@TypeCheck(double.class)
public static boolean isDouble(Object value) {
return value instanceof Double dbl && !dbl.isNaN();
}

private static final TypeGraph typeHierarchy = buildTypeHierarchy();

/**
Expand Down Expand Up @@ -116,8 +129,12 @@ public static void extractArguments(Object[] arguments) throws ArityException {
public static String getName(Object value) {
if (TypesGen.isLong(value) || TypesGen.isEnsoBigInteger(value)) {
return ConstantsGen.INTEGER;
} else if (TypesGen.isDouble(value)) {
return ConstantsGen.DECIMAL;
} else if (value instanceof Double dbl) {
if (dbl.isNaN()) {
return ConstantsGen.NAN;
} else {
return ConstantsGen.DECIMAL;
}
} else if (TypesGen.isBoolean(value)) {
return ConstantsGen.BOOLEAN;
} else if (TypesGen.isText(value)) {
Expand Down Expand Up @@ -240,6 +257,7 @@ private static TypeGraph buildTypeHierarchy() {
graph.insert(ConstantsGen.ARRAY, ConstantsGen.ANY);
graph.insert(ConstantsGen.BOOLEAN, ConstantsGen.ANY);
graph.insert(ConstantsGen.DECIMAL, ConstantsGen.NUMBER);
graph.insert(ConstantsGen.NAN, ConstantsGen.NUMBER);
graph.insert(ConstantsGen.ERROR, ConstantsGen.ANY);
graph.insert(ConstantsGen.FUNCTION, ConstantsGen.ANY);
graph.insert(ConstantsGen.INTEGER, ConstantsGen.NUMBER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,49 +25,29 @@ public class TypesFromProxy {
* @return the associated {@link Type} if it exists and {@code null} otherwise
*/
public static Type fromTypeSystem(Builtins builtins, String typeName) {
switch (typeName) {
case ConstantsGen.ANY:
return builtins.any();
case ConstantsGen.ARRAY:
return builtins.array();
case ConstantsGen.BOOLEAN:
return builtins.bool().getType();
case ConstantsGen.DATE:
return builtins.date();
case ConstantsGen.DATE_TIME:
return builtins.dateTime();
case ConstantsGen.DURATION:
return builtins.duration();
case ConstantsGen.DECIMAL:
return builtins.number().getDecimal();
case ConstantsGen.ERROR:
return builtins.dataflowError();
case ConstantsGen.FUNCTION:
return builtins.function();
case ConstantsGen.FILE:
return builtins.file();
case ConstantsGen.INTEGER:
return builtins.number().getInteger();
case ConstantsGen.MANAGED_RESOURCE:
return builtins.managedResource();
case ConstantsGen.NOTHING:
return builtins.nothing();
case ConstantsGen.NUMBER:
return builtins.number().getNumber();
case ConstantsGen.PANIC:
return builtins.panic();
case ConstantsGen.REF:
return builtins.ref();
case ConstantsGen.TEXT:
return builtins.text();
case ConstantsGen.TIME_OF_DAY:
return builtins.timeOfDay();
case ConstantsGen.TIME_ZONE:
return builtins.timeZone();
case ConstantsGen.VECTOR:
return builtins.vector();
default:
return null;
}
return switch (typeName) {
case ConstantsGen.ANY -> builtins.any();
case ConstantsGen.ARRAY -> builtins.array();
case ConstantsGen.BOOLEAN -> builtins.bool().getType();
case ConstantsGen.DATE -> builtins.date();
case ConstantsGen.DATE_TIME -> builtins.dateTime();
case ConstantsGen.DURATION -> builtins.duration();
case ConstantsGen.DECIMAL -> builtins.number().getDecimal();
case ConstantsGen.NAN -> builtins.number().getNaN();
case ConstantsGen.ERROR -> builtins.dataflowError();
case ConstantsGen.FUNCTION -> builtins.function();
case ConstantsGen.FILE -> builtins.file();
case ConstantsGen.INTEGER -> builtins.number().getInteger();
case ConstantsGen.MANAGED_RESOURCE -> builtins.managedResource();
case ConstantsGen.NOTHING -> builtins.nothing();
case ConstantsGen.NUMBER -> builtins.number().getNumber();
case ConstantsGen.PANIC -> builtins.panic();
case ConstantsGen.REF -> builtins.ref();
case ConstantsGen.TEXT -> builtins.text();
case ConstantsGen.TIME_OF_DAY -> builtins.timeOfDay();
case ConstantsGen.TIME_ZONE -> builtins.timeZone();
case ConstantsGen.VECTOR -> builtins.vector();
default -> null;
};
}
}
4 changes: 4 additions & 0 deletions test/Tests/src/Data/Numbers_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,10 @@ spec =
Number.nan==0 . should_be_false
Number.nan!=Number.nan . should_be_true

Test.specify "should support decimal methods on NaN" <|
Number.nan*10 . is_nan . should_be_true
Number.nan.sin . is_nan . should_be_true

Test.specify "should support inexact equality comparisons" <|
1.0001 . equals 1.0002 epsilon=0.01 . should_be_true
1.0001 . equals 1.0002 epsilon=0.0000001 . should_be_false
Expand Down

0 comments on commit 3ae8afe

Please sign in to comment.