Skip to content

Commit 9ef4841

Browse files
authored
Merge pull request #75 from emustudio/development
Development
2 parents 4d04682 + 9791ed4 commit 9ef4841

31 files changed

+515
-400
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@ For Maven, use:
1414
<dependency>
1515
<groupId>net.emustudio</groupId>
1616
<artifactId>emulib</artifactId>
17-
<version>11.7.0</version>
17+
<version>12.0.0</version>
1818
</dependency>
1919
```
2020

2121
For Gradle, use:
2222

2323
```
24-
implementation 'net.emustudio:emulib:11.7.0'
24+
implementation 'net.emustudio:emulib:12.0.0'
2525
```
2626

2727
### Important changes
2828

29-
Up to version 9.0.0 emuLib used different group (`net.sf.emustudio`) and artifactId (`emuLib`). From version 10.0.0
29+
Until version 9.0.0 emuLib used different group (`net.sf.emustudio`) and artifactId (`emuLib`). From version 10.0.0
3030
onwards it uses group `net.emustudio` and artifactId `emulib` (all lowercase).
3131

3232
## Deployment

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ plugins {
2525
}
2626

2727
group 'net.emustudio'
28-
version '11.7.0'
28+
version '12.0.0'
2929

3030
repositories {
3131
mavenCentral()

src/main/java/net/emustudio/emulib/plugins/Plugin.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
* - the root class has to have single constructor with 3 parameters (see below).
3737
* <p>
3838
* The constructor signature has to look like this:
39-
*
39+
* <p>
4040
* <code>
4141
* \@PluginRoot(...)
4242
* SamplePlugin(long pluginId, ApplicationApi emustudio, PluginSettings settings) {
@@ -116,9 +116,8 @@ public interface Plugin {
116116
/**
117117
* Get run-time title of this plugin.
118118
* <p>
119-
* The title is a matter of change during runtime - for example there
120-
* might be a device which might be used many times but it is called
121-
* differently for each instance.
119+
* The title is a matter of change during runtime - for example there might exist a device instantiated more than
120+
* once, and each instance can have different title assigned at runtime.
122121
*
123122
* @return run-time title of the plugin
124123
*/
@@ -144,5 +143,12 @@ public interface Plugin {
144143
* @return plugin description
145144
*/
146145
String getDescription();
146+
147+
/**
148+
* Determines if this plugin supports emulation automation
149+
*
150+
* @return true if the plugin supports emulation automation; false otherwise
151+
*/
152+
boolean isAutomationSupported();
147153
}
148154

src/main/java/net/emustudio/emulib/plugins/compiler/Compiler.java

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,26 +75,20 @@ public interface Compiler extends Plugin {
7575
/**
7676
* Creates a lexical analyzer.
7777
*
78-
* @param input source code
7978
* @return new lexer object
8079
*/
81-
LexicalAnalyzer createLexer(String input);
82-
83-
/**
84-
* Gets location of compiled program in memory.
85-
* <p>
86-
* Program location should be valid only after successful compilation.
87-
* The location should point to the starting position of the program in memory, where the CPU can start emulating.
88-
*
89-
* @return location of compiled program in memory
90-
*/
91-
int getProgramLocation();
80+
LexicalAnalyzer createLexer();
9281

9382
/**
9483
* Get the list of source file extensions supported by the compiler.
9584
*
9685
* @return list of supported source file extensions
9786
*/
98-
List<SourceFileExtension> getSourceFileExtensions();
87+
List<FileExtension> getSourceFileExtensions();
88+
89+
@Override
90+
default boolean isAutomationSupported() {
91+
return true;
92+
}
9993
}
10094

src/main/java/net/emustudio/emulib/plugins/compiler/CompilerContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
/**
2525
* Compiler context can be used to provide additional meta-information for runtime, which can be used by other plugins.
26-
*
26+
* <p>
2727
* Plugins which need the specific compiler contexts, should declare a dependency on the compiler plugin.
2828
*/
2929
@PluginContext

src/main/java/net/emustudio/emulib/plugins/compiler/CompilerMessage.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
* Messages are passed to compiler listeners when the compiler wishes to say something.
2525
*/
2626
public class CompilerMessage {
27-
public static final String MSG_INFO = "[Info ] ";
28-
public static final String MSG_ERROR = "[Error ] ";
29-
public static final String MSG_WARNING = "[Warning] ";
27+
public static final String MSG_INFO = "[INFO ] ";
28+
public static final String MSG_ERROR = "[ERROR ] ";
29+
public static final String MSG_WARNING = "[WARNING] ";
3030

3131
public static final String POSITION_FORMAT = "(%3d,%3d) ";
3232

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* This file is part of emuLib.
3+
*
4+
* Copyright (C) 2006-2023 Peter Jakubčo
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
package net.emustudio.emulib.plugins.compiler;
20+
21+
import net.jcip.annotations.Immutable;
22+
23+
import java.util.Objects;
24+
25+
/**
26+
* A file extension with description.
27+
* A compiler provides list of supported source file extensions with a description, which is then used in
28+
* emuStudio application when opening a file.
29+
* <p>
30+
* The file extension should be provided without the starting dot ("."), i.e. "asm" instead of ".asm".
31+
* The extension is case-sensitive.
32+
* <p>
33+
* Instances of this class can be compared using .equals() method and also put to hashed collections like
34+
* HashMap or HashSet. The comparison is performed by extension only.
35+
*/
36+
@Immutable
37+
public class FileExtension {
38+
private final String extension;
39+
private final String description;
40+
41+
/**
42+
* Creates new instance of FileExtension.
43+
*
44+
* @param extension Case-sensitive non-null file extension of the file, without the starting dot
45+
* (example: "asm", but not ".asm").
46+
* @param description Non-null description of the file extension.
47+
* @throws NullPointerException if extension or description is null
48+
*/
49+
public FileExtension(String extension, String description) {
50+
this.extension = Objects.requireNonNull(extension);
51+
this.description = Objects.requireNonNull(description);
52+
}
53+
54+
/**
55+
* Returns the file extension.
56+
*
57+
* @return File extension
58+
*/
59+
public String getExtension() {
60+
return extension;
61+
}
62+
63+
/**
64+
* Returns the file-extension description.
65+
*
66+
* @return file-extension description
67+
*/
68+
public String getDescription() {
69+
return description;
70+
}
71+
72+
@Override
73+
public boolean equals(Object o) {
74+
if (this == o) return true;
75+
if (o == null || getClass() != o.getClass()) return false;
76+
FileExtension that = (FileExtension) o;
77+
return extension.equals(that.extension);
78+
}
79+
80+
@Override
81+
public int hashCode() {
82+
return Objects.hash(extension);
83+
}
84+
85+
/**
86+
* Strip file name extension if the extension belongs to known extensions.
87+
* <p>
88+
* The idea is that compilers should generate file with some "output" extension, so the source extension is replaced
89+
* with it. However, if the source extension is unknown, it should be preserved.
90+
*
91+
* @param fileName a file name
92+
* @param knownExtensions known extensions
93+
* @return given file name stripped from extension if it belongs to known ones
94+
*/
95+
public static String stripKnownExtension(String fileName, Iterable<FileExtension> knownExtensions) {
96+
for (FileExtension extension : knownExtensions) {
97+
int i = fileName.lastIndexOf("." + extension.getExtension());
98+
if (i >= 0) {
99+
return fileName.substring(0, i);
100+
}
101+
}
102+
return fileName;
103+
}
104+
}

src/main/java/net/emustudio/emulib/plugins/compiler/LexicalAnalyzer.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
package net.emustudio.emulib.plugins.compiler;
2020

21+
import net.jcip.annotations.NotThreadSafe;
22+
2123
import java.io.IOException;
2224
import java.io.InputStream;
2325
import java.util.ArrayList;
@@ -26,38 +28,48 @@
2628

2729
/**
2830
* Lexical analyzer.
31+
* <p>
32+
* It is not meant to be thread-safe.
33+
* Before using, make sure the lexer is reset.
2934
*/
3035
@SuppressWarnings("unused")
36+
@NotThreadSafe
3137
public interface LexicalAnalyzer extends Iterable<Token> {
3238

3339
/**
34-
* Get next token.
35-
* <p>
36-
* Tokens are retrieved as in "iterator" style - the actual position is a mutable state stored in the lexer.
40+
* Parse next token.
3741
*
38-
* @return next token
42+
* @return next token, or Token.EOF if no token is available on the input
3943
*/
40-
Token nextToken();
44+
Token next();
4145

4246
/**
43-
* Determines if this lexer is at EOF (at the end of parsing)
44-
* @return true if the EOF was hit
47+
* Determines if a next token is available on the input at the current lexer position.
48+
*
49+
* @return true if the lexer has a next token to be parsed
4550
*/
46-
boolean isAtEOF();
51+
boolean hasNext();
4752

4853
/**
4954
* Reset this lexical analyzer with new input.
50-
* All state should be reset.
55+
*
5156
* @param input new program source code
5257
* @throws IOException when input cannot be read
5358
*/
5459
void reset(InputStream input) throws IOException;
5560

61+
/**
62+
* Reset this lexical analyzer with new input.
63+
*
64+
* @param input new program source code
65+
*/
66+
void reset(String input);
67+
5668
@Override
5769
default Iterator<Token> iterator() {
5870
List<Token> tokens = new ArrayList<>();
59-
while (!isAtEOF()) {
60-
tokens.add(nextToken());
71+
while (hasNext()) {
72+
tokens.add(next());
6173
}
6274
return tokens.iterator();
6375
}

src/main/java/net/emustudio/emulib/plugins/compiler/SourceFileExtension.java

Lines changed: 0 additions & 66 deletions
This file was deleted.

src/main/java/net/emustudio/emulib/plugins/cpu/AbstractCPU.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ void requestStop() {
126126
/**
127127
* Creates new instance of CPU.
128128
*
129-
* @param pluginID plugin ID
129+
* @param pluginID plugin ID
130130
* @param applicationApi emuStudio API
131-
* @param settings plugin custom settings
131+
* @param settings plugin custom settings
132132
*/
133133
public AbstractCPU(long pluginID, ApplicationApi applicationApi, PluginSettings settings) {
134134
this.pluginID = pluginID;
@@ -212,7 +212,9 @@ private void stopExecutor(ExecutorService executor) {
212212
Objects.requireNonNull(executor);
213213
executor.shutdown();
214214
try {
215-
executor.awaitTermination(10, TimeUnit.SECONDS);
215+
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
216+
executor.shutdownNow();
217+
}
216218
} catch (InterruptedException e) {
217219
Thread.currentThread().interrupt();
218220
}
@@ -273,7 +275,7 @@ private void ensureCpuIsStopped() {
273275

274276
@Override
275277
public void reset() {
276-
reset(0);
278+
reset(applicationApi.getProgramLocation());
277279
}
278280

279281
@Override

0 commit comments

Comments
 (0)