Skip to content

Commit

Permalink
add big integer
Browse files Browse the repository at this point in the history
  • Loading branch information
arvyy committed Nov 3, 2023
1 parent 6ed9422 commit 8baeef2
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.RootNode;

import java.math.BigInteger;

/**
* Implements numeric adition function `+`.
*/
Expand Down Expand Up @@ -43,6 +45,11 @@ int doInts(int a, int b) {
return Math.addExact(a, b);
}

@Specialization
BigInteger doBigInts(BigInteger a, BigInteger b) {
return a.add(b);
}

@Specialization
double doDoubles(double a, double b) {
return a + b;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;

import java.math.BigInteger;

/**
* Implements `class-of` function, returning given object's class.
*/
Expand Down Expand Up @@ -42,6 +44,13 @@ LispClass doInt(
return lispClass;
}

@Specialization
LispClass doBigInt(
BigInteger integer,
@Cached("loadIntegerClass()") LispClass lispClass) {
return lispClass;
}

@Specialization
LispClass doFloat(
double flt,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.profiles.CountingConditionProfile;

import java.math.BigInteger;

/**
* Implements numeric equality function `=`.
*/
Expand Down Expand Up @@ -43,6 +45,14 @@ Object doInts(int a, int b) {
return ISLISPContext.get(this).getNil();
}

@Specialization
Object doBigInts(BigInteger a, BigInteger b) {
if (profile.profile(a.equals(b))) {
return ISLISPContext.get(this).getT();
}
return ISLISPContext.get(this).getNil();
}

@Specialization
Object doDoubles(double a, double b) {
if (profile.profile(a == b)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.profiles.CountingConditionProfile;

import java.math.BigInteger;

/**
* Implements numeric comparator `>`.
*/
Expand Down Expand Up @@ -37,6 +39,14 @@ Object doInts(int a, int b) {
return ISLISPContext.get(this).getNil();
}

@Specialization
Object doBigInts(BigInteger a, BigInteger b) {
if (profile.profile(a.compareTo(b) > 0)) {
return ISLISPContext.get(this).getT();
}
return ISLISPContext.get(this).getNil();
}

@Fallback
Object notNumbers(Object a, Object b) {
throw new ISLISPError("Not numbers", this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.RootNode;

import java.math.BigInteger;

/**
* Implements numeric subtraction function `-`.
*/
Expand Down Expand Up @@ -38,6 +40,11 @@ int doInts(int a, int b) {
return Math.subtractExact(a, b);
}

@Specialization
BigInteger doBigInts(BigInteger a, BigInteger b) {
return a.subtract(b);
}

@Specialization
double doDoubles(double a, double b) {
return a - b;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.oracle.truffle.api.dsl.ImplicitCast;
import com.oracle.truffle.api.dsl.TypeSystem;

import java.math.BigInteger;

// class cannot be final
//CHECKSTYLE:OFF
@TypeSystem({
Expand All @@ -25,6 +27,17 @@ public class ISLISPTypes {

protected ISLISPTypes() { }

/**
* Implicitly convert int to double.
*
* @param v int value
* @return double value
*/
@ImplicitCast
public static BigInteger intToBigInt(int v) {
return BigInteger.valueOf(v);
}

/**
* Implicitly convert int to double.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.oracle.truffle.api.frame.FrameSlotKind;
import com.oracle.truffle.api.source.SourceSection;

import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -246,6 +247,7 @@ ISLISPExpressionNode parseExpressionNode(ParserContext parserContext, Object sex
}
if (sexpr instanceof Integer
|| sexpr instanceof Double
|| sexpr instanceof BigInteger
|| sexpr instanceof LispChar
|| sexpr instanceof String
|| sexpr instanceof LispVector
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -72,7 +73,11 @@ public Optional<Object> readSingle() {
}
if (t instanceof Token.ExactNumberToken) {
var value = ((Token.ExactNumberToken) t).value();
return Optional.of(value);
if (value.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) < 0) {
return Optional.of(value.intValueExact());
} else {
return Optional.of(value);
}
}
if (t instanceof Token.InexactNumberToken inexact) {
return Optional.of(inexact.value());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.github.arvyy.islisp.parser;

import java.math.BigInteger;

/**
* Possible values to be returned from Lexer.
*/
Expand All @@ -9,7 +11,7 @@ public sealed interface Token {
* Exact number literal.
* @param value
*/
record ExactNumberToken(int value) implements Token { }
record ExactNumberToken(BigInteger value) implements Token { }

/**
* Inexact number literal.
Expand Down
9 changes: 5 additions & 4 deletions language/src/main/jflex/islisp.jflex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.github.arvyy.islisp.parser;
import com.github.arvyy.islisp.parser.Token;
import java.util.Optional;
import java.io.IOException;
import java.math.BigInteger;

%%

Expand Down Expand Up @@ -189,19 +190,19 @@ CharacterName = newline | space | tab
}

("#B" | "#b") {ExplicitSign}? {BinDigit}+ {
return new Token.ExactNumberToken(Integer.parseInt(yytext().substring(2), 2));
return new Token.ExactNumberToken(new BigInteger(yytext().substring(2), 2));
}

("#o" | "#O") {ExplicitSign}? {OctDigit}+ {
return new Token.ExactNumberToken(Integer.parseInt(yytext().substring(2), 8));
return new Token.ExactNumberToken(new BigInteger(yytext().substring(2), 8));
}

{ExplicitSign}? {Digit}+ {
return new Token.ExactNumberToken(Integer.parseInt(yytext()));
return new Token.ExactNumberToken(new BigInteger(yytext()));
}

("#x" | "#X") {ExplicitSign}? {HexDigit}+ {
return new Token.ExactNumberToken(Integer.parseInt(yytext().substring(2), 16));
return new Token.ExactNumberToken(new BigInteger(yytext().substring(2), 16));
}

{WhiteSpace} {}
Expand Down
1 change: 1 addition & 0 deletions tests/add.expect.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
OK1
OK2
OK3
OK4
11 changes: 8 additions & 3 deletions tests/add.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@
(print "OK2")
(print "FAIL2"))

;; test big integer
(if (= 10000000000000000001 (+ 10000000000000000000 1))
(print "OK3")
(print "FAIL3"))

(block exit
(with-handler
(lambda (condition)
(if (instancep condition (class <domain-error>))
(print "OK3")
(print "FAIL3"))
(print "OK4")
(print "FAIL4"))
(return-from exit nil))
(+ 1 "2")
(print "FAIL3")))
(print "FAIL4")))

0 comments on commit 8baeef2

Please sign in to comment.