Compare commits

..

No commits in common. "master" and "Beta" have entirely different histories.
master ... Beta

26 changed files with 32 additions and 513 deletions

4
.gitignore vendored
View file

@ -30,6 +30,4 @@ bin/
.class
/src/*.jar
/.idea
hello_world.froj
testfile.froj
/.idea

View file

@ -28,7 +28,7 @@ Implement some standard functions and method such as:
# Hello World
## The simplest way to get started:
* [Download the .jar under releases](https://github.com/jsaasta/Froj/releases)
* [Download the .jar under releases](https://github.com/jsaasta/Froj/releases/tag/stable)
* Create file ``helloworld.froj`` with the contents below:
print "Hello World";

View file

@ -7,40 +7,5 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library name="JUnit4">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.13.1/junit-4.13.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="JUnit4">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.13.1/junit-4.13.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="testng">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/testng/testng/7.1.0/testng-7.1.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/beust/jcommander/1.72/jcommander-1.72.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/google/inject/guice/4.1.0/guice-4.1.0-no_aop.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/aopalliance/aopalliance/1.0/aopalliance-1.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/19.0/guava-19.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/yaml/snakeyaml/1.21/snakeyaml-1.21.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

View file

@ -1 +1,4 @@
print "hello world";
print "Hello world!";

View file

@ -1,6 +1,4 @@
FILE_PATH = ./com/jsaasta/froj
FILE_PATH_STDLIB = $(FILE_PATH)/stdlib
FILE_PATH_STDLIB_SOCKET = $(FILE_PATH_STDLIB)/socket
FILE = ../hello_world.froj
FILE_NAME_JAR = froj.jar
@ -8,17 +6,13 @@ all: run
compile:
rm -f $(FILE_PATH)/*.class
javac -d ./ $(FILE_PATH)/*.java $(FILE_PATH_STDLIB)/*.java $(FILE_PATH_STDLIB_SOCKET)/*.java
jar -cfm $(FILE_NAME_JAR) ./META-INF/MANIFEST.MF $(FILE_PATH)/*.class $(FILE_PATH_STDLIB)/*.class $(FILE_PATH_STDLIB_SOCKET)/*.class
javac -d ./ $(FILE_PATH)/*.java
jar -cfm $(FILE_NAME_JAR) ./META-INF/MANIFEST.MF $(FILE_PATH)/*.class
rm -f $(FILE_PATH)/*.class
rm -f $(FILE_PATH_STDLIB)/*.class
rm -f $(FILE_PATH_STDLIB_SOCKET)/*.class
clean:
rm -f $(FILE_PATH)/*.class
rm -f ./$(FILE_NAME_JAR)
rm -f $(FILE_PATH_STDLIB)/*.class
rm -f $(FILE_PATH_STDLIB_SOCKET)/*.class
javac:
javac -d ./ $(FILE_PATH)/*.java

View file

@ -26,7 +26,7 @@ public class Froj {
}
public void runFile(String path) throws IOException {
private void runFile(String path) throws IOException {
try {
byte[] bytes = Files.readAllBytes(Paths.get(path));
run(new String(bytes, Charset.defaultCharset()));
@ -74,7 +74,7 @@ public class Froj {
}
public static void error(int line, String message) {
static void error(int line, String message) {
report(line, "", message);
}

View file

@ -1,9 +1,5 @@
package com.jsaasta.froj;
import com.jsaasta.froj.stdlib.Clock;
import com.jsaasta.froj.stdlib.Input;
import com.jsaasta.froj.stdlib.Stdlib;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -16,7 +12,23 @@ public class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
private Environment environment = globals;
public Interpreter() {
Stdlib.define().forEach(globals::define);
globals.define("clock", new FrojCallable() {
@Override
public int arity() {
return 0;
}
@Override
public Object call(Interpreter interpreter, List<Object> arguments) {
return (double) System.currentTimeMillis() / 1000.0;
}
@Override
public String toString() {
return "<native fn>";
}
});
}
public void interpret(List<Stmt> statements) {

View file

@ -14,7 +14,7 @@ public class Parser {
private final List<Token> tokens;
private int current = 0;
public Parser(List<Token> tokens) {
Parser(List<Token> tokens) {
this.tokens = tokens;
}

View file

@ -1,7 +1,7 @@
package com.jsaasta.froj;
public class RuntimeError extends RuntimeException {
public final Token token;
final Token token;
public RuntimeError(Token token, String message) {
super(message);

View file

@ -37,7 +37,7 @@ public class Scanner {
private int line = 1;
public Scanner(String source) {
Scanner(String source) {
this.source = source;
}

View file

@ -2,7 +2,7 @@ package com.jsaasta.froj;
import java.util.List;
public abstract class Stmt {
abstract class Stmt {
interface Visitor<R> {
R visitBlockStmt(Block stmt);

View file

@ -4,7 +4,7 @@ public class Token {
public final TokenType type;
public final String lexeme;
public final Object literal;
public final int line;
final int line;
public Token(TokenType type, String lexeme, Object literal, int line) {
this.type = type;

View file

@ -1,28 +0,0 @@
package com.jsaasta.froj.stdlib;
import com.jsaasta.froj.FrojCallable;
import com.jsaasta.froj.Interpreter;
import java.util.List;
/**
* @return Returns current time in nanoSeconds / 1000;
*/
public class Clock implements FrojCallable {
@Override
public int arity() {
return 0;
}
@Override
public Object call(Interpreter interpreter, List<Object> arguments) {
return (double) System.nanoTime() / 1000.0;
}
@Override
public String toString() {
return "<native fn Clock()>";
}
}

