mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 22:10:15 +03:00
Add the ability to split Text on word boundaries (#1302)
This commit is contained in:
parent
fbe1f4c439
commit
e62f6796fe
@ -2,6 +2,7 @@ from Base import all
|
||||
from Builtins import Text, Prim_Text_Helpers
|
||||
|
||||
import Base.Data.Text.Split_Kind
|
||||
import Base.Meta
|
||||
|
||||
from Builtins export Text
|
||||
|
||||
@ -10,8 +11,8 @@ polyglot java import org.enso.base.Text_Utils
|
||||
|
||||
## Computes the number of characters in the text.
|
||||
|
||||
A character is defined as an Extended Grapheme Cluster, see
|
||||
[Unicode Standard Annex #29](https://unicode.org/reports/tr29/).
|
||||
A character is defined as an Extended Grapheme Cluster, see Unicode
|
||||
[Standard Annex #29](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries).
|
||||
|
||||
This is the smallest unit that still has semantic meaning in most
|
||||
text-processing applications.
|
||||
@ -29,8 +30,8 @@ Text.length =
|
||||
|
||||
## Applies `function` to each character in `this`.
|
||||
|
||||
A character is defined as an Extended Grapheme Cluster, see
|
||||
[Unicode Standard Annex #29](https://unicode.org/reports/tr29/).
|
||||
A character is defined as an Extended Grapheme Cluster, see Unicode
|
||||
[Standard Annex #29](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries).
|
||||
|
||||
This is the smallest unit that still has semantic meaning in most
|
||||
text-processing applications.
|
||||
@ -51,8 +52,8 @@ Text.each function =
|
||||
|
||||
## Returns a vector containing all characters in the given text.
|
||||
|
||||
A character is defined as an Extended Grapheme Cluster, see
|
||||
[Unicode Standard Annex #29](https://unicode.org/reports/tr29/).
|
||||
A character is defined as an Extended Grapheme Cluster, see Unicode
|
||||
[Standard Annex #29](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries).
|
||||
|
||||
This is the smallest unit that still has semantic meaning in most
|
||||
text-processing applications.
|
||||
@ -76,9 +77,45 @@ Text.split (separator = Split_Kind.Whitespace) =
|
||||
result = case separator of
|
||||
Split_Kind.Whitespace -> Text_Utils.split_on_whitespace [this]
|
||||
Split_Kind.Lines -> Text_Utils.split_on_lines [this]
|
||||
Split_Kind.Words -> this.words
|
||||
Text -> Text_Utils.split_by_literal [this, separator]
|
||||
Vector.from_polyglot_array result
|
||||
|
||||
## Returns a vector containing all words in the given text.
|
||||
|
||||
A word is defined based on the definition of Word Boundaries in the Unicode
|
||||
[Standard Annex #29](https://www.unicode.org/reports/tr29/#Word_Boundaries),
|
||||
supplemented by language-specific dictionaries for Chinese, Japanese, Thai,
|
||||
and Khmer.
|
||||
|
||||
By default, the function doesn't include the whitespace between words, but
|
||||
this can be enabled.
|
||||
|
||||
> Example
|
||||
Getting the words in the sentence "I have not one, but two cats."
|
||||
"I have not one, but two cats.".words
|
||||
Text.words : Boolean -> Vector.Vector
|
||||
Text.words keep_whitespace=False =
|
||||
iterator = BreakIterator.getWordInstance []
|
||||
iterator.setText [this]
|
||||
bldr = Vector.new_builder
|
||||
fst = iterator.first []
|
||||
nxt = iterator.next []
|
||||
|
||||
build prev nxt = if nxt == -1 then Nothing else
|
||||
word = Text_Utils.substring [this, prev, nxt]
|
||||
word_not_whitespace = (Text_Utils.is_whitespace [word]).not
|
||||
if word_not_whitespace then bldr.append word else
|
||||
if keep_whitespace then
|
||||
bldr.append word
|
||||
|
||||
next_nxt = iterator.next []
|
||||
@Tail_Call build nxt next_nxt
|
||||
|
||||
build fst nxt
|
||||
|
||||
bldr.to_vector
|
||||
|
||||
## Checks whether `this` is equal to `that`.
|
||||
|
||||
The definition of equality includes Unicode canonicalization. I.e. two texts
|
||||
@ -92,7 +129,8 @@ Text.split (separator = Split_Kind.Whitespace) =
|
||||
`e` followed by U+0301, COMBINING ACUTE ACCENT). Therefore:
|
||||
('é' == 'e\u0301') == True
|
||||
Text.== : Any -> Boolean
|
||||
Text.== that = Text_Utils.equals [this, that]
|
||||
Text.== that = if Meta.is_same_object this Text then Meta.is_same_object that Text else
|
||||
Text_Utils.equals [this, that]
|
||||
|
||||
## Checks whether `this` is equal to `that`, ignoring case considerations.
|
||||
|
||||
|
@ -6,6 +6,8 @@ type Split_Kind
|
||||
type Whitespace
|
||||
## Split into lines.
|
||||
type Lines
|
||||
## Split into words.
|
||||
type Words
|
||||
## Split on a literal.
|
||||
Text
|
||||
|
||||
|
@ -73,6 +73,43 @@ Polyglot.get_language =
|
||||
lang_str = Builtins.Meta.get_polyglot_language
|
||||
if lang_str == "java" then Java else Unknown
|
||||
|
||||
## Checks if `this` is an instance of `typ`.
|
||||
Any.is_a : Any -> Boolean
|
||||
Any.is_a typ = here.is_a this typ
|
||||
|
||||
## Checks if `this` is an instance of `typ`.
|
||||
Any.is_an : Any -> Boolean
|
||||
Any.is_an typ = here.is_a this typ
|
||||
|
||||
## Checks if `value` is an instance of `typ`.
|
||||
is_a : Any -> Any -> Boolean
|
||||
is_a value typ = if typ == Any then True else
|
||||
case value of
|
||||
Array -> typ == Array
|
||||
Boolean -> if typ == Boolean then True else value == typ
|
||||
Text -> typ == Text
|
||||
Number -> if typ == Number then True else case value of
|
||||
Integer -> typ == Integer
|
||||
Decimal -> typ == Decimal
|
||||
Base.Polyglot -> typ == Base.Polyglot
|
||||
_ ->
|
||||
meta_val = here.meta value
|
||||
case meta_val of
|
||||
Atom _ -> meta_val.constructor == typ
|
||||
Constructor _ ->
|
||||
meta_typ = here.meta typ
|
||||
case meta_typ of
|
||||
Atom _ -> meta_val.constructor == meta_typ.constructor
|
||||
Constructor _ -> meta_val.constructor == meta_typ
|
||||
_ -> False
|
||||
Error _ -> typ == Error
|
||||
Unresolved_Symbol _ -> typ == Unresolved_Symbol
|
||||
_ -> False
|
||||
|
||||
## Checks if `value` is an instance of `typ`.
|
||||
is_an : Any -> Any -> Boolean
|
||||
is_an value typ = here.is_a value typ
|
||||
|
||||
## Returns a meta-representation of a given runtime entity.
|
||||
meta : Any -> Meta
|
||||
meta value = if Builtins.Meta.is_atom value then Atom value else
|
||||
|
@ -54,15 +54,8 @@ expect_fail_with ~action matcher =
|
||||
case res of
|
||||
_ -> here.fail ("Expected a " + matcher.to_text + " to be thrown, but the action succeeded.")
|
||||
err = res.catch x->x
|
||||
case Meta.meta matcher of
|
||||
Meta.Atom _ -> if err == matcher then Success else
|
||||
here.fail ("Expected a " + matcher.to_text + "be thrown, but found " + err.to_text + ".")
|
||||
Meta.Constructor _ ->
|
||||
meta_err = Meta.meta err
|
||||
case meta_err of
|
||||
Meta.Atom _ -> if meta_err.constructor == matcher then Success else
|
||||
here.fail ("Unexpected error " + err.to_text + " thrown.")
|
||||
_ -> here.fail ("Incorrect instance " + err.to_text + ".")
|
||||
if err.is_a matcher then Nothing else
|
||||
here.fail ("Unexpected error " + err.to_text + " thrown.")
|
||||
|
||||
## Asserts that `this` value is equal to the expected value.
|
||||
Any.should_equal that = case this == that of
|
||||
|
@ -12,6 +12,7 @@ import org.enso.interpreter.node.ExpressionNode;
|
||||
import org.enso.interpreter.node.callable.ExecuteCallNode;
|
||||
import org.enso.interpreter.node.callable.ExecuteCallNodeGen;
|
||||
import org.enso.interpreter.node.callable.function.CreateFunctionNode;
|
||||
import org.enso.interpreter.runtime.builtin.Bool;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
|
@ -0,0 +1,56 @@
|
||||
package org.enso.interpreter.node.controlflow;
|
||||
|
||||
import com.oracle.truffle.api.RootCallTarget;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.runtime.builtin.Bool;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
|
||||
@NodeInfo(shortName = "BooleanConsMatch", description = "Match using the Boolean constructor.")
|
||||
public abstract class BooleanConstructorBranchNode extends BranchNode {
|
||||
private final AtomConstructor boolCons;
|
||||
private final AtomConstructor trueCons;
|
||||
private final AtomConstructor falseCons;
|
||||
private final ConditionProfile profile = ConditionProfile.createCountingProfile();
|
||||
|
||||
BooleanConstructorBranchNode(Bool bool, RootCallTarget branch) {
|
||||
super(branch);
|
||||
this.boolCons = bool.getBool();
|
||||
this.trueCons = bool.getTrue();
|
||||
this.falseCons = bool.getFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new node for handling matching using the Boolean constructor in a case expression.
|
||||
*
|
||||
* @param bool the boolean container
|
||||
* @param branch the expression to be executed if (@code matcher} matches
|
||||
* @return a node for matching in a case expression
|
||||
*/
|
||||
public static BooleanConstructorBranchNode build(Bool bool, RootCallTarget branch) {
|
||||
return BooleanConstructorBranchNodeGen.create(bool, branch);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
void doConstructor(VirtualFrame frame, Object state, Atom target) {
|
||||
var shouldMatch =
|
||||
(target.getConstructor() == boolCons)
|
||||
|| (target.getConstructor() == falseCons)
|
||||
|| (target.getConstructor() == trueCons);
|
||||
if (profile.profile(shouldMatch)) {
|
||||
accept(frame, state, new Object[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
void doBool(VirtualFrame frame, Object state, boolean target) {
|
||||
accept(frame, state, new Object[0]);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
void doFallback(VirtualFrame frame, Object state, Object target) {}
|
||||
}
|
@ -6,6 +6,7 @@ import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.runtime.builtin.Number;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
@ -13,27 +14,35 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
@NodeInfo(shortName = "IntegerMatch", description = "Allows matching on the Integer type.")
|
||||
public abstract class IntegerBranchNode extends BranchNode {
|
||||
private final AtomConstructor integer;
|
||||
private final AtomConstructor smallInteger;
|
||||
private final AtomConstructor bigInteger;
|
||||
private final ConditionProfile profile = ConditionProfile.createCountingProfile();
|
||||
|
||||
public IntegerBranchNode(AtomConstructor integer, RootCallTarget branch) {
|
||||
public IntegerBranchNode(Number number, RootCallTarget branch) {
|
||||
super(branch);
|
||||
this.integer = integer;
|
||||
this.integer = number.getInteger();
|
||||
this.smallInteger = number.getSmallInteger();
|
||||
this.bigInteger = number.getBigInteger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new node to handle matching with the Integer constructor.
|
||||
*
|
||||
* @param integer the constructor used for matching
|
||||
* @param number the constructor used for matching
|
||||
* @param branch the code to execute
|
||||
* @return an integer branch node
|
||||
*/
|
||||
public static IntegerBranchNode build(AtomConstructor integer, RootCallTarget branch) {
|
||||
return IntegerBranchNodeGen.create(integer, branch);
|
||||
public static IntegerBranchNode build(Number number, RootCallTarget branch) {
|
||||
return IntegerBranchNodeGen.create(number, branch);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
void doConstructor(VirtualFrame frame, Object state, Atom target) {
|
||||
if (profile.profile(integer == target.getConstructor())) {
|
||||
var shouldMatch =
|
||||
(integer == target.getConstructor())
|
||||
|| (smallInteger == target.getConstructor())
|
||||
|| (bigInteger == target.getConstructor());
|
||||
if (profile.profile(shouldMatch)){
|
||||
accept(frame, state, target.getFields());
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.runtime.builtin.Number;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
@ -13,11 +14,19 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
@NodeInfo(shortName = "NumberMatch", description = "Allows matching on the Number type.")
|
||||
public abstract class NumberBranchNode extends BranchNode {
|
||||
private final AtomConstructor number;
|
||||
private final AtomConstructor integer;
|
||||
private final AtomConstructor bigInteger;
|
||||
private final AtomConstructor smallInteger;
|
||||
private final AtomConstructor decimal;
|
||||
private final ConditionProfile profile = ConditionProfile.createCountingProfile();
|
||||
|
||||
NumberBranchNode(AtomConstructor number, RootCallTarget branch) {
|
||||
NumberBranchNode(Number number, RootCallTarget branch) {
|
||||
super(branch);
|
||||
this.number = number;
|
||||
this.number = number.getNumber();
|
||||
this.integer = number.getInteger();
|
||||
this.bigInteger = number.getBigInteger();
|
||||
this.smallInteger = number.getSmallInteger();
|
||||
this.decimal = number.getDecimal();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -27,13 +36,19 @@ public abstract class NumberBranchNode extends BranchNode {
|
||||
* @param branch the code to execute
|
||||
* @return an integer branch node
|
||||
*/
|
||||
public static NumberBranchNode build(AtomConstructor number, RootCallTarget branch) {
|
||||
public static NumberBranchNode build(Number number, RootCallTarget branch) {
|
||||
return NumberBranchNodeGen.create(number, branch);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
void doConstructor(VirtualFrame frame, Object state, Atom target) {
|
||||
if (profile.profile(number == target.getConstructor())) {
|
||||
var shouldMatch =
|
||||
(target.getConstructor() == number)
|
||||
|| (target.getConstructor() == integer)
|
||||
|| (target.getConstructor() == bigInteger)
|
||||
|| (target.getConstructor() == smallInteger)
|
||||
|| (target.getConstructor() == decimal);
|
||||
if (profile.profile(shouldMatch)) {
|
||||
accept(frame, state, target.getFields());
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,48 @@
|
||||
package org.enso.interpreter.node.expression.builtin.bool;
|
||||
|
||||
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
|
||||
@BuiltinMethod(type = "Boolean", name = "==", description = "Computes the equality of two booleans")
|
||||
public class EqualsNode extends Node {
|
||||
boolean execute(boolean _this, boolean that) {
|
||||
public abstract class EqualsNode extends Node {
|
||||
abstract boolean execute(Object _this, Object that);
|
||||
|
||||
static EqualsNode build() {
|
||||
return EqualsNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBoolean(boolean _this, boolean that) {
|
||||
return _this == that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doAtom(
|
||||
Atom _this,
|
||||
Atom that,
|
||||
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||
@Cached("getBooleanConstructor(ctxRef)") AtomConstructor boolCons
|
||||
) {
|
||||
var thisCons = _this.getConstructor();
|
||||
var thatCons = that.getConstructor();
|
||||
return (thatCons == boolCons) && (thisCons == thatCons);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(Object _this, Object that) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AtomConstructor getBooleanConstructor(ContextReference<Context> ctxRef) {
|
||||
return ctxRef.get().getBuiltins().bool().getBool();
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,24 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
import cats.derived.IterState.Cont;
|
||||
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "==", description = "Big integer equality.")
|
||||
public abstract class EqualsNode extends Node {
|
||||
|
||||
abstract boolean execute(EnsoBigInteger _this, Object that);
|
||||
abstract boolean execute(Object _this, Object that);
|
||||
|
||||
static EqualsNode build() {
|
||||
return EqualsNodeGen.create();
|
||||
@ -26,8 +34,23 @@ public abstract class EqualsNode extends Node {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) == that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doAtom(
|
||||
Atom _this,
|
||||
Atom that,
|
||||
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||
@Cached("getBigIntegerConstructor(ctxRef)") AtomConstructor bigIntCons) {
|
||||
var thisCons = _this.getConstructor();
|
||||
var thatCons = that.getConstructor();
|
||||
return (thatCons == bigIntCons) && (thisCons == thatCons);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(EnsoBigInteger _this, Object that) {
|
||||
boolean doOther(Object _this, Object that) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AtomConstructor getBigIntegerConstructor(ContextReference<Context> ctxRef) {
|
||||
return ctxRef.get().getBuiltins().number().getBigInteger();
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,22 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "==", description = "Equality on numbers.")
|
||||
public abstract class EqualsNode extends Node {
|
||||
|
||||
abstract boolean execute(double _this, Object that);
|
||||
abstract boolean execute(Object _this, Object that);
|
||||
|
||||
static EqualsNode build() {
|
||||
return EqualsNodeGen.create();
|
||||
@ -31,8 +37,23 @@ public abstract class EqualsNode extends Node {
|
||||
return _this == BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doAtom(
|
||||
Atom _this,
|
||||
Atom that,
|
||||
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||
@Cached("getDecimalConstructor(ctxRef)") AtomConstructor decimalCons) {
|
||||
var thatCons = that.getConstructor();
|
||||
var thisCons = _this.getConstructor();
|
||||
return (thatCons == decimalCons) && (thisCons == thatCons);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(double _this, Object that) {
|
||||
boolean doOther(Object _this, Object that) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AtomConstructor getDecimalConstructor(ContextReference<Context> ctxRef) {
|
||||
return ctxRef.get().getBuiltins().number().getDecimal();
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,21 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.smallInteger;
|
||||
|
||||
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = "==", description = "Equality on numbers.")
|
||||
public abstract class EqualsNode extends Node {
|
||||
|
||||
abstract boolean execute(long _this, Object that);
|
||||
abstract boolean execute(Object _this, Object that);
|
||||
|
||||
static EqualsNode build() {
|
||||
return EqualsNodeGen.create();
|
||||
@ -24,8 +31,23 @@ public abstract class EqualsNode extends Node {
|
||||
return (double) _this == that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doAtom(
|
||||
Atom _this,
|
||||
Atom that,
|
||||
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||
@Cached("getSmallIntegerConstructor(ctxRef)") AtomConstructor smallIntCons) {
|
||||
var thisCons = _this.getConstructor();
|
||||
var thatCons = that.getConstructor();
|
||||
return (thatCons == smallIntCons) && (thisCons == thatCons);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(long _this, Object that) {
|
||||
boolean doOther(Object _this, Object that) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AtomConstructor getSmallIntegerConstructor(ContextReference<Context> ctxRef) {
|
||||
return ctxRef.get().getBuiltins().number().getBigInteger();
|
||||
}
|
||||
}
|
||||
|
@ -701,11 +701,10 @@ class IrToTruffle(
|
||||
)
|
||||
|
||||
runtimeConsOpt.map { atomCons =>
|
||||
val any = context.getBuiltins.any
|
||||
val array = context.getBuiltins.mutable.constructor
|
||||
val bool = context.getBuiltins.bool
|
||||
val decimal = context.getBuiltins.number.getDecimal
|
||||
val integer = context.getBuiltins.number.getInteger
|
||||
val number = context.getBuiltins.number.getNumber
|
||||
val number = context.getBuiltins.number
|
||||
val polyglot = context.getBuiltins.polyglot.getPolyglot
|
||||
val text = context.getBuiltins.text
|
||||
val branchNode: BranchNode =
|
||||
@ -713,18 +712,22 @@ class IrToTruffle(
|
||||
BooleanBranchNode.build(true, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == bool.getFalse) {
|
||||
BooleanBranchNode.build(false, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == bool.getBool) {
|
||||
BooleanConstructorBranchNode.build(bool, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == text.getText) {
|
||||
TextBranchNode.build(text.getText, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == integer) {
|
||||
IntegerBranchNode.build(integer, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == decimal) {
|
||||
DecimalBranchNode.build(decimal, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == number) {
|
||||
} else if (atomCons == number.getInteger) {
|
||||
IntegerBranchNode.build(number, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == number.getDecimal) {
|
||||
DecimalBranchNode.build(number.getDecimal, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == number.getNumber) {
|
||||
NumberBranchNode.build(number, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == array) {
|
||||
ArrayBranchNode.build(array, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == polyglot) {
|
||||
PolyglotBranchNode.build(polyglot, branchCodeNode.getCallTarget)
|
||||
} else if (atomCons == any) {
|
||||
CatchAllBranchNode.build(branchCodeNode.getCallTarget)
|
||||
} else {
|
||||
ConstructorBranchNode.build(
|
||||
atomCons,
|
||||
|
@ -89,6 +89,17 @@ public class Text_Utils {
|
||||
return vertical_space.split(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided string consists only of whitespace characters.
|
||||
*
|
||||
* @param str the string to check
|
||||
* @return {@code true} if {@code str} is only whitespace, otherwise {@code false}
|
||||
*/
|
||||
public static boolean is_whitespace(String str) {
|
||||
var matcher = whitespace.matcher(str);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether two strings are equal up to Unicode canonicalization.
|
||||
*
|
||||
|
@ -20,6 +20,11 @@ spec = describe "Text" <|
|
||||
utf_8_whitespace_split = ["foo", "bar", "baz", "quux"]
|
||||
utf_8_vertical = 'foo\n bar \v baz \r quux'
|
||||
utf_8_vertical_split = ["foo", " bar ", " baz ", " quux"]
|
||||
sentences = '''
|
||||
I have a very long block of text, here. It goes on and on, containing
|
||||
things like decimal points (1.0314e3) and other language scripts as well
|
||||
건반(Korean).
|
||||
sentence_words = ['I', 'have', 'a', 'very', 'long', 'block', 'of', 'text', ',', 'here', '.', 'It', 'goes', 'on', 'and', 'on', ',', 'containing', 'things', 'like', 'decimal', 'points', '(', '1.0314e3', ')', 'and', 'other', 'language', 'scripts', 'as', 'well', '건반', '(', 'Korean', ')', '.']
|
||||
it "should allow naive length computation over grapheme clusters" <|
|
||||
kshi.length . should_equal 1
|
||||
facepalm.length . should_equal 1
|
||||
@ -29,6 +34,8 @@ spec = describe "Text" <|
|
||||
it "should split the text into grapheme clusters" <|
|
||||
str = kshi + facepalm + accent_1 + accent_2
|
||||
str.characters . should_equal [kshi, facepalm, accent_1, accent_2]
|
||||
it "should be able to split the text into words" <|
|
||||
sentences.words . should_equal sentence_words
|
||||
it "should be able to split the text on UTF-8 whitespace" <|
|
||||
utf_8_whitespace.split . should_equal utf_8_whitespace_split
|
||||
it "should be able to split the text on UTF-8 newlines" <|
|
||||
|
@ -5,6 +5,16 @@ import Test
|
||||
polyglot java import java.util.Random
|
||||
|
||||
spec = describe "Pattern Matches" <|
|
||||
it "should be able to match on the Boolean type" <|
|
||||
case Boolean of
|
||||
Boolean -> Nothing
|
||||
_ -> Test.fail "Expected the Boolean constructor to match."
|
||||
case True of
|
||||
Boolean -> Nothing
|
||||
_ -> Test.fail "Expected the True constructor to match."
|
||||
case False of
|
||||
Boolean -> Nothing
|
||||
_ -> Test.fail "Expected the False constructor to match."
|
||||
it "should be able to match on the Integer type" <|
|
||||
case 1 of
|
||||
Integer -> Nothing
|
||||
@ -15,6 +25,12 @@ spec = describe "Pattern Matches" <|
|
||||
case Integer of
|
||||
Integer -> Nothing
|
||||
_ -> Test.fail "Expected the Integer constructor to match."
|
||||
case Big_Integer of
|
||||
Integer -> Nothing
|
||||
_ -> Test.fail "Expected the Big_Integer constructor to match."
|
||||
case Small_Integer of
|
||||
Integer -> Nothing
|
||||
_ -> Test.fail "Expected the Small_Integer constructor to match."
|
||||
it "should be able to match on the Decimal type" <|
|
||||
case 1.7 of
|
||||
Decimal -> Nothing
|
||||
@ -35,6 +51,18 @@ spec = describe "Pattern Matches" <|
|
||||
case Number of
|
||||
Number -> Nothing
|
||||
_ -> Test.fail "Expected the Number constructor to match."
|
||||
case Small_Integer of
|
||||
Number -> Nothing
|
||||
_ -> Test.fail "Expected the Small_Integer constructor to match."
|
||||
case Big_Integer of
|
||||
Number -> Nothing
|
||||
_ -> Test.fail "Expected the Big_Integer constructor to match."
|
||||
case Integer of
|
||||
Number -> Nothing
|
||||
_ -> Test.fail "Expected the Integer constructor to match."
|
||||
case Decimal of
|
||||
Number -> Nothing
|
||||
_ -> Test.fail "Expected the Decimal constructor to match."
|
||||
it "should be able to match on the Text type" <|
|
||||
case "foo" of
|
||||
Text -> Nothing
|
||||
@ -57,3 +85,18 @@ spec = describe "Pattern Matches" <|
|
||||
case Polyglot of
|
||||
Polyglot -> Nothing
|
||||
_ -> Test.fail "Expected the Polyglot constructor to match."
|
||||
it "should be able to match on the Any type" <|
|
||||
value_1 = 1.23143
|
||||
value_2 = "foo bar"
|
||||
case value_1 of
|
||||
Any -> Nothing
|
||||
_ -> Test.fail "Expected any value to match Any."
|
||||
case value_2 of
|
||||
Any -> Nothing
|
||||
_ -> Test.fail "Expected any value to match Any."
|
||||
case Polyglot of
|
||||
Any -> Nothing
|
||||
_ -> Test.fail "Expect any constructor to match Any."
|
||||
case Any of
|
||||
Any -> Nothing
|
||||
_ -> Test.fail "Expected the Any constructor to match."
|
||||
|
@ -1,10 +1,14 @@
|
||||
from Base import all
|
||||
import Test
|
||||
|
||||
polyglot java import java.util.Random
|
||||
|
||||
type My_Type foo bar baz
|
||||
|
||||
My_Type.my_method = this.foo + this.bar + this.baz
|
||||
|
||||
type Test_Type x
|
||||
|
||||
spec = describe "Meta-Value Manipulation" <|
|
||||
it "should allow manipulating unresolved symbols" <|
|
||||
sym = does_not_exist
|
||||
@ -22,4 +26,38 @@ spec = describe "Meta-Value Manipulation" <|
|
||||
it "should correctly return representations of different classes of objects" <|
|
||||
Meta.meta 1 . should equal (Meta.Primitive 1)
|
||||
Meta.meta "foo" . should equal (Meta.Primitive "foo")
|
||||
it "should allow checking if a value is of a certain type" <|
|
||||
1.is_an Any . should_be_true
|
||||
1.2.is_an Any . should_be_true
|
||||
(My_Type 1 "foo" Nothing).is_an Any . should_be_true
|
||||
|
||||
Array.is_an Array . should_be_true
|
||||
[].to_array.is_an Array . should_be_true
|
||||
[].to_array.is_a Decimal . should_be_false
|
||||
|
||||
Boolean.is_a Boolean . should_be_true
|
||||
True.is_a Boolean . should_be_true
|
||||
False.is_a Boolean . should_be_true
|
||||
True.is_an Integer . should_be_false
|
||||
|
||||
"".is_a Text . should_be_true
|
||||
"".is_a Decimal . should_be_false
|
||||
|
||||
1.is_an Array . should_be_false
|
||||
1.is_an Integer . should_be_true
|
||||
1.is_a Number . should_be_true
|
||||
1.is_a Decimal . should_be_false
|
||||
|
||||
1.0.is_a Number . should_be_true
|
||||
1.0.is_a Decimal . should_be_true
|
||||
1.0.is_an Integer . should_be_false
|
||||
1.0.is_a Text . should_be_false
|
||||
|
||||
random_gen = Random.new [].to_array
|
||||
Meta.is_a random_gen Polyglot . should_be_true
|
||||
Meta.is_an random_gen Integer . should_be_false
|
||||
|
||||
(My_Type 1 "foo" Nothing).is_a My_Type . should_be_true
|
||||
(My_Type 1 "foo" Nothing).is_a Test_Type . should_be_false
|
||||
(My_Type 1 "foo" Nothing).is_a Number . should_be_false
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user