├── .gitignore
├── README.md
├── example
├── Sample.class
└── Sample.java
├── jvmmathlang-catalog-java11.properties
├── pom.xml
└── src
└── main
├── assembly
├── distribution.xml
└── native-image.properties
└── java
├── grammer
├── Math.g4
├── Math.tokens
├── MathBaseListener.java
├── MathLexer.java
├── MathLexer.tokens
├── MathListener.java
└── MathParser.java
├── jvmmathlang
└── truffle
│ ├── JvmMathLang.java
│ ├── JvmMathLangContext.java
│ ├── JvmMathLangMain.java
│ ├── JvmMathLangTypes.java
│ └── MathParseTreeListener.java
└── nodes
├── AsyncJvmMathLangNode.java
├── BinaryNode.java
├── JvmMathLangNode.java
├── JvmMathLangRootNode.java
├── ParenJvmMathLangNode.java
├── literal
├── BigDecimalNode.java
├── BigDecimalTruffleObject.java
└── LongNode.java
├── ops
├── AddNode.java
├── DivNode.java
├── MulNode.java
└── SubNode.java
└── uml.puml
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | *.iml
3 | target/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JVM Math language
2 |
3 | ## What is this?
4 |
5 | This is a language implementation of simple arithmetic operations for GraalVM. You can install this language into your GraalVM.
6 |
7 | Of course this is implemented with Truffle API. This program can execute four arithmetic operations. You can use numbers, +, -, *, /, "()". Additionally "->" for running in another thread.
8 |
9 | * Lexer, Parser: ANTLR 4.7
10 | * AST Interpreter: Truffle in GraalVM 20.3.0
11 |
12 | ## Usage
13 |
14 | ### Install
15 |
16 | #### Local Install
17 |
18 | Just run `mvn package` & `gu install -L target/jvmmathlang-0.1.0-component.jar`.
19 | With `gu list`, you can see the JVM Math Lang component as follows.
20 |
21 | ```
22 | $ gu list
23 | ComponentId Version Component name Origin
24 | --------------------------------------------------------------------------------
25 | js 20.3.0 Graal.js
26 | jvmmathlang 1.0.0 JVM Math Lang github.com
27 | graalvm 20.3.0 GraalVM Core
28 | ```
29 |
30 | #### From Component Catalog
31 |
32 | I also provide the component catalog for this language. Just run `gu install -C https://raw.githubusercontent.com/jyukutyo/JVM-Math-Language/master/jvmmathlang-catalog-java11.properties jvmmathlang`. Currently it is only for GraalVM 20.3.0 and 20.2.0.
33 |
34 | ### Run Sample Code
35 |
36 | ```
37 | $ cd example
38 | $ javac Sample.java
39 | $ java Sample
40 | inputed String: (1+2)*3
41 | add(long, long)
42 | 9
43 | ```
44 |
45 | ## Details
46 |
47 | In DevoxxUS 2017 I heard Oleg Šelajev's "How to Create a New JVM Language". He doesn't publish his code, so I wrote code and created a similar language.
48 |
49 | ## Publishing
50 |
51 | * GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう (Japanese, a session at JJUG Night Seminar on 27th Feb 2019)
52 | https://www.slideshare.net/jyukutyo/graalvmjvm
53 |
54 | * オレオレJVM言語を作ってみる (Japanese, a session at JJUG CCC 2017 Fall on 18th Nov 2017)
55 | https://www.slideshare.net/jyukutyo/jjug-ccc-2017-fall-jvm
--------------------------------------------------------------------------------
/example/Sample.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jyukutyo/JVM-Math-Language/b76c9cfa6de68f04aee1fb7979cacb1d6470f06a/example/Sample.class
--------------------------------------------------------------------------------
/example/Sample.java:
--------------------------------------------------------------------------------
1 | import org.graalvm.polyglot.*;
2 |
3 | class Sample {
4 | public static void main(String... args) {
5 | try (var context = Context.newBuilder("jvmmathlang").build()) {
6 | Value answer = context.eval("jvmmathlang", "(1+2)*3");
7 | System.out.println(answer);
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/jvmmathlang-catalog-java11.properties:
--------------------------------------------------------------------------------
1 | # 20.3.0 Release
2 | org.graalvm.20.3.0_linux_amd64=GraalVM 20.3.0 linux/amd64
3 | org.graalvm.20.3.0_windows_amd64=GraalVM 20.3.0 windows/amd64
4 | org.graalvm.20.3.0_macos_amd64=GraalVM 20.3.0 macos/amd64
5 |
6 | Component.20.3.0_linux_amd64.org.graalvm.jvmmathlang=https://github.com/jyukutyo/JVM-Math-Language/releases/download/1.0.0/jvmmathlang-1.0.0-component.jar
7 | Component.20.3.0_linux_amd64.org.graalvm.jvmmathlang-hash=ceb05504f90709d5827fc7dfd092047fc300a586d7cf7e1df1b2aca1a52e451a
8 | Component.20.3.0_linux_amd64.org.graalvm.jvmmathlang-Bundle-Name=JVM Math Lang
9 | Component.20.3.0_linux_amd64.org.graalvm.jvmmathlang-Bundle-Symbolic-Name=jvmmathlang
10 | Component.20.3.0_linux_amd64.org.graalvm.jvmmathlang-Bundle-Version=20.3.0
11 | Component.20.3.0_linux_amd64.org.graalvm.jvmmathlang-Bundle-RequireCapability=org.graalvm; filter:="(&(graalvm_version=20.3.0)(java_version=11))"
12 | Component.20.3.0_linux_amd64.org.graalvm.jvmmathlang-x-GraalVM-Polyglot-Part=True
13 | Component.20.3.0_linux_amd64.org.graalvm.jvmmathlang-x-GraalVM-Working-Directories=languages/jvmmathlang
14 |
15 | Component.20.3.0_windows_amd64.org.graalvm.jvmmathlang=https://github.com/jyukutyo/JVM-Math-Language/releases/download/1.0.0/jvmmathlang-1.0.0-component.jar
16 | Component.20.3.0_windows_amd64.org.graalvm.jvmmathlang-hash=ceb05504f90709d5827fc7dfd092047fc300a586d7cf7e1df1b2aca1a52e451a
17 | Component.20.3.0_windows_amd64.org.graalvm.jvmmathlang-Bundle-Name=JVM Math Lang
18 | Component.20.3.0_windows_amd64.org.graalvm.jvmmathlang-Bundle-Symbolic-Name=jvmmathlang
19 | Component.20.3.0_windows_amd64.org.graalvm.jvmmathlang-Bundle-Version=20.3.0
20 | Component.20.3.0_windows_amd64.org.graalvm.jvmmathlang-Bundle-RequireCapability=org.graalvm; filter:="(&(graalvm_version=20.3.0)(java_version=11))"
21 | Component.20.3.0_windows_amd64.org.graalvm.jvmmathlang-x-GraalVM-Polyglot-Part=True
22 | Component.20.3.0_windows_amd64.org.graalvm.jvmmathlang-x-GraalVM-Working-Directories=languages/jvmmathlang
23 |
24 | Component.20.3.0_macos_amd64.org.graalvm.jvmmathlang=https://github.com/jyukutyo/JVM-Math-Language/releases/download/1.0.0/jvmmathlang-1.0.0-component.jar
25 | Component.20.3.0_macos_amd64.org.graalvm.jvmmathlang-hash=ceb05504f90709d5827fc7dfd092047fc300a586d7cf7e1df1b2aca1a52e451a
26 | Component.20.3.0_macos_amd64.org.graalvm.jvmmathlang-Bundle-Name=JVM Math Lang
27 | Component.20.3.0_macos_amd64.org.graalvm.jvmmathlang-Bundle-Symbolic-Name=jvmmathlang
28 | Component.20.3.0_macos_amd64.org.graalvm.jvmmathlang-Bundle-Version=20.3.0
29 | Component.20.3.0_macos_amd64.org.graalvm.jvmmathlang-Bundle-RequireCapability=org.graalvm; filter:="(&(graalvm_version=20.3.0)(java_version=11))"
30 | Component.20.3.0_macos_amd64.org.graalvm.jvmmathlang-x-GraalVM-Polyglot-Part=True
31 | Component.20.3.0_macos_amd64.org.graalvm.jvmmathlang-x-GraalVM-Working-Directories=languages/jvmmathlang
32 |
33 | # 20.2.0 Release
34 | org.graalvm.20.2.0_linux_amd64=GraalVM 20.2.0 linux/amd64
35 | org.graalvm.20.2.0_windows_amd64=GraalVM 20.2.0 windows/amd64
36 | org.graalvm.20.2.0_macos_amd64=GraalVM 20.2.0 macos/amd64
37 |
38 | Component.20.2.0_linux_amd64.org.graalvm.jvmmathlang=https://github.com/jyukutyo/JVM-Math-Language/releases/download/1.0.0/jvmmathlang-1.0.0-component.jar
39 | Component.20.2.0_linux_amd64.org.graalvm.jvmmathlang-hash=ceb05504f90709d5827fc7dfd092047fc300a586d7cf7e1df1b2aca1a52e451a
40 | Component.20.2.0_linux_amd64.org.graalvm.jvmmathlang-Bundle-Name=JVM Math Lang
41 | Component.20.2.0_linux_amd64.org.graalvm.jvmmathlang-Bundle-Symbolic-Name=jvmmathlang
42 | Component.20.2.0_linux_amd64.org.graalvm.jvmmathlang-Bundle-Version=20.2.0
43 | Component.20.2.0_linux_amd64.org.graalvm.jvmmathlang-Bundle-RequireCapability=org.graalvm; filter:="(&(graalvm_version=20.2.0)(java_version=11))"
44 | Component.20.2.0_linux_amd64.org.graalvm.jvmmathlang-x-GraalVM-Polyglot-Part=True
45 | Component.20.2.0_linux_amd64.org.graalvm.jvmmathlang-x-GraalVM-Working-Directories=languages/jvmmathlang
46 |
47 | Component.20.2.0_windows_amd64.org.graalvm.jvmmathlang=https://github.com/jyukutyo/JVM-Math-Language/releases/download/1.0.0/jvmmathlang-1.0.0-component.jar
48 | Component.20.2.0_windows_amd64.org.graalvm.jvmmathlang-hash=ceb05504f90709d5827fc7dfd092047fc300a586d7cf7e1df1b2aca1a52e451a
49 | Component.20.2.0_windows_amd64.org.graalvm.jvmmathlang-Bundle-Name=JVM Math Lang
50 | Component.20.2.0_windows_amd64.org.graalvm.jvmmathlang-Bundle-Symbolic-Name=jvmmathlang
51 | Component.20.2.0_windows_amd64.org.graalvm.jvmmathlang-Bundle-Version=20.2.0
52 | Component.20.2.0_windows_amd64.org.graalvm.jvmmathlang-Bundle-RequireCapability=org.graalvm; filter:="(&(graalvm_version=20.2.0)(java_version=11))"
53 | Component.20.2.0_windows_amd64.org.graalvm.jvmmathlang-x-GraalVM-Polyglot-Part=True
54 | Component.20.2.0_windows_amd64.org.graalvm.jvmmathlang-x-GraalVM-Working-Directories=languages/jvmmathlang
55 |
56 | Component.20.2.0_macos_amd64.org.graalvm.jvmmathlang=https://github.com/jyukutyo/JVM-Math-Language/releases/download/1.0.0/jvmmathlang-1.0.0-component.jar
57 | Component.20.2.0_macos_amd64.org.graalvm.jvmmathlang-hash=ceb05504f90709d5827fc7dfd092047fc300a586d7cf7e1df1b2aca1a52e451a
58 | Component.20.2.0_macos_amd64.org.graalvm.jvmmathlang-Bundle-Name=JVM Math Lang
59 | Component.20.2.0_macos_amd64.org.graalvm.jvmmathlang-Bundle-Symbolic-Name=jvmmathlang
60 | Component.20.2.0_macos_amd64.org.graalvm.jvmmathlang-Bundle-Version=20.2.0
61 | Component.20.2.0_macos_amd64.org.graalvm.jvmmathlang-Bundle-RequireCapability=org.graalvm; filter:="(&(graalvm_version=20.2.0)(java_version=11))"
62 | Component.20.2.0_macos_amd64.org.graalvm.jvmmathlang-x-GraalVM-Polyglot-Part=True
63 | Component.20.2.0_macos_amd64.org.graalvm.jvmmathlang-x-GraalVM-Working-Directories=languages/jvmmathlang
64 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.jyukutyo
6 | jvmmathlang
7 | 1.0.0
8 | jar
9 |
10 | jvmmathlang
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 | 11
16 | ${java.version}
17 | ${java.version}
18 | jvmmathlang
19 | 20.3.0
20 |
21 |
22 |
23 |
24 |
25 | org.apache.maven.plugins
26 | maven-compiler-plugin
27 | 3.8.1
28 |
29 |
30 | org.apache.maven.plugins
31 | maven-jar-plugin
32 | 3.2.0
33 |
34 | ${project.artifactId}
35 |
36 |
37 |
38 | org.apache.maven.plugins
39 | maven-assembly-plugin
40 | 3.3.0
41 |
42 |
43 | src/main/assembly/distribution.xml
44 |
45 |
46 |
47 | JVM Math Lang
48 | ${bundle.symbolic.name}
49 | ${project.version}
50 | org.graalvm; filter:="(java_version=11)"
51 | True
52 |
53 |
54 |
55 |
56 |
57 | make-assembly
58 | package
59 |
60 | single
61 |
62 |
63 |
64 |
65 |
66 | net.nicoulaj.maven.plugins
67 | checksum-maven-plugin
68 | 1.9
69 |
70 |
71 | SHA-256
72 |
73 |
74 |
75 | ${project.build.directory}
76 |
77 | ${project.artifactId}-${project.version}-component.jar
78 |
79 |
80 |
81 |
82 |
83 |
84 | package
85 |
86 | files
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | org.antlr
97 | antlr4-runtime
98 | 4.7
99 |
100 |
101 | org.graalvm.truffle
102 | truffle-api
103 | ${target.graalvm.version}
104 |
105 |
106 | org.graalvm.truffle
107 | truffle-dsl-processor
108 | ${target.graalvm.version}
109 | provided
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/src/main/assembly/distribution.xml:
--------------------------------------------------------------------------------
1 |
4 | component
5 |
6 | jar
7 |
8 | false
9 |
10 |
11 | languages${file.separator}${bundle.symbolic.name}
12 | ${project.build.directory}${file.separator}${project.artifactId}.jar
13 |
14 |
15 | languages${file.separator}${bundle.symbolic.name}
16 | ${project.basedir}${file.separator}src${file.separator}main${file.separator}assembly${file.separator}native-image.properties
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/assembly/native-image.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jyukutyo/JVM-Math-Language/b76c9cfa6de68f04aee1fb7979cacb1d6470f06a/src/main/assembly/native-image.properties
--------------------------------------------------------------------------------
/src/main/java/grammer/Math.g4:
--------------------------------------------------------------------------------
1 | grammar Math;
2 |
3 | prog
4 | : expr (EOF | NEWLINE)
5 | ;
6 |
7 |
8 | expr
9 | : '(' expr ')' #parensExpr
10 | | functionName '('argument? (',' argument)* ')' #invoke
11 | | '->' expr #asyncExpr
12 | | left=expr op=('*'|'/') right=expr #infixExpr
13 | | left=expr op=('+'|'-') right=expr #infixExpr
14 | | value=NUM #numberExpr
15 | ;
16 |
17 | functionName: ID;
18 | argument: expr;
19 |
20 | ID
21 | : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*
22 | ;
23 |
24 |
25 | OP_ADD: '+';
26 | OP_SUB: '-';
27 | OP_MUL: '*';
28 | OP_DIV: '/';
29 |
30 | NUM: [0-9]+ ('.' [0-9]+)?;
31 | WS: [ \t]+ -> skip;
32 | COMMA: ',';
33 |
34 | NEWLINE: '\r'? '\n';
--------------------------------------------------------------------------------
/src/main/java/grammer/Math.tokens:
--------------------------------------------------------------------------------
1 | T__0=1
2 | T__1=2
3 | T__2=3
4 | ID=4
5 | OP_ADD=5
6 | OP_SUB=6
7 | OP_MUL=7
8 | OP_DIV=8
9 | NUM=9
10 | WS=10
11 | COMMA=11
12 | NEWLINE=12
13 | '('=1
14 | ')'=2
15 | '->'=3
16 | '+'=5
17 | '-'=6
18 | '*'=7
19 | '/'=8
20 | ','=11
21 |
--------------------------------------------------------------------------------
/src/main/java/grammer/MathBaseListener.java:
--------------------------------------------------------------------------------
1 | // Generated from Math.g4 by ANTLR 4.7
2 | package grammer;
3 |
4 | import org.antlr.v4.runtime.ParserRuleContext;
5 | import org.antlr.v4.runtime.tree.ErrorNode;
6 | import org.antlr.v4.runtime.tree.TerminalNode;
7 |
8 | /**
9 | * This class provides an empty implementation of {@link MathListener},
10 | * which can be extended to create a listener which only needs to handle a subset
11 | * of the available methods.
12 | */
13 | public class MathBaseListener implements MathListener {
14 | /**
15 | * {@inheritDoc}
16 | *
17 | *
The default implementation does nothing.
18 | */
19 | @Override public void enterProg(MathParser.ProgContext ctx) { }
20 | /**
21 | * {@inheritDoc}
22 | *
23 | * The default implementation does nothing.
24 | */
25 | @Override public void exitProg(MathParser.ProgContext ctx) { }
26 | /**
27 | * {@inheritDoc}
28 | *
29 | * The default implementation does nothing.
30 | */
31 | @Override public void enterAsyncExpr(MathParser.AsyncExprContext ctx) { }
32 | /**
33 | * {@inheritDoc}
34 | *
35 | * The default implementation does nothing.
36 | */
37 | @Override public void exitAsyncExpr(MathParser.AsyncExprContext ctx) { }
38 | /**
39 | * {@inheritDoc}
40 | *
41 | * The default implementation does nothing.
42 | */
43 | @Override public void enterInfixExpr(MathParser.InfixExprContext ctx) { }
44 | /**
45 | * {@inheritDoc}
46 | *
47 | * The default implementation does nothing.
48 | */
49 | @Override public void exitInfixExpr(MathParser.InfixExprContext ctx) { }
50 | /**
51 | * {@inheritDoc}
52 | *
53 | * The default implementation does nothing.
54 | */
55 | @Override public void enterNumberExpr(MathParser.NumberExprContext ctx) { }
56 | /**
57 | * {@inheritDoc}
58 | *
59 | * The default implementation does nothing.
60 | */
61 | @Override public void exitNumberExpr(MathParser.NumberExprContext ctx) { }
62 | /**
63 | * {@inheritDoc}
64 | *
65 | * The default implementation does nothing.
66 | */
67 | @Override public void enterInvoke(MathParser.InvokeContext ctx) { }
68 | /**
69 | * {@inheritDoc}
70 | *
71 | * The default implementation does nothing.
72 | */
73 | @Override public void exitInvoke(MathParser.InvokeContext ctx) { }
74 | /**
75 | * {@inheritDoc}
76 | *
77 | * The default implementation does nothing.
78 | */
79 | @Override public void enterParensExpr(MathParser.ParensExprContext ctx) { }
80 | /**
81 | * {@inheritDoc}
82 | *
83 | * The default implementation does nothing.
84 | */
85 | @Override public void exitParensExpr(MathParser.ParensExprContext ctx) { }
86 | /**
87 | * {@inheritDoc}
88 | *
89 | * The default implementation does nothing.
90 | */
91 | @Override public void enterFunctionName(MathParser.FunctionNameContext ctx) { }
92 | /**
93 | * {@inheritDoc}
94 | *
95 | * The default implementation does nothing.
96 | */
97 | @Override public void exitFunctionName(MathParser.FunctionNameContext ctx) { }
98 | /**
99 | * {@inheritDoc}
100 | *
101 | * The default implementation does nothing.
102 | */
103 | @Override public void enterArgument(MathParser.ArgumentContext ctx) { }
104 | /**
105 | * {@inheritDoc}
106 | *
107 | * The default implementation does nothing.
108 | */
109 | @Override public void exitArgument(MathParser.ArgumentContext ctx) { }
110 |
111 | /**
112 | * {@inheritDoc}
113 | *
114 | * The default implementation does nothing.
115 | */
116 | @Override public void enterEveryRule(ParserRuleContext ctx) { }
117 | /**
118 | * {@inheritDoc}
119 | *
120 | * The default implementation does nothing.
121 | */
122 | @Override public void exitEveryRule(ParserRuleContext ctx) { }
123 | /**
124 | * {@inheritDoc}
125 | *
126 | * The default implementation does nothing.
127 | */
128 | @Override public void visitTerminal(TerminalNode node) { }
129 | /**
130 | * {@inheritDoc}
131 | *
132 | * The default implementation does nothing.
133 | */
134 | @Override public void visitErrorNode(ErrorNode node) { }
135 | }
--------------------------------------------------------------------------------
/src/main/java/grammer/MathLexer.java:
--------------------------------------------------------------------------------
1 | // Generated from Math.g4 by ANTLR 4.7
2 | package grammer;
3 | import org.antlr.v4.runtime.Lexer;
4 | import org.antlr.v4.runtime.CharStream;
5 | import org.antlr.v4.runtime.Token;
6 | import org.antlr.v4.runtime.TokenStream;
7 | import org.antlr.v4.runtime.*;
8 | import org.antlr.v4.runtime.atn.*;
9 | import org.antlr.v4.runtime.dfa.DFA;
10 | import org.antlr.v4.runtime.misc.*;
11 |
12 | @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
13 | public class MathLexer extends Lexer {
14 | static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
15 |
16 | protected static final DFA[] _decisionToDFA;
17 | protected static final PredictionContextCache _sharedContextCache =
18 | new PredictionContextCache();
19 | public static final int
20 | T__0=1, T__1=2, T__2=3, ID=4, OP_ADD=5, OP_SUB=6, OP_MUL=7, OP_DIV=8,
21 | NUM=9, WS=10, COMMA=11, NEWLINE=12;
22 | public static String[] channelNames = {
23 | "DEFAULT_TOKEN_CHANNEL", "HIDDEN"
24 | };
25 |
26 | public static String[] modeNames = {
27 | "DEFAULT_MODE"
28 | };
29 |
30 | public static final String[] ruleNames = {
31 | "T__0", "T__1", "T__2", "ID", "OP_ADD", "OP_SUB", "OP_MUL", "OP_DIV",
32 | "NUM", "WS", "COMMA", "NEWLINE"
33 | };
34 |
35 | private static final String[] _LITERAL_NAMES = {
36 | null, "'('", "')'", "'->'", null, "'+'", "'-'", "'*'", "'/'", null, null,
37 | "','"
38 | };
39 | private static final String[] _SYMBOLIC_NAMES = {
40 | null, null, null, null, "ID", "OP_ADD", "OP_SUB", "OP_MUL", "OP_DIV",
41 | "NUM", "WS", "COMMA", "NEWLINE"
42 | };
43 | public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
44 |
45 | /**
46 | * @deprecated Use {@link #VOCABULARY} instead.
47 | */
48 | @Deprecated
49 | public static final String[] tokenNames;
50 | static {
51 | tokenNames = new String[_SYMBOLIC_NAMES.length];
52 | for (int i = 0; i < tokenNames.length; i++) {
53 | tokenNames[i] = VOCABULARY.getLiteralName(i);
54 | if (tokenNames[i] == null) {
55 | tokenNames[i] = VOCABULARY.getSymbolicName(i);
56 | }
57 |
58 | if (tokenNames[i] == null) {
59 | tokenNames[i] = "";
60 | }
61 | }
62 | }
63 |
64 | @Override
65 | @Deprecated
66 | public String[] getTokenNames() {
67 | return tokenNames;
68 | }
69 |
70 | @Override
71 |
72 | public Vocabulary getVocabulary() {
73 | return VOCABULARY;
74 | }
75 |
76 |
77 | public MathLexer(CharStream input) {
78 | super(input);
79 | _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
80 | }
81 |
82 | @Override
83 | public String getGrammarFileName() { return "Math.g4"; }
84 |
85 | @Override
86 | public String[] getRuleNames() { return ruleNames; }
87 |
88 | @Override
89 | public String getSerializedATN() { return _serializedATN; }
90 |
91 | @Override
92 | public String[] getChannelNames() { return channelNames; }
93 |
94 | @Override
95 | public String[] getModeNames() { return modeNames; }
96 |
97 | @Override
98 | public ATN getATN() { return _ATN; }
99 |
100 | public static final String _serializedATN =
101 | "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\16L\b\1\4\2\t\2\4"+
102 | "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+
103 | "\13\4\f\t\f\4\r\t\r\3\2\3\2\3\3\3\3\3\4\3\4\3\4\3\5\3\5\7\5%\n\5\f\5\16"+
104 | "\5(\13\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\6\n\63\n\n\r\n\16\n\64\3"+
105 | "\n\3\n\6\n9\n\n\r\n\16\n:\5\n=\n\n\3\13\6\13@\n\13\r\13\16\13A\3\13\3"+
106 | "\13\3\f\3\f\3\r\5\rI\n\r\3\r\3\r\2\2\16\3\3\5\4\7\5\t\6\13\7\r\b\17\t"+
107 | "\21\n\23\13\25\f\27\r\31\16\3\2\6\5\2C\\aac|\6\2\62;C\\aac|\3\2\62;\4"+
108 | "\2\13\13\"\"\2Q\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3"+
109 | "\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2"+
110 | "\2\27\3\2\2\2\2\31\3\2\2\2\3\33\3\2\2\2\5\35\3\2\2\2\7\37\3\2\2\2\t\""+
111 | "\3\2\2\2\13)\3\2\2\2\r+\3\2\2\2\17-\3\2\2\2\21/\3\2\2\2\23\62\3\2\2\2"+
112 | "\25?\3\2\2\2\27E\3\2\2\2\31H\3\2\2\2\33\34\7*\2\2\34\4\3\2\2\2\35\36\7"+
113 | "+\2\2\36\6\3\2\2\2\37 \7/\2\2 !\7@\2\2!\b\3\2\2\2\"&\t\2\2\2#%\t\3\2\2"+
114 | "$#\3\2\2\2%(\3\2\2\2&$\3\2\2\2&\'\3\2\2\2\'\n\3\2\2\2(&\3\2\2\2)*\7-\2"+
115 | "\2*\f\3\2\2\2+,\7/\2\2,\16\3\2\2\2-.\7,\2\2.\20\3\2\2\2/\60\7\61\2\2\60"+
116 | "\22\3\2\2\2\61\63\t\4\2\2\62\61\3\2\2\2\63\64\3\2\2\2\64\62\3\2\2\2\64"+
117 | "\65\3\2\2\2\65<\3\2\2\2\668\7\60\2\2\679\t\4\2\28\67\3\2\2\29:\3\2\2\2"+
118 | ":8\3\2\2\2:;\3\2\2\2;=\3\2\2\2<\66\3\2\2\2<=\3\2\2\2=\24\3\2\2\2>@\t\5"+
119 | "\2\2?>\3\2\2\2@A\3\2\2\2A?\3\2\2\2AB\3\2\2\2BC\3\2\2\2CD\b\13\2\2D\26"+
120 | "\3\2\2\2EF\7.\2\2F\30\3\2\2\2GI\7\17\2\2HG\3\2\2\2HI\3\2\2\2IJ\3\2\2\2"+
121 | "JK\7\f\2\2K\32\3\2\2\2\t\2&\64:'=3
16 | '+'=5
17 | '-'=6
18 | '*'=7
19 | '/'=8
20 | ','=11
21 |
--------------------------------------------------------------------------------
/src/main/java/grammer/MathListener.java:
--------------------------------------------------------------------------------
1 | // Generated from Math.g4 by ANTLR 4.7
2 | package grammer;
3 | import org.antlr.v4.runtime.tree.ParseTreeListener;
4 |
5 | /**
6 | * This interface defines a complete listener for a parse tree produced by
7 | * {@link MathParser}.
8 | */
9 | public interface MathListener extends ParseTreeListener {
10 | /**
11 | * Enter a parse tree produced by {@link MathParser#prog}.
12 | * @param ctx the parse tree
13 | */
14 | void enterProg(MathParser.ProgContext ctx);
15 | /**
16 | * Exit a parse tree produced by {@link MathParser#prog}.
17 | * @param ctx the parse tree
18 | */
19 | void exitProg(MathParser.ProgContext ctx);
20 | /**
21 | * Enter a parse tree produced by the {@code asyncExpr}
22 | * labeled alternative in {@link MathParser#expr}.
23 | * @param ctx the parse tree
24 | */
25 | void enterAsyncExpr(MathParser.AsyncExprContext ctx);
26 | /**
27 | * Exit a parse tree produced by the {@code asyncExpr}
28 | * labeled alternative in {@link MathParser#expr}.
29 | * @param ctx the parse tree
30 | */
31 | void exitAsyncExpr(MathParser.AsyncExprContext ctx);
32 | /**
33 | * Enter a parse tree produced by the {@code infixExpr}
34 | * labeled alternative in {@link MathParser#expr}.
35 | * @param ctx the parse tree
36 | */
37 | void enterInfixExpr(MathParser.InfixExprContext ctx);
38 | /**
39 | * Exit a parse tree produced by the {@code infixExpr}
40 | * labeled alternative in {@link MathParser#expr}.
41 | * @param ctx the parse tree
42 | */
43 | void exitInfixExpr(MathParser.InfixExprContext ctx);
44 | /**
45 | * Enter a parse tree produced by the {@code numberExpr}
46 | * labeled alternative in {@link MathParser#expr}.
47 | * @param ctx the parse tree
48 | */
49 | void enterNumberExpr(MathParser.NumberExprContext ctx);
50 | /**
51 | * Exit a parse tree produced by the {@code numberExpr}
52 | * labeled alternative in {@link MathParser#expr}.
53 | * @param ctx the parse tree
54 | */
55 | void exitNumberExpr(MathParser.NumberExprContext ctx);
56 | /**
57 | * Enter a parse tree produced by the {@code invoke}
58 | * labeled alternative in {@link MathParser#expr}.
59 | * @param ctx the parse tree
60 | */
61 | void enterInvoke(MathParser.InvokeContext ctx);
62 | /**
63 | * Exit a parse tree produced by the {@code invoke}
64 | * labeled alternative in {@link MathParser#expr}.
65 | * @param ctx the parse tree
66 | */
67 | void exitInvoke(MathParser.InvokeContext ctx);
68 | /**
69 | * Enter a parse tree produced by the {@code parensExpr}
70 | * labeled alternative in {@link MathParser#expr}.
71 | * @param ctx the parse tree
72 | */
73 | void enterParensExpr(MathParser.ParensExprContext ctx);
74 | /**
75 | * Exit a parse tree produced by the {@code parensExpr}
76 | * labeled alternative in {@link MathParser#expr}.
77 | * @param ctx the parse tree
78 | */
79 | void exitParensExpr(MathParser.ParensExprContext ctx);
80 | /**
81 | * Enter a parse tree produced by {@link MathParser#functionName}.
82 | * @param ctx the parse tree
83 | */
84 | void enterFunctionName(MathParser.FunctionNameContext ctx);
85 | /**
86 | * Exit a parse tree produced by {@link MathParser#functionName}.
87 | * @param ctx the parse tree
88 | */
89 | void exitFunctionName(MathParser.FunctionNameContext ctx);
90 | /**
91 | * Enter a parse tree produced by {@link MathParser#argument}.
92 | * @param ctx the parse tree
93 | */
94 | void enterArgument(MathParser.ArgumentContext ctx);
95 | /**
96 | * Exit a parse tree produced by {@link MathParser#argument}.
97 | * @param ctx the parse tree
98 | */
99 | void exitArgument(MathParser.ArgumentContext ctx);
100 | }
--------------------------------------------------------------------------------
/src/main/java/grammer/MathParser.java:
--------------------------------------------------------------------------------
1 | // Generated from Math.g4 by ANTLR 4.7
2 | package grammer;
3 | import org.antlr.v4.runtime.atn.*;
4 | import org.antlr.v4.runtime.dfa.DFA;
5 | import org.antlr.v4.runtime.*;
6 | import org.antlr.v4.runtime.misc.*;
7 | import org.antlr.v4.runtime.tree.*;
8 | import java.util.List;
9 | import java.util.Iterator;
10 | import java.util.ArrayList;
11 |
12 | @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
13 | public class MathParser extends Parser {
14 | static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
15 |
16 | protected static final DFA[] _decisionToDFA;
17 | protected static final PredictionContextCache _sharedContextCache =
18 | new PredictionContextCache();
19 | public static final int
20 | T__0=1, T__1=2, T__2=3, ID=4, OP_ADD=5, OP_SUB=6, OP_MUL=7, OP_DIV=8,
21 | NUM=9, WS=10, COMMA=11, NEWLINE=12;
22 | public static final int
23 | RULE_prog = 0, RULE_expr = 1, RULE_functionName = 2, RULE_argument = 3;
24 | public static final String[] ruleNames = {
25 | "prog", "expr", "functionName", "argument"
26 | };
27 |
28 | private static final String[] _LITERAL_NAMES = {
29 | null, "'('", "')'", "'->'", null, "'+'", "'-'", "'*'", "'/'", null, null,
30 | "','"
31 | };
32 | private static final String[] _SYMBOLIC_NAMES = {
33 | null, null, null, null, "ID", "OP_ADD", "OP_SUB", "OP_MUL", "OP_DIV",
34 | "NUM", "WS", "COMMA", "NEWLINE"
35 | };
36 | public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
37 |
38 | /**
39 | * @deprecated Use {@link #VOCABULARY} instead.
40 | */
41 | @Deprecated
42 | public static final String[] tokenNames;
43 | static {
44 | tokenNames = new String[_SYMBOLIC_NAMES.length];
45 | for (int i = 0; i < tokenNames.length; i++) {
46 | tokenNames[i] = VOCABULARY.getLiteralName(i);
47 | if (tokenNames[i] == null) {
48 | tokenNames[i] = VOCABULARY.getSymbolicName(i);
49 | }
50 |
51 | if (tokenNames[i] == null) {
52 | tokenNames[i] = "";
53 | }
54 | }
55 | }
56 |
57 | @Override
58 | @Deprecated
59 | public String[] getTokenNames() {
60 | return tokenNames;
61 | }
62 |
63 | @Override
64 |
65 | public Vocabulary getVocabulary() {
66 | return VOCABULARY;
67 | }
68 |
69 | @Override
70 | public String getGrammarFileName() { return "Math.g4"; }
71 |
72 | @Override
73 | public String[] getRuleNames() { return ruleNames; }
74 |
75 | @Override
76 | public String getSerializedATN() { return _serializedATN; }
77 |
78 | @Override
79 | public ATN getATN() { return _ATN; }
80 |
81 | public MathParser(TokenStream input) {
82 | super(input);
83 | _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
84 | }
85 | public static class ProgContext extends ParserRuleContext {
86 | public ExprContext expr() {
87 | return getRuleContext(ExprContext.class,0);
88 | }
89 | public TerminalNode EOF() { return getToken(MathParser.EOF, 0); }
90 | public TerminalNode NEWLINE() { return getToken(MathParser.NEWLINE, 0); }
91 | public ProgContext(ParserRuleContext parent, int invokingState) {
92 | super(parent, invokingState);
93 | }
94 | @Override public int getRuleIndex() { return RULE_prog; }
95 | @Override
96 | public void enterRule(ParseTreeListener listener) {
97 | if ( listener instanceof MathListener ) ((MathListener)listener).enterProg(this);
98 | }
99 | @Override
100 | public void exitRule(ParseTreeListener listener) {
101 | if ( listener instanceof MathListener ) ((MathListener)listener).exitProg(this);
102 | }
103 | }
104 |
105 | public final ProgContext prog() throws RecognitionException {
106 | ProgContext _localctx = new ProgContext(_ctx, getState());
107 | enterRule(_localctx, 0, RULE_prog);
108 | int _la;
109 | try {
110 | enterOuterAlt(_localctx, 1);
111 | {
112 | setState(8);
113 | expr(0);
114 | setState(9);
115 | _la = _input.LA(1);
116 | if ( !(_la==EOF || _la==NEWLINE) ) {
117 | _errHandler.recoverInline(this);
118 | }
119 | else {
120 | if ( _input.LA(1)==Token.EOF ) matchedEOF = true;
121 | _errHandler.reportMatch(this);
122 | consume();
123 | }
124 | }
125 | }
126 | catch (RecognitionException re) {
127 | _localctx.exception = re;
128 | _errHandler.reportError(this, re);
129 | _errHandler.recover(this, re);
130 | }
131 | finally {
132 | exitRule();
133 | }
134 | return _localctx;
135 | }
136 |
137 | public static class ExprContext extends ParserRuleContext {
138 | public ExprContext(ParserRuleContext parent, int invokingState) {
139 | super(parent, invokingState);
140 | }
141 | @Override public int getRuleIndex() { return RULE_expr; }
142 |
143 | public ExprContext() { }
144 | public void copyFrom(ExprContext ctx) {
145 | super.copyFrom(ctx);
146 | }
147 | }
148 | public static class AsyncExprContext extends ExprContext {
149 | public ExprContext expr() {
150 | return getRuleContext(ExprContext.class,0);
151 | }
152 | public AsyncExprContext(ExprContext ctx) { copyFrom(ctx); }
153 | @Override
154 | public void enterRule(ParseTreeListener listener) {
155 | if ( listener instanceof MathListener ) ((MathListener)listener).enterAsyncExpr(this);
156 | }
157 | @Override
158 | public void exitRule(ParseTreeListener listener) {
159 | if ( listener instanceof MathListener ) ((MathListener)listener).exitAsyncExpr(this);
160 | }
161 | }
162 | public static class InfixExprContext extends ExprContext {
163 | public ExprContext left;
164 | public Token op;
165 | public ExprContext right;
166 | public List expr() {
167 | return getRuleContexts(ExprContext.class);
168 | }
169 | public ExprContext expr(int i) {
170 | return getRuleContext(ExprContext.class,i);
171 | }
172 | public InfixExprContext(ExprContext ctx) { copyFrom(ctx); }
173 | @Override
174 | public void enterRule(ParseTreeListener listener) {
175 | if ( listener instanceof MathListener ) ((MathListener)listener).enterInfixExpr(this);
176 | }
177 | @Override
178 | public void exitRule(ParseTreeListener listener) {
179 | if ( listener instanceof MathListener ) ((MathListener)listener).exitInfixExpr(this);
180 | }
181 | }
182 | public static class NumberExprContext extends ExprContext {
183 | public Token value;
184 | public TerminalNode NUM() { return getToken(MathParser.NUM, 0); }
185 | public NumberExprContext(ExprContext ctx) { copyFrom(ctx); }
186 | @Override
187 | public void enterRule(ParseTreeListener listener) {
188 | if ( listener instanceof MathListener ) ((MathListener)listener).enterNumberExpr(this);
189 | }
190 | @Override
191 | public void exitRule(ParseTreeListener listener) {
192 | if ( listener instanceof MathListener ) ((MathListener)listener).exitNumberExpr(this);
193 | }
194 | }
195 | public static class InvokeContext extends ExprContext {
196 | public FunctionNameContext functionName() {
197 | return getRuleContext(FunctionNameContext.class,0);
198 | }
199 | public List argument() {
200 | return getRuleContexts(ArgumentContext.class);
201 | }
202 | public ArgumentContext argument(int i) {
203 | return getRuleContext(ArgumentContext.class,i);
204 | }
205 | public InvokeContext(ExprContext ctx) { copyFrom(ctx); }
206 | @Override
207 | public void enterRule(ParseTreeListener listener) {
208 | if ( listener instanceof MathListener ) ((MathListener)listener).enterInvoke(this);
209 | }
210 | @Override
211 | public void exitRule(ParseTreeListener listener) {
212 | if ( listener instanceof MathListener ) ((MathListener)listener).exitInvoke(this);
213 | }
214 | }
215 | public static class ParensExprContext extends ExprContext {
216 | public ExprContext expr() {
217 | return getRuleContext(ExprContext.class,0);
218 | }
219 | public ParensExprContext(ExprContext ctx) { copyFrom(ctx); }
220 | @Override
221 | public void enterRule(ParseTreeListener listener) {
222 | if ( listener instanceof MathListener ) ((MathListener)listener).enterParensExpr(this);
223 | }
224 | @Override
225 | public void exitRule(ParseTreeListener listener) {
226 | if ( listener instanceof MathListener ) ((MathListener)listener).exitParensExpr(this);
227 | }
228 | }
229 |
230 | public final ExprContext expr() throws RecognitionException {
231 | return expr(0);
232 | }
233 |
234 | private ExprContext expr(int _p) throws RecognitionException {
235 | ParserRuleContext _parentctx = _ctx;
236 | int _parentState = getState();
237 | ExprContext _localctx = new ExprContext(_ctx, _parentState);
238 | ExprContext _prevctx = _localctx;
239 | int _startState = 2;
240 | enterRecursionRule(_localctx, 2, RULE_expr, _p);
241 | int _la;
242 | try {
243 | int _alt;
244 | enterOuterAlt(_localctx, 1);
245 | {
246 | setState(33);
247 | _errHandler.sync(this);
248 | switch (_input.LA(1)) {
249 | case T__0:
250 | {
251 | _localctx = new ParensExprContext(_localctx);
252 | _ctx = _localctx;
253 | _prevctx = _localctx;
254 |
255 | setState(12);
256 | match(T__0);
257 | setState(13);
258 | expr(0);
259 | setState(14);
260 | match(T__1);
261 | }
262 | break;
263 | case ID:
264 | {
265 | _localctx = new InvokeContext(_localctx);
266 | _ctx = _localctx;
267 | _prevctx = _localctx;
268 | setState(16);
269 | functionName();
270 | setState(17);
271 | match(T__0);
272 | setState(19);
273 | _errHandler.sync(this);
274 | _la = _input.LA(1);
275 | if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__2) | (1L << ID) | (1L << NUM))) != 0)) {
276 | {
277 | setState(18);
278 | argument();
279 | }
280 | }
281 |
282 | setState(25);
283 | _errHandler.sync(this);
284 | _la = _input.LA(1);
285 | while (_la==COMMA) {
286 | {
287 | {
288 | setState(21);
289 | match(COMMA);
290 | setState(22);
291 | argument();
292 | }
293 | }
294 | setState(27);
295 | _errHandler.sync(this);
296 | _la = _input.LA(1);
297 | }
298 | setState(28);
299 | match(T__1);
300 | }
301 | break;
302 | case T__2:
303 | {
304 | _localctx = new AsyncExprContext(_localctx);
305 | _ctx = _localctx;
306 | _prevctx = _localctx;
307 | setState(30);
308 | match(T__2);
309 | setState(31);
310 | expr(4);
311 | }
312 | break;
313 | case NUM:
314 | {
315 | _localctx = new NumberExprContext(_localctx);
316 | _ctx = _localctx;
317 | _prevctx = _localctx;
318 | setState(32);
319 | ((NumberExprContext)_localctx).value = match(NUM);
320 | }
321 | break;
322 | default:
323 | throw new NoViableAltException(this);
324 | }
325 | _ctx.stop = _input.LT(-1);
326 | setState(43);
327 | _errHandler.sync(this);
328 | _alt = getInterpreter().adaptivePredict(_input,4,_ctx);
329 | while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
330 | if ( _alt==1 ) {
331 | if ( _parseListeners!=null ) triggerExitRuleEvent();
332 | _prevctx = _localctx;
333 | {
334 | setState(41);
335 | _errHandler.sync(this);
336 | switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) {
337 | case 1:
338 | {
339 | _localctx = new InfixExprContext(new ExprContext(_parentctx, _parentState));
340 | ((InfixExprContext)_localctx).left = _prevctx;
341 | pushNewRecursionContext(_localctx, _startState, RULE_expr);
342 | setState(35);
343 | if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)");
344 | setState(36);
345 | ((InfixExprContext)_localctx).op = _input.LT(1);
346 | _la = _input.LA(1);
347 | if ( !(_la==OP_MUL || _la==OP_DIV) ) {
348 | ((InfixExprContext)_localctx).op = (Token)_errHandler.recoverInline(this);
349 | }
350 | else {
351 | if ( _input.LA(1)==Token.EOF ) matchedEOF = true;
352 | _errHandler.reportMatch(this);
353 | consume();
354 | }
355 | setState(37);
356 | ((InfixExprContext)_localctx).right = expr(4);
357 | }
358 | break;
359 | case 2:
360 | {
361 | _localctx = new InfixExprContext(new ExprContext(_parentctx, _parentState));
362 | ((InfixExprContext)_localctx).left = _prevctx;
363 | pushNewRecursionContext(_localctx, _startState, RULE_expr);
364 | setState(38);
365 | if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
366 | setState(39);
367 | ((InfixExprContext)_localctx).op = _input.LT(1);
368 | _la = _input.LA(1);
369 | if ( !(_la==OP_ADD || _la==OP_SUB) ) {
370 | ((InfixExprContext)_localctx).op = (Token)_errHandler.recoverInline(this);
371 | }
372 | else {
373 | if ( _input.LA(1)==Token.EOF ) matchedEOF = true;
374 | _errHandler.reportMatch(this);
375 | consume();
376 | }
377 | setState(40);
378 | ((InfixExprContext)_localctx).right = expr(3);
379 | }
380 | break;
381 | }
382 | }
383 | }
384 | setState(45);
385 | _errHandler.sync(this);
386 | _alt = getInterpreter().adaptivePredict(_input,4,_ctx);
387 | }
388 | }
389 | }
390 | catch (RecognitionException re) {
391 | _localctx.exception = re;
392 | _errHandler.reportError(this, re);
393 | _errHandler.recover(this, re);
394 | }
395 | finally {
396 | unrollRecursionContexts(_parentctx);
397 | }
398 | return _localctx;
399 | }
400 |
401 | public static class FunctionNameContext extends ParserRuleContext {
402 | public TerminalNode ID() { return getToken(MathParser.ID, 0); }
403 | public FunctionNameContext(ParserRuleContext parent, int invokingState) {
404 | super(parent, invokingState);
405 | }
406 | @Override public int getRuleIndex() { return RULE_functionName; }
407 | @Override
408 | public void enterRule(ParseTreeListener listener) {
409 | if ( listener instanceof MathListener ) ((MathListener)listener).enterFunctionName(this);
410 | }
411 | @Override
412 | public void exitRule(ParseTreeListener listener) {
413 | if ( listener instanceof MathListener ) ((MathListener)listener).exitFunctionName(this);
414 | }
415 | }
416 |
417 | public final FunctionNameContext functionName() throws RecognitionException {
418 | FunctionNameContext _localctx = new FunctionNameContext(_ctx, getState());
419 | enterRule(_localctx, 4, RULE_functionName);
420 | try {
421 | enterOuterAlt(_localctx, 1);
422 | {
423 | setState(46);
424 | match(ID);
425 | }
426 | }
427 | catch (RecognitionException re) {
428 | _localctx.exception = re;
429 | _errHandler.reportError(this, re);
430 | _errHandler.recover(this, re);
431 | }
432 | finally {
433 | exitRule();
434 | }
435 | return _localctx;
436 | }
437 |
438 | public static class ArgumentContext extends ParserRuleContext {
439 | public ExprContext expr() {
440 | return getRuleContext(ExprContext.class,0);
441 | }
442 | public ArgumentContext(ParserRuleContext parent, int invokingState) {
443 | super(parent, invokingState);
444 | }
445 | @Override public int getRuleIndex() { return RULE_argument; }
446 | @Override
447 | public void enterRule(ParseTreeListener listener) {
448 | if ( listener instanceof MathListener ) ((MathListener)listener).enterArgument(this);
449 | }
450 | @Override
451 | public void exitRule(ParseTreeListener listener) {
452 | if ( listener instanceof MathListener ) ((MathListener)listener).exitArgument(this);
453 | }
454 | }
455 |
456 | public final ArgumentContext argument() throws RecognitionException {
457 | ArgumentContext _localctx = new ArgumentContext(_ctx, getState());
458 | enterRule(_localctx, 6, RULE_argument);
459 | try {
460 | enterOuterAlt(_localctx, 1);
461 | {
462 | setState(48);
463 | expr(0);
464 | }
465 | }
466 | catch (RecognitionException re) {
467 | _localctx.exception = re;
468 | _errHandler.reportError(this, re);
469 | _errHandler.recover(this, re);
470 | }
471 | finally {
472 | exitRule();
473 | }
474 | return _localctx;
475 | }
476 |
477 | public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
478 | switch (ruleIndex) {
479 | case 1:
480 | return expr_sempred((ExprContext)_localctx, predIndex);
481 | }
482 | return true;
483 | }
484 | private boolean expr_sempred(ExprContext _localctx, int predIndex) {
485 | switch (predIndex) {
486 | case 0:
487 | return precpred(_ctx, 3);
488 | case 1:
489 | return precpred(_ctx, 2);
490 | }
491 | return true;
492 | }
493 |
494 | public static final String _serializedATN =
495 | "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\16\65\4\2\t\2\4\3"+
496 | "\t\3\4\4\t\4\4\5\t\5\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\5\3\26"+
497 | "\n\3\3\3\3\3\7\3\32\n\3\f\3\16\3\35\13\3\3\3\3\3\3\3\3\3\3\3\5\3$\n\3"+
498 | "\3\3\3\3\3\3\3\3\3\3\3\3\7\3,\n\3\f\3\16\3/\13\3\3\4\3\4\3\5\3\5\3\5\2"+
499 | "\3\4\6\2\4\6\b\2\5\3\3\16\16\3\2\t\n\3\2\7\b\2\67\2\n\3\2\2\2\4#\3\2\2"+
500 | "\2\6\60\3\2\2\2\b\62\3\2\2\2\n\13\5\4\3\2\13\f\t\2\2\2\f\3\3\2\2\2\r\16"+
501 | "\b\3\1\2\16\17\7\3\2\2\17\20\5\4\3\2\20\21\7\4\2\2\21$\3\2\2\2\22\23\5"+
502 | "\6\4\2\23\25\7\3\2\2\24\26\5\b\5\2\25\24\3\2\2\2\25\26\3\2\2\2\26\33\3"+
503 | "\2\2\2\27\30\7\r\2\2\30\32\5\b\5\2\31\27\3\2\2\2\32\35\3\2\2\2\33\31\3"+
504 | "\2\2\2\33\34\3\2\2\2\34\36\3\2\2\2\35\33\3\2\2\2\36\37\7\4\2\2\37$\3\2"+
505 | "\2\2 !\7\5\2\2!$\5\4\3\6\"$\7\13\2\2#\r\3\2\2\2#\22\3\2\2\2# \3\2\2\2"+
506 | "#\"\3\2\2\2$-\3\2\2\2%&\f\5\2\2&\'\t\3\2\2\',\5\4\3\6()\f\4\2\2)*\t\4"+
507 | "\2\2*,\5\4\3\5+%\3\2\2\2+(\3\2\2\2,/\3\2\2\2-+\3\2\2\2-.\3\2\2\2.\5\3"+
508 | "\2\2\2/-\3\2\2\2\60\61\7\6\2\2\61\7\3\2\2\2\62\63\5\4\3\2\63\t\3\2\2\2"+
509 | "\7\25\33#+-";
510 | public static final ATN _ATN =
511 | new ATNDeserializer().deserialize(_serializedATN.toCharArray());
512 | static {
513 | _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
514 | for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
515 | _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
516 | }
517 | }
518 | }
--------------------------------------------------------------------------------
/src/main/java/jvmmathlang/truffle/JvmMathLang.java:
--------------------------------------------------------------------------------
1 | package jvmmathlang.truffle;
2 |
3 | import java.io.IOException;
4 | import java.nio.ByteBuffer;
5 |
6 | import com.oracle.truffle.api.CallTarget;
7 | import com.oracle.truffle.api.Truffle;
8 | import com.oracle.truffle.api.TruffleLanguage;
9 | import com.oracle.truffle.api.source.Source;
10 | import grammer.MathLexer;
11 | import grammer.MathParser;
12 | import nodes.JvmMathLangRootNode;
13 | import org.antlr.v4.runtime.CharStream;
14 | import org.antlr.v4.runtime.CodePointBuffer;
15 | import org.antlr.v4.runtime.CodePointCharStream;
16 | import org.antlr.v4.runtime.CommonTokenStream;
17 | import org.antlr.v4.runtime.tree.ParseTreeWalker;
18 |
19 | /**
20 | * run code with ANTLR and Truffle.
21 | */
22 | @TruffleLanguage.Registration(
23 | id = "jvmmathlang",
24 | name = "JVM Math Language",
25 | version = "0.0.2")
26 | public class JvmMathLang extends TruffleLanguage {
27 |
28 | @Override
29 | protected JvmMathLangContext createContext(Env env) {
30 | return new JvmMathLangContext();
31 | }
32 |
33 | @Override
34 | protected CallTarget parse(ParsingRequest request) throws Exception {
35 | JvmMathLangRootNode main = parseSource(request.getSource());
36 | return Truffle.getRuntime().createCallTarget(main);
37 | }
38 |
39 | private JvmMathLangRootNode parseSource(Source source) throws IOException {
40 | // get user input
41 | String input = source.getCharacters().toString();
42 |
43 | System.out.println("inputed String: " + input);
44 |
45 | // convert user input to ANTLR character stream
46 | // java.lang.UnsupportedOperationException causes when use CharBuffer
47 | CharStream charStream = CodePointCharStream.fromBuffer(
48 | CodePointBuffer.withBytes(
49 | ByteBuffer.wrap(
50 | input.getBytes())));
51 |
52 | // lexing
53 | MathLexer mathLexer = new MathLexer(charStream);
54 | CommonTokenStream tokenStream = new CommonTokenStream(mathLexer);
55 |
56 | // parsing
57 | MathParser mathParser = new MathParser(tokenStream);
58 | MathParser.ProgContext prog = mathParser.prog();
59 |
60 | // creates Truffle nodes from ANTLR parse result
61 | ParseTreeWalker treeWalker = new ParseTreeWalker();
62 | MathParseTreeListener listener = new MathParseTreeListener();
63 | treeWalker.walk(listener, prog);
64 |
65 | return listener.getRoot(this);
66 | }
67 |
68 | protected boolean isObjectOfLanguage(Object object) {
69 | // return true if this language can deal with such object in "native way"
70 | return false;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/jvmmathlang/truffle/JvmMathLangContext.java:
--------------------------------------------------------------------------------
1 | package jvmmathlang.truffle;
2 |
3 | public class JvmMathLangContext {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/jvmmathlang/truffle/JvmMathLangMain.java:
--------------------------------------------------------------------------------
1 | package jvmmathlang.truffle;
2 |
3 | import java.io.IOException;
4 | import java.util.Scanner;
5 |
6 | import com.oracle.truffle.api.Truffle;
7 | import org.graalvm.polyglot.Context;
8 | import org.graalvm.polyglot.Source;
9 | import org.graalvm.polyglot.Value;
10 |
11 | /**
12 | * Main class.
13 | *
14 | *
15 | * waiting for user input.
16 | *
17 | */
18 | public class JvmMathLangMain {
19 |
20 | public static void main(String[] args) throws IOException {
21 | System.out.println("Truffle runtime: " + Truffle.getRuntime().getName());
22 |
23 | Context context = Context.create("jvmmathlang");
24 | context.getEngine().getLanguages().forEach((s, l) -> System.out.println("Language: " + l.getName()));
25 |
26 | try (Scanner s = new Scanner(System.in)) {
27 | while (true) {
28 | System.out.print("> ");
29 | String program = s.nextLine().trim();
30 |
31 | if (program.equalsIgnoreCase("quit")) {
32 | break;
33 | }
34 |
35 | Object answer = runCode(context, program);
36 | System.out.println("answer: " + answer);
37 | System.out.println();
38 | }
39 | }
40 | }
41 |
42 | private static Object runCode(Context context, String program) throws IOException {
43 | Source source = Source.newBuilder("jvmmathlang", program, "MATH").build();
44 | Value value = context.eval(source);
45 | return value;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/jvmmathlang/truffle/JvmMathLangTypes.java:
--------------------------------------------------------------------------------
1 | package jvmmathlang.truffle;
2 |
3 | import com.oracle.truffle.api.dsl.TypeSystem;
4 |
5 | /**
6 | * Type definition.
7 | *
8 | *
9 | * define only long so others are treated as general type.
10 | *
11 | */
12 | @TypeSystem(long.class)
13 | public abstract class JvmMathLangTypes {
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/jvmmathlang/truffle/MathParseTreeListener.java:
--------------------------------------------------------------------------------
1 | package jvmmathlang.truffle;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.LinkedList;
5 |
6 | import com.oracle.truffle.api.frame.FrameDescriptor;
7 | import grammer.MathBaseListener;
8 | import grammer.MathLexer;
9 | import grammer.MathParser;
10 | import nodes.AsyncJvmMathLangNode;
11 | import nodes.JvmMathLangNode;
12 | import nodes.JvmMathLangRootNode;
13 | import nodes.ParenJvmMathLangNode;
14 | import nodes.literal.BigDecimalNode;
15 | import nodes.literal.LongNode;
16 |
17 | /**
18 | * Truffle nodes creator.
19 | */
20 | public class MathParseTreeListener extends MathBaseListener {
21 |
22 | private JvmMathLangNode node;
23 |
24 | private LinkedList mathLangNodes = new LinkedList<>();
25 |
26 | @Override
27 | public void exitNumberExpr(MathParser.NumberExprContext ctx) {
28 | String text = ctx.value.getText();
29 | try {
30 | mathLangNodes.push(new LongNode(Long.parseLong(text)));
31 | } catch(NumberFormatException e) {
32 | mathLangNodes.push(new BigDecimalNode(new BigDecimal(text)));
33 | }
34 | }
35 |
36 | @Override
37 | public void exitInfixExpr(MathParser.InfixExprContext ctx) {
38 | JvmMathLangNode right = mathLangNodes.pop();
39 | JvmMathLangNode left = mathLangNodes.pop();
40 |
41 | JvmMathLangNode current = null;
42 | switch (ctx.op.getType()) {
43 | case MathLexer.OP_ADD:
44 | current = nodes.ops.AddNodeGen.create(left, right);
45 | break;
46 | case MathLexer.OP_DIV:
47 | current = nodes.ops.DivNodeGen.create(left, right);
48 | break;
49 | case MathLexer.OP_MUL:
50 | current = nodes.ops.MulNodeGen.create(left, right);
51 | break;
52 | case MathLexer.OP_SUB:
53 | current = nodes.ops.SubNodeGen.create(left, right);
54 | break;
55 | }
56 | mathLangNodes.push(current);
57 | }
58 |
59 | @Override
60 | public void exitParensExpr(MathParser.ParensExprContext ctx) {
61 | mathLangNodes.push(new ParenJvmMathLangNode(mathLangNodes.pop()));
62 | }
63 |
64 | @Override
65 | public void exitAsyncExpr(MathParser.AsyncExprContext ctx) {
66 | mathLangNodes.push(new AsyncJvmMathLangNode(mathLangNodes.pop()));
67 | }
68 |
69 | @Override
70 | public void exitProg(MathParser.ProgContext ctx) {
71 | node = mathLangNodes.pop();
72 | }
73 |
74 | public JvmMathLangRootNode getRoot(JvmMathLang jvmMathLang) {
75 | return new JvmMathLangRootNode(jvmMathLang, new FrameDescriptor(), node, "main");
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/nodes/AsyncJvmMathLangNode.java:
--------------------------------------------------------------------------------
1 | package nodes;
2 |
3 | import java.util.concurrent.CompletableFuture;
4 | import java.util.concurrent.ExecutionException;
5 |
6 | import com.oracle.truffle.api.frame.VirtualFrame;
7 | import com.oracle.truffle.api.nodes.NodeInfo;
8 |
9 | @NodeInfo(shortName = "->")
10 | public class AsyncJvmMathLangNode extends JvmMathLangNode {
11 |
12 | @Child private JvmMathLangNode expression;
13 |
14 | public AsyncJvmMathLangNode(JvmMathLangNode node) {
15 | this.expression = node;
16 | }
17 |
18 | @Override
19 | public Object executeGeneric(VirtualFrame frame) {
20 | try {
21 | System.out.println("Running on another thread: " + expression);
22 | return CompletableFuture.supplyAsync(() -> expression.executeGeneric(frame)).get();
23 | } catch (InterruptedException|ExecutionException e) {
24 | throw new RuntimeException(e);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/nodes/BinaryNode.java:
--------------------------------------------------------------------------------
1 | package nodes;
2 |
3 | import com.oracle.truffle.api.dsl.NodeChild;
4 | import com.oracle.truffle.api.dsl.NodeChildren;
5 |
6 | @NodeChildren({ @NodeChild("leftNode"), @NodeChild("righrNode") })
7 | public abstract class BinaryNode extends JvmMathLangNode {
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/nodes/JvmMathLangNode.java:
--------------------------------------------------------------------------------
1 | package nodes;
2 |
3 | import com.oracle.truffle.api.dsl.TypeSystemReference;
4 | import com.oracle.truffle.api.frame.VirtualFrame;
5 | import com.oracle.truffle.api.nodes.Node;
6 | import com.oracle.truffle.api.nodes.NodeInfo;
7 | import com.oracle.truffle.api.nodes.UnexpectedResultException;
8 | import jvmmathlang.truffle.JvmMathLangTypes;
9 | import jvmmathlang.truffle.JvmMathLangTypesGen;
10 |
11 | @NodeInfo
12 | @TypeSystemReference(JvmMathLangTypes.class)
13 | public abstract class JvmMathLangNode extends Node {
14 |
15 | public abstract Object executeGeneric(VirtualFrame frame);
16 |
17 | public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
18 | return JvmMathLangTypesGen.expectLong(executeGeneric(frame));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/nodes/JvmMathLangRootNode.java:
--------------------------------------------------------------------------------
1 | package nodes;
2 |
3 | import com.oracle.truffle.api.TruffleLanguage;
4 | import com.oracle.truffle.api.frame.FrameDescriptor;
5 | import com.oracle.truffle.api.frame.VirtualFrame;
6 | import com.oracle.truffle.api.nodes.NodeInfo;
7 | import com.oracle.truffle.api.nodes.RootNode;
8 |
9 | @NodeInfo
10 | public class JvmMathLangRootNode extends RootNode {
11 |
12 | /** The function body that is executed, and specialized during execution. */
13 | private JvmMathLangNode bodyNode;
14 |
15 | /** The name of the function, for printing purposes only. */
16 | private String name;
17 |
18 | public JvmMathLangRootNode(TruffleLanguage> language, FrameDescriptor frameDescriptor, JvmMathLangNode node, String name) {
19 | super(language, frameDescriptor);
20 | this.bodyNode = node;
21 | this.name = name;
22 | }
23 |
24 | @Override
25 | public Object execute(VirtualFrame frame) {
26 | return bodyNode.executeGeneric(frame);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/nodes/ParenJvmMathLangNode.java:
--------------------------------------------------------------------------------
1 | package nodes;
2 |
3 | import com.oracle.truffle.api.frame.VirtualFrame;
4 | import com.oracle.truffle.api.nodes.NodeInfo;
5 | import com.oracle.truffle.api.nodes.UnexpectedResultException;
6 |
7 | @NodeInfo
8 | public class ParenJvmMathLangNode extends JvmMathLangNode {
9 |
10 | @Child private JvmMathLangNode expression;
11 |
12 | public ParenJvmMathLangNode(JvmMathLangNode node) {
13 | this.expression = node;
14 | }
15 |
16 | public void setExpression(JvmMathLangNode node) {
17 | this.expression = node;
18 | }
19 |
20 | @Override
21 | public Object executeGeneric(VirtualFrame frame) {
22 | try {
23 | return this.expression.executeLong(frame);
24 | } catch (UnexpectedResultException e) {
25 | return this.expression.executeGeneric(frame);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/nodes/literal/BigDecimalNode.java:
--------------------------------------------------------------------------------
1 | package nodes.literal;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import com.oracle.truffle.api.frame.VirtualFrame;
6 | import com.oracle.truffle.api.nodes.NodeInfo;
7 | import nodes.JvmMathLangNode;
8 |
9 | @NodeInfo(shortName = "const")
10 | public class BigDecimalNode extends JvmMathLangNode {
11 |
12 | private final BigDecimal value;
13 |
14 | public BigDecimalNode(BigDecimal bigDecimal) {
15 | this.value = bigDecimal;
16 | }
17 |
18 | @Override
19 | public Object executeGeneric(VirtualFrame frame) {
20 | return new BigDecimalTruffleObject(this.value);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/nodes/literal/BigDecimalTruffleObject.java:
--------------------------------------------------------------------------------
1 | package nodes.literal;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import com.oracle.truffle.api.interop.ForeignAccess;
6 | import com.oracle.truffle.api.interop.TruffleObject;
7 |
8 | public class BigDecimalTruffleObject implements TruffleObject {
9 | private final BigDecimal value;
10 |
11 | public BigDecimalTruffleObject(BigDecimal value) {
12 | this.value = value;
13 | }
14 |
15 | public BigDecimal getValue() {
16 | return value;
17 | }
18 |
19 | @Override
20 | public ForeignAccess getForeignAccess() {
21 | return null;
22 | }
23 |
24 | @Override
25 | public String toString() {
26 | return this.value.toString();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/nodes/literal/LongNode.java:
--------------------------------------------------------------------------------
1 | package nodes.literal;
2 |
3 | import com.oracle.truffle.api.frame.VirtualFrame;
4 | import com.oracle.truffle.api.nodes.NodeInfo;
5 | import nodes.JvmMathLangNode;
6 |
7 | @NodeInfo(shortName = "const")
8 | public class LongNode extends JvmMathLangNode {
9 |
10 | private final long value;
11 |
12 | public LongNode(long l) {
13 | this.value = l;
14 | }
15 |
16 | public long executeLong(VirtualFrame frame) {
17 | return this.value;
18 | }
19 |
20 | @Override
21 | public Object executeGeneric(VirtualFrame frame) {
22 | return this.value;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/nodes/ops/AddNode.java:
--------------------------------------------------------------------------------
1 | package nodes.ops;
2 |
3 |
4 | import java.math.BigDecimal;
5 |
6 | import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
7 | import com.oracle.truffle.api.dsl.Specialization;
8 | import com.oracle.truffle.api.nodes.NodeInfo;
9 | import nodes.BinaryNode;
10 | import nodes.literal.BigDecimalTruffleObject;
11 |
12 | @NodeInfo(shortName = "+")
13 | public abstract class AddNode extends BinaryNode {
14 |
15 | @Specialization(rewriteOn = ArithmeticException.class)
16 | protected long add(long left, long right) {
17 | System.out.println("add(long, long)");
18 | return Math.addExact(left, right);
19 | }
20 |
21 | @Specialization
22 | @TruffleBoundary
23 | protected BigDecimalTruffleObject add(BigDecimalTruffleObject left, BigDecimalTruffleObject right) {
24 | System.out.println("add(BigDecimal, BigDecimal)");
25 | return new BigDecimalTruffleObject(left.getValue().add(right.getValue()));
26 | }
27 |
28 | @Specialization
29 | @TruffleBoundary
30 | protected BigDecimalTruffleObject add(Object left, Object right) {
31 | System.out.println("add(Object, Object)");
32 | BigDecimal l = left instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) left).getValue() : BigDecimal.valueOf((long) left);
33 | BigDecimal r = right instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) right).getValue() : BigDecimal.valueOf((long) right);
34 | return new BigDecimalTruffleObject(l.add(r));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/nodes/ops/DivNode.java:
--------------------------------------------------------------------------------
1 | package nodes.ops;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import com.oracle.truffle.api.dsl.Specialization;
6 | import com.oracle.truffle.api.nodes.NodeInfo;
7 | import nodes.BinaryNode;
8 | import nodes.literal.BigDecimalTruffleObject;
9 |
10 | @NodeInfo(shortName = "/")
11 | public abstract class DivNode extends BinaryNode {
12 |
13 | @Specialization(rewriteOn = ArithmeticException.class)
14 | protected long div(long left, long right) {
15 | long result = left / right;
16 |
17 | // leftがLong.MIN_VALUEでrightが-1だとオーバーフローとなる
18 | if ((left & right & result) < 0) {
19 | throw new ArithmeticException("long overflow");
20 | }
21 | return result;
22 | }
23 |
24 | @Specialization
25 | protected BigDecimalTruffleObject div(BigDecimalTruffleObject left, BigDecimalTruffleObject right) {
26 | return new BigDecimalTruffleObject(left.getValue().divide(right.getValue()));
27 | }
28 |
29 | @Specialization
30 | protected BigDecimalTruffleObject div(Object left, Object right) {
31 | BigDecimal l = left instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) left).getValue() : BigDecimal.valueOf((long) left);
32 | BigDecimal r = right instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) right).getValue() : BigDecimal.valueOf((long) right);
33 | return new BigDecimalTruffleObject(l.divide(r));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/nodes/ops/MulNode.java:
--------------------------------------------------------------------------------
1 | package nodes.ops;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import com.oracle.truffle.api.dsl.Specialization;
6 | import com.oracle.truffle.api.nodes.NodeInfo;
7 | import nodes.BinaryNode;
8 | import nodes.literal.BigDecimalTruffleObject;
9 |
10 | @NodeInfo(shortName = "*")
11 | public abstract class MulNode extends BinaryNode {
12 |
13 | @Specialization(rewriteOn = ArithmeticException.class)
14 | protected long mul(long left, long right) {
15 | return Math.multiplyExact(left, right);
16 | }
17 |
18 | @Specialization
19 | protected BigDecimalTruffleObject mul(BigDecimalTruffleObject left, BigDecimalTruffleObject right) {
20 | return new BigDecimalTruffleObject(left.getValue().multiply(right.getValue()));
21 | }
22 |
23 | @Specialization
24 | protected BigDecimalTruffleObject mul(Object left, Object right) {
25 | BigDecimal l = left instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) left).getValue() : BigDecimal.valueOf((long) left);
26 | BigDecimal r = right instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) right).getValue() : BigDecimal.valueOf((long) right);
27 | return new BigDecimalTruffleObject(l.multiply(r));
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/nodes/ops/SubNode.java:
--------------------------------------------------------------------------------
1 | package nodes.ops;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import com.oracle.truffle.api.dsl.Specialization;
6 | import com.oracle.truffle.api.nodes.NodeInfo;
7 | import nodes.BinaryNode;
8 | import nodes.literal.BigDecimalTruffleObject;
9 |
10 | @NodeInfo(shortName = "-")
11 | public abstract class SubNode extends BinaryNode {
12 |
13 | @Specialization(rewriteOn = ArithmeticException.class)
14 | protected long sub(long left, long right) {
15 | return Math.subtractExact(left, right);
16 | }
17 |
18 | @Specialization
19 | protected BigDecimalTruffleObject sub(BigDecimalTruffleObject left, BigDecimalTruffleObject right) {
20 | return new BigDecimalTruffleObject(left.getValue().subtract(right.getValue()));
21 | }
22 |
23 | @Specialization
24 | protected BigDecimalTruffleObject sub(Object left, Object right) {
25 | BigDecimal l = left instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) left).getValue() : BigDecimal.valueOf((long) left);
26 | BigDecimal r = right instanceof BigDecimalTruffleObject ? ((BigDecimalTruffleObject) right).getValue() : BigDecimal.valueOf((long) right);
27 | return new BigDecimalTruffleObject(l.subtract(r));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/nodes/uml.puml:
--------------------------------------------------------------------------------
1 | @startuml
2 |
3 | abstract class JvmMathLangNode
4 | abstract class BinaryNode
5 | abstract class AddNode
6 | abstract class SubNode
7 | abstract class MulNode
8 | abstract class DivNode
9 |
10 | JvmMathLangNode <|-- BinaryNode
11 | BinaryNode <|-- AddNode
12 | BinaryNode <|-- SubNode
13 | BinaryNode <|-- MulNode
14 | BinaryNode <|-- DivNode
15 |
16 | @enduml
17 |
18 | @startuml
19 |
20 | abstract class com.oracle.truffle.api.nodes.Node
21 | abstract class JvmMathLangNode
22 |
23 | com.oracle.truffle.api.nodes.Node <|-- JvmMathLangNode
24 |
25 | @enduml
26 |
27 | @startuml
28 |
29 | abstract class JvmMathLangNode
30 | class BigDecimalNode
31 | class LongNode
32 | class ParenJvmMathLangNode
33 |
34 | JvmMathLangNode <|-- BigDecimalNode
35 | JvmMathLangNode <|-- LongNode
36 | JvmMathLangNode <|-- ParenJvmMathLangNode
37 |
38 | @enduml
39 |
40 | @startuml
41 |
42 | abstract class AddNode
43 | abstract class SubNode
44 | abstract class MulNode
45 | abstract class DivNode
46 | class AddNodeGen
47 | class SubNodeGen
48 | class MulNodeGen
49 | class DivNodeGen
50 |
51 | AddNode <|-- AddNodeGen
52 | SubNode <|-- SubNodeGen
53 | MulNode <|-- MulNodeGen
54 | DivNode <|-- DivNodeGen
55 |
56 | @enduml
--------------------------------------------------------------------------------