An attempt at making a MUMPS runtime environment for the java virtual machine (JVM) similar to how other programming languages such as Groovy, Scala, Ruby, Python etc. have utilized the JVM platform
- ANTLR-based Lexer/parser that can interpret and execute M code
- Compiler that can compile M code to JVM byte-code (very early, only 1-2 commands implemented)
- Globals API/proxy
- Plain java persistence (Using H2's MVStore storage engine)
- Connecters back to InterSystems Cache (Using cache extreme drivers)
 
- Runtime environment (~40% of the system commands/functions implemented)
- Shell/console tool including:
- command history
- TAB-expansion of variable and routine names
- VI/EMACS-style key bindings
 
- Created by Brian Bray, President/Founder of BrayLabs
- Initially created as an exercise in learning M while working for the VA on the Health Management Platform (HMP). The original project, not the current eHMP project.
- This is an enhanced version of what was originally published as open source software by the VA to OSEHRA,
- Questions/comments can be directed to me via email, or I also still lurk on the Hardhats list a bit.
- Java (7 or 8)
- Maven
- InterSystems Cache (Optional)
- ANTLR4 Eclipse Plugin (Optional)
- Currently will fail to fetch Cache dependencies, might need to comment them out or install into local maven repo manually
- CacheGlobalStoredoesn't work on OSX, the cache driver causes core dumps
- There is still some quirky M code that the ANTLR grammar cannot handle
- Not all the commands/system functions are implemented nor are they fully implemented and completely compatible
- Some forms of indirection work, others do not
git clone https://github.com/braylabs/m4j.git
cd m4j
mvn package
java -jar target/m4j-0.1.jar
Welcome to M4J console, type 'H' to quit
M4J> S SAY="HELLO",NAME="WORLD"
M4J> W SAY_" "_NAME
HELLO WORLD
M4J>
Currently only 1 M routine in src/test/ compiles.  This should generate a class file that can be utilized by regular java apps.
m4jc -package=m4j. -dest=target/m4jc/m4j src/test/java/com/braylabs/m4j/lang/M4JCTST.int
import java.io.File;
import java.io.IOException;
import com.braylabs.m4j.lang.M4JRuntime;
import com.braylabs.m4j.lang.M4JRuntime.M4JProcess;
import com.braylabs.m4j.lang.RoutineProxy;
import com.braylabs.m4j.lang.RoutineProxy.MInterpRoutineProxy;
import com.braylabs.m4j.lang.RoutineProxy.JavaClassProxy.M4JEntryPoint;
import com.braylabs.m4j.lang.RoutineProxy.JavaClassProxy.M4JRoutine;
import static com.braylabs.m4j.lang.MUMPS.*;
public class Demo {
	public static void main(String[] args) throws IOException {
	  // Create a M4J runtime and register 2 routines:
	  // 1) Register an annotated java static method as a M routine
	  // 2) Load/Parse a M-language routine file from disk
		M4JRuntime runtime = new M4JRuntime();
		runtime.registerRoutine(new RoutineProxy.JavaClassProxy(MyFirstM4JRoutine.class));
		runtime.registerRoutine(new MInterpRoutineProxy(new File("src/main/mumps/XLFSTR.int")));
		
		// Create a M4J Process and evaluate a simple line
		M4JProcess proc = new M4JProcess(runtime, 123);
		proc.getInterpreter().evalLine("W !,$$SAY^HELLO($$UP^XLFSTR(\"world\")),!");
	}
	// Register this class as a M routine named 'HELLO'
	@M4JRoutine(name="HELLO")
	public static class MyFirstM4JRoutine {
		
		// With an entry point named 'SAY'
		@M4JEntryPoint(name="SAY")
		public static String hello(String val) {
			return "Hello: " + val;
		}
	}
}