Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
termermc committed Dec 24, 2019
1 parent 863c3e4 commit 55c6556
Show file tree
Hide file tree
Showing 70 changed files with 6,745 additions and 1 deletion.
20 changes: 20 additions & 0 deletions .classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/classes" path="src">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Compiled class file
*.class

# Output files
bin/
target/

# Log file
*.log

Expand Down
23 changes: 23 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Rtflc</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
2 changes: 2 additions & 0 deletions .settings/org.eclipse.core.resources.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding//src/net/termer/rtflc/Main.java=UTF-8
13 changes: 13 additions & 0 deletions .settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
4 changes: 4 additions & 0 deletions .settings/org.eclipse.m2e.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,47 @@
# Rtflc
Advanced and high(er) permformance Rtfl runtime and compiler
Robust Rtfl runtime and compiler

## Why?
Since the creation of Rtfl, its speed has been a major drag on usefulness and usability. Due to this fact, I decided to write a new Rtfl runtime, fulfilling the following requirements:
- Speed
- Robustness
- Improved debugging

## How does Rtflc fulfill these requirements?t
To understand how Rtflc is an improvement on the original Rtfl interpreter, we must first understand how the original Rtfl interpreter worked. The original interpreter did not split up its execution and parsing mechanisms, instead executing each line as it parsed it. The effect of this is that execution was throttled to the speed of parsing, which is [not very good](https://github.com/termermc/rtfl/blob/c6d785a39353af4f1779d86064d307027d5bd078/src/net/termer/rtfl/expressions/Expressions.java#L50).

Rtflc, on the other hand, splits up parsing and execution into different components. The parsing component takes in source code and produces intermediate instructions which it then feeds to the executor. Since the parser can parse multiple lines into instructions and runs faster than the original interpreter, it allow the executor to work much faster. Loops are also faster, since instead of re-parsing the loop body, the entire body is translated into instructions that the executor can re-use.

## Rtfl bytecode
Like many previously interpreted languages have done, Rtfl now utilizes bytecode, which is effectively a high level implementation of basic instructions. Interpreting source code is far more expensive than executing bytecode, and as such, Rtflc can compile Rtfl source code into bytecode binaries that can be executed by Rtflc.

## Compiling
To compile (assuming you have Maven, if not, install it), you need to run `mvn install` in the source code root, and a file named `Rtflc-X.X-jar-with-dependencies.jar` will be created in the `target/` directory.

## Embedding Rtfl
Embedding Rtfl in an existing Java application is as simple as including the Rtflc jar, and adding the following code to your project:
```java
RtflRuntime runtime new RtflRuntime();
```
From there, you can import that standard library with
```java
runtime.importStandard();
```
import Java interop functions with
```java
runtime.importJavaInterop();
```
To expose a Java method to Rtfl, it's as simple as the following:
```java
// Some object
String str = "Hello world";

runtime.exposeMethod(/* The object that owns the method */ str, /* The method to expose */ "substring", /* The method's arguments */ new Class<?>[] {int.class});
```
After that, it would be possible to execute `println(substring(2))` and it would output `llo world`!

## Usage
To see usage instructions, execute the Rtflc jar with the `-h` or `--help` options.

## Language documentation
TODO, there's been some large updates. The last version of Rtfl was 1.3, this runtime supports 1.3 and onward. To see which versions Rtflc supports, execute the jar with the `-v` or `--version` options.
11 changes: 11 additions & 0 deletions Rtflc.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
51 changes: 51 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Rtflc</groupId>
<artifactId>Rtflc</artifactId>
<version>1.0</version>
<name>Rtflc</name>
<description>Higher performance Rtfl runtime and compiler</description>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>net.termer.rtflc.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
</project>
139 changes: 139 additions & 0 deletions src/net/termer/rtflc/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package net.termer.rtflc;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import net.termer.rtflc.type.ArrayType;
import net.termer.rtflc.type.RtflType;
import net.termer.rtflc.type.StringType;
import net.termer.rtflc.utils.ArgParser;
import net.termer.rtflc.compiler.CompilerOptions;
import net.termer.rtflc.compiler.RtflCompiler;
import net.termer.rtflc.producers.ProducerException;
import net.termer.rtflc.runtime.RtflRuntime;
import net.termer.rtflc.runtime.RuntimeException;

public class Main {
public static final double RTFLC_VERSION = 1.0;
public static final double RTFL_VERSION = 1.4;

@SuppressWarnings("unchecked")
public static void main(String[] args) {
ArgParser arg = new ArgParser(args);

if(arg.option("help") || arg.flag('h')) {
// Print program help
String jarName = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getName();
System.out.println(
"java -jar "+jarName+" <SCRIPT/BINARY> [OPTIONS]\n" +
"\n" +
"-h, --help prints this message\n" +
"-v, --version prints the version of Rtfl supported and the version of Rtflc running\n" +
"-c, --compile compiles the specified script\n" +
"-t, --time displays the time it took to execute or compile the provided script/binary (in milliseconds)\n" +
"-l, --compile-literal-loads compiles all scripts or binaries that are referenced with `load()` calls with literal string paths in them, and references the compiled versions\n" +
"-r, --compile-literal-requires compiles all scripts or binaries that are referenced with `require()` calls with literal string paths in them, and references the compiled versions\n" +
"-p, --package-literal-loads packages all scripts or binaries that are referenced with `load()` calls into the compiled binary output instead of referencing them\n" +
"-e, --package-literal-requires packages all scripts or binaries that are references with `require()` calls into the compiled binary output instead of referencing them\n" +
"-n, --preserve-line-numbers preserves line numbers for instructions in compiled binaries for debugging purposes\n" +
"-i, --disable-interop disables Java/Rtfl interop functions\n" +
"--out=FILENAME specifies the path to output the compiled binary to\n" +
"\n" +
"Examples:\n" +
" java -jar "+jarName+" script.rtfl --time Executes script.rtfl and outputs the time it took to execute it\n" +
" java -jar "+jarName+" script.rtfl --compile --package-literal-loads Compiles script.rtfl and packages all `load()` calls with literal paths specified"
);
} else if(arg.option("version") || arg.flag('v')) {
System.out.println("Supporting Rtfl version "+RTFL_VERSION+", running Rtflc "+RTFLC_VERSION);
} else if(arg.arguments().length > 0) {
// Check if referenced file is real and not a directory
File file = new File(arg.arguments()[0]);
if(file.isFile()) {
// Check if executing or compiling
if(arg.option("compile") || arg.flag('c')) {
// Setup compiler with command line options
RtflCompiler compiler = new RtflCompiler(
new CompilerOptions()
.compileLiteralLoads(arg.option("compile-literal-loads") || arg.flag('l'))
.compileLiteralRequires(arg.option("compile-literal-requires") || arg.flag('r'))
.packageLiteralLoads(arg.option("package-literal-loads") || arg.flag('p'))
.packageLiteralRequires(arg.option("package-literal-requires") || arg.flag('e'))
.preserveLineNumbers(arg.option("preserve-line-numbers") || arg.flag('n'))
);

String outPath = file.getPath();

// Resolve compile output path
if(arg.optionString("out") != null) {
outPath = arg.optionString("out");
} else {
if(outPath.endsWith(".rtfl"))
outPath = outPath.substring(0, outPath.length()-1)+'c';
else
outPath = outPath+".rtfc";
}

// Compile
try {
// Get start time (for timing purposes)
long startMs = System.currentTimeMillis();

// Compile file
compiler.compile(file, new FileOutputStream(outPath));

// Print amount of time the compile took if specified in options
long endMs = System.currentTimeMillis();
if(arg.option("time") || arg.flag('t'))
System.out.println("Took "+(endMs-startMs)+"ms to compile file");

} catch (IOException | ProducerException | RuntimeException e) {
System.err.println("Failed to compile file:");
e.printStackTrace();
}
} else {
// Create runtime and import standard library
RtflRuntime rt = new RtflRuntime().importStandard();

if(!arg.option("disable-interop") && !arg.flag('i'))
rt.importJavaInterop();

// Make launch arguments available to runtime
ArrayType rtflArgs = new ArrayType();
for(int i = 1; i < arg.arguments().length; i++)
((ArrayList<RtflType>) rtflArgs.value()).add(new StringType(arg.arguments()[i]));
rt.globalVarables().put("args", rtflArgs);

try {
// Record start time
long startMs = System.currentTimeMillis();

// Execute file
rt.executeFile(file);

// If enabled, print the time it took to read and execute file
long endMs = System.currentTimeMillis();
if(arg.option("time") || arg.flag('t'))
System.out.println("Took "+(endMs-startMs)+"ms to read and execute file");

} catch (IOException e) {
System.err.println("Error while reading file:");
e.printStackTrace();
} catch (RuntimeException e) {
// Print runtime error
String where = e.cause() == null ? "unknown:0" : e.cause().originFile()+':'+e.cause().originLine();
System.err.println(where+' '+e.getMessage());
} catch (ProducerException e) {
// Print compile error
System.err.println("Failed to execute file: "+e.getMessage());
}
}
} else {
System.out.println("Specified path does not point to a file");
}
} else {
System.out.println("Please provide a path to an Rtfl file or specify --help");
}
}
}
17 changes: 17 additions & 0 deletions src/net/termer/rtflc/RtflLibrary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package net.termer.rtflc;

import net.termer.rtflc.runtime.RtflRuntime;

/**
* Basic library interface to be extended by external jar libraries
* @author termer
* @since 1.0
*/
public interface RtflLibrary {
/**
* Method to be run when the library is loaded
* @param runtime The instance of the Rtfl runtime that loaded this library
* @since 1.0
*/
public void initialize(RtflRuntime runtime);
}
16 changes: 16 additions & 0 deletions src/net/termer/rtflc/compiler/CompilerException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.termer.rtflc.compiler;

import java.io.IOException;

/**
* Exception to be thrown when there's an issue compiling Rtfl code
* @author termer
* @since 1.0
*/
public class CompilerException extends IOException {
private static final long serialVersionUID = 1L;

public CompilerException(String msg) {
super(msg);
}
}
Loading

0 comments on commit 55c6556

Please sign in to comment.