View file

@ -1,29 +0,0 @@
package com.jsaasta.froj.stdlib;
import com.jsaasta.froj.Froj;
import com.jsaasta.froj.FrojCallable;
import com.jsaasta.froj.Interpreter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
public class FileReader implements FrojCallable {
@Override
public int arity() {
return 1;
}
@Override
public Object call(Interpreter interpreter, List<Object> arguments) {
try {
byte[] bytes = Files.readAllBytes(Paths.get((String) arguments.get(0)));
return new String(bytes, Charset.defaultCharset());
} catch (IOException e) {
throw new StdlibRuntimeError("Couldn't find file: " + arguments.get(0));
}
}
}

View file

@ -1,42 +0,0 @@
package com.jsaasta.froj.stdlib;
import com.jsaasta.froj.FrojCallable;
import com.jsaasta.froj.Interpreter;
import com.jsaasta.froj.RuntimeError;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
public class Input implements FrojCallable {
@Override
public int arity() {
return 0;
}
@Override
public Object call(Interpreter interpreter, List<Object> arguments) {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
System.out.print("> ");
try {
String line = reader.readLine();
try {
return Double.parseDouble(line);
} catch(NumberFormatException ex) {
return line;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "<native fn Clock()>";
}
}

View file

@ -1,23 +0,0 @@
package com.jsaasta.froj.stdlib;
import com.jsaasta.froj.stdlib.socket.SocketServer;
import java.util.HashMap;
import java.util.Map;
public class Stdlib {
private static final Map<String, Object> classes;
static {
classes = new HashMap<>();
classes.put("clock", new Clock());
classes.put("input", new Input());
classes.put("fileReader", new FileReader());
classes.put("socket", new SocketServer());
}
public static Map<String, Object> define(){
return classes;
}
}

View file

@ -1,11 +0,0 @@
package com.jsaasta.froj.stdlib;
import com.jsaasta.froj.Token;
public class StdlibRuntimeError extends RuntimeException{
public StdlibRuntimeError(String message) {
super(message, null, false, false);
}
}

View file

@ -1,39 +0,0 @@
package com.jsaasta.froj.stdlib.socket;
import java.io.*;
import java.net.Socket;
class ClientHandler implements Runnable {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
byte[] buffer = new byte[1024];
int bytesRead = in.read(buffer);
if (bytesRead == -1) {
System.out.println("Client closed the Connection");
}
String message = new String(buffer, 0, bytesRead);
System.out.println("Received message from client: " + message);
out.write(message.getBytes());
SocketServer.messageQueue.put(message);
socket.close();
} catch (IOException e) {
System.out.println("Error handling client connection: " + e.getMessage());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -1,72 +0,0 @@
package com.jsaasta.froj.stdlib.socket;
import com.jsaasta.froj.FrojCallable;
import com.jsaasta.froj.Interpreter;
import com.jsaasta.froj.stdlib.StdlibRuntimeError;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class SocketServer implements FrojCallable {
protected static BlockingQueue<String> messageQueue = new LinkedBlockingQueue<>();
private static ServerSocket serverSocket;
private final String EXIT_CODE = "EXIT";
@Override
public int arity() {
return 1;
}
@Override
public Object call(Interpreter interpreter, List<Object> arguments) {
return startSocketServer(arguments.get(0));
}
private Object startSocketServer(Object port) {
try {
Double param = (Double) port;
final int PORT = param.intValue();
serverSocket = new ServerSocket(PORT);
Socket socket = serverSocket.accept();
System.out.println("Incoming connection from " + socket.getInetAddress());
ClientHandler clientHandler = new ClientHandler(socket);
clientHandler.run();
String nextMessage = getNextMessage();
if (nextMessage.toLowerCase().contentEquals("exit")) {
shutdown();
return EXIT_CODE;
}
try {
return Double.parseDouble(nextMessage);
} catch (NumberFormatException e) {
return nextMessage;
}
} catch (IOException | InterruptedException e) {
throw new StdlibRuntimeError(e.getMessage());
} finally {
shutdown();
}
}
public static String getNextMessage() throws InterruptedException {
return messageQueue.take();
}
public static void shutdown() {
try {
serverSocket.close();
} catch (IOException e) {
System.out.println("Error shutting down server: " + e.getMessage());
}
}
}

View file

@ -1,58 +0,0 @@
package com.jsaasta.tool;
import java.io.*;
import java.net.ConnectException;
import java.net.Socket;
class SocketClient {
public static void main(String[] args) throws IOException {
while(true) {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
String message = reader.readLine();
if(message.contentEquals("SHUTMEDOWN")){
break;
}
String response = sendMessage(message);
if (response != null) {
System.out.println("Received response from server: " + response);
}
}
}
private static String sendMessage(String message) throws IOException {
Socket socket = null;
try {
socket = new Socket("localhost", 8000);
System.out.println("Connected to server");
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
out.write(message.getBytes());
byte[] buffer = new byte[1024];
int bytesRead = in.read(buffer);
String response = new String(buffer, 0, bytesRead);
return response;
} catch (ConnectException e) {
System.out.println("Connection refused. Is the server running?");
return null;
} catch (IOException e) {
System.out.println("Error sending message: " + e.getMessage());
return null;
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
System.out.println("Error closing socket: " + e.getMessage());
}
}
}
}
}

View file

@ -1,15 +0,0 @@
package test.com.saasta.froj;
import com.jsaasta.froj.*;
import org.junit.Test;
import java.io.IOException;
public class FrojTest {
@Test
public void testHelloWorld() throws IOException {
Froj froj = new Froj();
froj.runFile("src/test/com/saasta/froj/froj_test.froj");
}
}

View file

@ -1,109 +0,0 @@
class HelloParent {
welcome(){
print "Hello from Parent";
}
}
class HelloWorld < HelloParent {
init(helloString){
this.helloString = helloString;
}
welcome(){
super.welcome();
print this.helloString;
}
}
var hello = "Hello World!";
var helloWorldObject = HelloWorld(hello);
helloWorldObject.welcome();
// Or just a simple:
print "Hello World";
// -----------------------------------------
class Test {
init(aBoolean){
if(aBoolean){
print "in true";
} else {
print "in false";
}
}
}
Test(false);
// ----------------------------------------
function controlFlowTest(someValue){
if(someValue == "if"){
print "in " + someValue;
} else if(someValue == "else if") {
print "in " + someValue;
} else {
print "in 'else', because the value was: " + someValue;
}
}
controlFlowTest("if");
controlFlowTest("else if");
controlFlowTest("something else entirely");
// ----------------------------------------
function testWhile(){
var a = 0;
while(a < 10){
a = a+1;
}
return a;
}
function testFor() {
var a = "";
for(var i = 0; i < 10; i = i + 1){
a = a + "a";
}
return a;
}
print testWhile();
print testFor();
// ---------------------------------------
function addTwoNumbers(a, b) {
return a + b;
}
function testCallBack(aFunction){
var a = 1;
var b = 2;
return aFunction(a, b);
}
print addTwoNumbers(4,5);
print testCallBack(addTwoNumbers);
// ---------------------------------------
class Person {
init(name){
this.name = name;
}
myNameIs() {
print this.name;
}
}
var janne = Person("Janne");
janne.name = "Janne";
janne.otherName = "Totally Not Janne";
janne.myNameIs();
print janne.otherName;
// ---------------------------------------

View file

@ -1,24 +0,0 @@
package test.com.saasta.froj.stdlib;
import com.jsaasta.froj.Froj;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
public class FrojStdlibTest {
@Test
public void test_Stdlib_Clock() throws IOException {
Froj froj = new Froj();
froj.runFile("src/test/com/saasta/froj/stdlib/froj_stdlib_clock.froj");
froj.runFile("src/test/com/saasta/froj/stdlib/froj_stdlib_fileReader.froj");
try {
froj.runFile("src/test/com/saasta/froj/stdlib/froj_stdlib_socketserver.froj");
} catch(NullPointerException ex){
}
}
}

View file

@ -1 +0,0 @@
clock();

View file

@ -1 +0,0 @@
fileReader("./hello_world.froj");

View file

@ -1 +0,0 @@
socket("asdf");