blob: 0c2ba3ae31dac096c4dacc8616a6d92428f9018c [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.mrql;
import org.apache.mrql.gen.*;
import java.io.*;
import javax.tools.*;
import javax.tools.JavaCompiler.CompilationTask;
import java.lang.reflect.*;
import java.util.*;
import java.net.*;
import java.util.jar.*;
import org.apache.hadoop.io.WritableComparable;
/** compilation of MRQL expressions to Java code and then to Java bytecode */
final public class Compiler extends Translator {
static JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
static DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
final static String tmp_dir = "/tmp/mrql_jar_"+System.getProperty("user.name");
public static String jar_path;
static int lambda_num = 0;
static int user_functions_num = 0;
static Trees compiled_lambdas = #[ ];
/** Compile the MRQL functional arguments into Java bytecode */
final private static class JavaSourceFromString extends SimpleJavaFileObject {
final String code;
JavaSourceFromString ( String name, String code ) {
super(URI.create("string:///org/apache/mrql/" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent ( boolean ignoreEncodingErrors ) {
return code;
}
}
private static String new_lambda_name () {
return "MRQL_Lambda_"+(lambda_num++);
}
private static void add2jar ( File source, int offset, JarOutputStream target ) throws IOException {
if (source.isDirectory()) {
String name = source.getPath();
if (name.length() > offset) {
JarEntry entry = new JarEntry(name.substring(offset));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
target.closeEntry();
};
for ( File nestedFile: source.listFiles() )
add2jar(nestedFile,offset,target);
} else {
JarEntry entry = new JarEntry(source.getPath().substring(offset));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
BufferedInputStream in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
int count = 1;
while (count > 0) {
count = in.read(buffer);
if (count > 0)
target.write(buffer,0,count);
};
target.closeEntry();
in.close();
}
}
private static void remove ( File file ) throws IOException {
if (file.isDirectory())
for ( File nestedFile: file.listFiles() )
remove(nestedFile);
file.delete();
}
public static void clean () throws IOException {
remove(new File(tmp_dir));
}
final private static Tree compile ( Tree e, StringBuffer out ) throws Exception {
match e {
case `f(...al):
if (!plans_with_distributed_lambdas.member(#<`f>))
fail;
Trees nl = #[];
for ( Tree a: al)
match Interpreter.closure(a,Interpreter.global_env) {
case compiled(`fname,lambda(`v,`body)):
if (compiled_lambdas.member(fname))
fail;
compiled_lambdas = compiled_lambdas.append(fname);
StringBuffer sb = new StringBuffer(1000);
sb.append("final class "+fname+" extends Function {\n");
sb.append(fname+" () {}\n");
sb.append("final public MRData eval ( final MRData "+v
+" ) { return "+compileE(body)+"; }\n}\n");
out.append(sb);
nl = nl.append(#<compiled(`fname,lambda(`v,`body))>);
case lambda(`v,`body):
String fname = new_lambda_name();
compiled_lambdas = compiled_lambdas.append(#<`fname>);
StringBuffer sb = new StringBuffer(1000);
sb.append("final class "+fname+" extends Function {\n");
sb.append(fname+" () {}\n");
sb.append("final public MRData eval ( final MRData "+v
+" ) { return "+compileE(body)+"; }\n}\n");
out.append(sb);
nl = nl.append(#<compiled(`fname,`a)>);
case _: nl = nl.append(compile(a,out));
};
return #<`f(...nl)>;
case `f(...al):
Trees nl = #[];
for ( Tree a: al)
nl = nl.append(compile(a,out));
return #<`f(...nl)>;
};
return e;
}
private static boolean is_persistent_type ( Tree tp ) {
match tp {
case `T(`t):
return is_persistent_collection(T.toString());
case `f(...ts):
for ( Tree t: ts )
if (is_persistent_type(t))
return true;
case `v:
Tree vt = TypeInference.expand(v);
if (!v.equals(vt))
return is_persistent_type(vt);
};
return false;
}
private static StringBuffer out;
/** compile the functional arguments of the MRQL operators using the Java compiler
* @param query the expression to compile
* @return the query with all functional arguments compiled to Java bytecode
*/
final public static Tree compile ( Tree query ) {
try {
compiled_lambdas = #[ ];
user_functions_num = lambda_num++;
// remove the old jar
if (jar_path != null)
remove(new File(jar_path));
jar_path = tmp_dir+"/mrql_args_"+(new Random().nextInt(1000000))+".jar";
out = new StringBuffer(1000);
out.append("package org.apache.mrql;\n");
Tree nq = compile(query,out);
StringBuffer sb = new StringBuffer(1000);
for ( String f: global_functions )
match global_functions.lookup(f) {
case function(tuple(...params),`otp,`body):
if (is_persistent_type(otp)) {
compile(body,out); // incorporate compiled arguments but ignore body
fail
};
sb.append("final public static "+get_MR_type(otp)+" "+f);
if (params.is_empty())
sb.append(" ()");
else {
match params.head() {
case bind(`v,`tp):
sb.append(" ( final "+get_MR_type(tp)+" "+v);
};
for ( Tree var: params.tail() )
match var {
case bind(`v,`tp):
sb.append(", final "+get_MR_type(tp)+" "+v);
}
sb.append(" ) { return ("+get_MR_type(otp)+")");
sb.append(compileE(body));
sb.append("; }\n");
}
};
out.append("final class UserFunctions_"+user_functions_num+" {\n");
out.append(sb);
out.append("}\n");
String code = out.toString();
//System.out.println(code);
JavaFileObject file = new JavaSourceFromString("UserFunctions_"+user_functions_num,code);
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
List<String> optionList = new ArrayList<String>();
(new File(tmp_dir)).mkdir();
String dir = tmp_dir+"/classes_"+(new Random().nextInt(1000000));
File fdir = new File(dir);
fdir.mkdir();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String classpath = jar_path;
String separator = System.getProperty("path.separator");
for ( URL url: ((URLClassLoader) classLoader).getURLs() )
classpath += separator+url.getFile();
// use hadoop core jar
classpath += separator + WritableComparable.class.getProtectionDomain().getCodeSource().getLocation().toString();
optionList.addAll(Arrays.asList("-classpath",classpath));
optionList.addAll(Arrays.asList("-d",dir));
CompilationTask task = compiler.getTask(null,null,diagnostics,optionList,null,compilationUnits);
boolean success = task.call();
if (!success)
for ( Diagnostic d: diagnostics.getDiagnostics() )
System.err.println("*** Compilation error at line "+d.getLineNumber()+" position "
+d.getColumnNumber()+": "+d.getMessage(Locale.US));
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION,"1.0");
JarOutputStream target = new JarOutputStream(new FileOutputStream(jar_path),manifest);
add2jar(new File(dir+"/"),dir.length()+1,target);
target.close();
remove(fdir);
return nq;
} catch (Exception e) {
System.err.println("*** Warning: Unable to compile the query:\n"+query);
if (Config.trace)
e.printStackTrace(System.err);
return query;
}
}
/** load the Java class of the anonymous function with name lambda_name */
final public static Function compiled ( ClassLoader cl, String lambda_name ) throws Exception {
URL[] urls = ((URLClassLoader) cl).getURLs();
URL[] new_urls = new URL[urls.length+1];
for ( int i = 0; i < urls.length; i++ )
new_urls[i+1] = urls[i];
new_urls[0] = new URL("file://"+jar_path);
URLClassLoader loader = new URLClassLoader(new_urls,cl);
Class c = loader.loadClass("org.apache.mrql."+lambda_name);
Constructor cc = c.getDeclaredConstructors()[0];
cc.setAccessible(true);
return (Function)cc.newInstance();
}
/** The Java type of an MRQL type */
private static String get_MR_type ( Tree type ) {
match type {
case boolean: return "MR_bool";
case byte: return "MR_byte";
case short: return "MR_short";
case int: return "MR_int";
case long: return "MR_long";
case float: return "MR_float";
case double: return "MR_double";
case char: return "MR_char";
case string: return "MR_string";
case union: return "Union";
case bag(...): return "Bag";
case list(...): return "Bag";
};
return "MRData";
}
private static Trees remove_duplicates ( Trees al ) {
if (al.is_empty())
return al;
Trees el = remove_duplicates(al.tail());
if (el.member(al.head()))
return el;
else return el.cons(al.head());
}
/** lambda lifting: generate Java code from an anonymous function */
private static String compilef ( String v, Tree body ) throws Exception {
String fname = new_lambda_name();
Trees free_vars = remove_duplicates(free_variables(body,#[`v,...repeat_variables]));
StringBuffer sb = new StringBuffer(1000);
sb.append("final class "+fname+" extends Function {\n");
for ( Tree var: free_vars )
sb.append("MRData "+var+"; ");
sb.append("\npublic "+fname+" (");
if (free_vars.is_empty())
sb.append(") {}\n");
else {
sb.append(" MRData "+free_vars.head());
for ( Tree var: free_vars.tail() )
sb.append(", MRData "+var);
sb.append(" ) { ");
for ( Tree var: free_vars )
sb.append("this."+var+" = "+var+"; ");
sb.append("}\n");
};
sb.append("final public MRData eval ( final MRData "+v
+" ) { return "+compileE(body)+"; }\n}\n");
out.append(sb);
String s = "new "+fname+"(";
if (!free_vars.is_empty()) {
s += free_vars.head();
for ( Tree var: free_vars.tail() )
s += ","+var;
};
return s+")";
}
private static String compileF ( Tree fnc ) throws Exception {
match fnc {
case lambda(`v,`b):
return compilef(v.toString(),b);
case compiled(`f,`lm):
// recompile the function
String s = compileF(lm);
((Node)fnc).children().head = new VariableLeaf(s.substring(4,s.indexOf("("))); //destructive
return s;
case function(tuple(...params),`tp,`body):
if (is_persistent_type(tp)) {
compileE(body);
return "";
};
String ret = "new Lambda(new Function () { "
+"final public MRData eval ( final MRData _x ) { ";
for ( int i = 0; i < params.length(); i++ )
match params.nth(i) {
case bind(`v,_):
ret += "final MRData "+v+" = ((Tuple)_x).get("+i+"); ";
};
return ret+" return "+compileE(body)+"; } })";
};
throw new Exception("Ill-formed lambda: "+fnc);
}
private static String compileEL ( Trees el ) throws Exception {
if (el.is_empty())
return "";
String ret = compileE(el.head());
for ( Tree a: el.tail() )
ret += ","+compileE(a);
return ret;
}
private static String compileE ( Tree e ) throws Exception {
if (e == null)
return "(new MR_byte(0))";
if (e.equals(#<true>))
return "(new MR_bool(true))";
else if (e.equals(#<false>))
return "(new MR_bool(false))";
else if (e.equals(#<null>))
return "(new MR_byte(0))";
else if (e.is_variable())
if (global_type_env.lookup(e.toString()) != null || repeat_variables.member(e))
return "Interpreter.lookup_global_binding(\""+e.toString()+"\")";
else return e.toString();
else if (e.is_long())
return "(new MR_int("+((LongLeaf)e).value()+"))";
else if (e.is_double())
return "(new MR_double("+((DoubleLeaf)e).value()+"))";
else if (e.is_string())
return "(new MR_string("+e.toString()+"))";
match e {
case trace(`msg,`tp,`x):
return "Interpreter.trace(Interpreter.pre_trace(((MR_string)("
+compileE(msg)+")).get()),"+reify(tp)+","+compileE(x)+")";
case callM(and,_,`x,`y):
return "(new MR_bool(((MR_bool)"+compileE(x)
+").get() && ((MR_bool)"+compileE(y)+").get()))";
case callM(or,_,`x,`y):
return "(new MR_bool(((MR_bool)"+compileE(x)
+").get() || ((MR_bool)"+compileE(y)+").get()))";
case callM(not,_,`x):
return "(new MR_bool(!((MR_bool)"+compileE(x)+").get()))";
case callM(`f,`n,...args):
if (!n.is_long())
fail;
String ret = "SystemFunctions."+ClassImporter.method_name((int)((LongLeaf)n).value())+"(";
Trees sig = ClassImporter.signature((int)((LongLeaf)n).value());
for (int i = 0; i < args.length(); i++)
ret += ((i > 0) ? ",(" : "(")+get_MR_type(sig.nth(i+1))+")("+compileE(args.nth(i))+")";
return ret+")";
case lambda(`v,`body):
return "new Lambda("+compilef(v.toString(),body)+")";
case nth(`x,`n):
return "(((Tuple)("+compileE(x)+")).get("+((LongLeaf)n).value()+"))";
case setNth(`x,`n,`v,`ret):
return "(((Tuple)("+compileE(x)+")).set("+((LongLeaf)n).value()+","+compileE(v)+","+compileE(ret)+"))";
case materialize(`u):
return "MapReduceAlgebra.materialize("+compileE(u)+")";
case let(`v,`u,`body):
return "(new Function () { public MRData eval ( final MRData "+v
+" ) { if ("+v+" instanceof Bag) ((Bag)"+v+").materialize(); return "
+compileE(body)+"; }; }).eval("+compileE(u)+")";
case cmap(`m,`s):
return "MapReduceAlgebra.cmap("+compileF(m)+",(Bag)("+compileE(s)+"))";
case filter(`p,`m,`s):
return "MapReduceAlgebra.filter("+compileF(p)+","+compileF(m)
+",(Bag)"+compileE(s)+")";
case map(`m,`s):
return "MapReduceAlgebra.map("+compileF(m)+",(Bag)"+compileE(s)+")";
case fold(`acc,`zero,`s):
return "MapReduceAlgebra.fold("+compileF(acc)+","+compileE(zero)+",(Bag)"+compileE(s)+")";
case range(`min,`max):
return "MapReduceAlgebra.generator(((MR_long)"+compileE(min)+").get(),"
+"((MR_long)"+compileE(max)+").get())";
case call(`f,...args):
return "("+compileF(f)+".eval("+compileE(#<tuple(...args)>)+"))";
case tuple():
return "(new Tuple())";
case tuple(`x):
return "(new Tuple("+compileE(x)+"))";
case tuple(`a,...el):
String ret = "(new Tuple("+compileE(a);
for ( Tree x: el )
ret += ","+compileE(x);
return ret+"))";
case tagged_union(`n,`u):
return "(new Union((byte)"+((LongLeaf)n).value()+","+compileE(u)+"))";
case union_value(`x):
return "(((Union)"+compileE(x)+").value())";
case union_tag(`x):
return "(new MR_int(((Union)"+compileE(x)+").tag()))";
// used for shortcutting sync in bsp supersteps
case BAG():
return "SystemFunctions.bsp_empty_bag";
case TRUE():
return "SystemFunctions.bsp_true_value";
case FALSE():
return "SystemFunctions.bsp_false_value";
case `T():
if (is_collection(T))
return "(new Bag())";
else fail
case `T(e):
if (is_collection(T))
return "(new Bag("+compileE(e)+"))";
else fail
case `T(`a,...el):
if (!is_collection(T))
fail;
String ret = "(new Bag("+compileE(a);
for ( Tree x: el )
ret += ",(MRData)"+compileE(x);
return ret+"))";
case if(`c,`x,`y):
return "((((MR_bool)"+compileE(c)+").get())?"+compileE(x)+":"+compileE(y)+")";
case synchronize(`peer,`b):
return "SystemFunctions.synchronize(((MR_string)"+compileE(peer)+"),(MR_bool)"+compileE(b)+")";
case distribute(`peer,`s):
return "SystemFunctions.distribute(((MR_string)"+compileE(peer)+"),(Bag)"+compileE(s)+")";
case mapReduce(`mx,`my,`s,_):
return "MapReduceAlgebra.mapReduce("+compileF(mx)+","+compileF(my)+",(Bag)("+compileE(s)+"))";
case mapReduce2(`mx,`my,`r,`x,`y,_):
return "MapReduceAlgebra.mapReduce2("+compileF(mx)+","+compileF(my)+","+compileF(r)
+",(Bag)("+compileE(x)+"),(Bag)("+compileE(y)+"))";
case mapJoin(`kx,`ky,`r,`x,`y):
return "MapReduceAlgebra.mapJoin("+compileF(kx)+","+compileF(ky)+","+compileF(r)
+",(Bag)("+compileE(x)+"),(Bag)("+compileE(y)+"))";
case join(`kx,`ky,`r,`x,`y):
return "MapReduceAlgebra.join("+compileF(kx)+","+compileF(ky)+","+compileF(r)
+",(Bag)("+compileE(x)+"),(Bag)("+compileE(y)+"))";
case groupBy(`s):
return "MapReduceAlgebra.groupBy((Bag)("+compileE(s)+"))";
case index(`x,`n):
return "SystemFunctions.index((Bag)("+compileE(x)+"),"+compileE(n)+")";
case range(`x,`i,`j):
return "SystemFunctions.range((Bag)("+compileE(x)+"),"+compileE(i)+","+compileE(j)+")";
case map_index(`x,`key):
return "((Bag)("+compileE(x)+")).map_find("+compileE(key)+")";
case aggregate(`acc,`zero,`s):
return "MapReduceAlgebra.aggregate("+compileF(acc)+","+compileE(zero)+",(Bag)("+compileE(s)+"))";
case Aggregate(`acc,`zero,`s):
return "MapReducePlan.aggregate("+compileF(acc)+","+compileE(zero)+","+compileM(s)+")";
case mergeGroupByJoin(`kx,`ky,`gx,`gy,`acc,`zero,`r,`x,`y,`o):
return "MapReduceAlgebra.mergeGroupByJoin("+compileF(kx)+","+compileF(ky)
+","+compileF(gx)+","+compileF(gy)+","+compileF(acc)+","+compileE(zero)
+","+compileF(r)+",(Bag)"+compileE(x)+",(Bag)"+compileE(y)+")";
case loop(lambda(tuple(...vs),`b),`s,`n):
String fs = "new Function () { final public MRData eval ( final MRData _x ) { ";
for ( int i = 0; i < vs.length(); i++ )
fs += "final MRData "+vs.nth(i)+" = ((Tuple)_x).get("+i+"); ";
return "MapReduceAlgebra.loop("+fs+"return "+compileE(b)+";}},(Tuple)("+compileE(s)
+"),"+((LongLeaf)n).value()+")";
case function(tuple(...params),`tp,`body):
return compileF(e);
case typed(`x,_):
return compileE(x);
case apply(`f,tuple(...args)):
if (!f.is_variable())
fail;
match global_functions.lookup(f.toString()) {
case function(tuple(...params),`otp,`body):
if (is_persistent_type(otp))
fail;
String ret = "UserFunctions_"+user_functions_num+"."+f+"(";
if (args.is_empty())
return ret+")";
for ( int i = 0; i < params.length(); i++ )
match params.nth(i) {
case bind(_,`tp):
ret += ((i==0)?"":",")+"("+get_MR_type(tp)+")"+compileE(args.nth(i));
};
return ret+")";
};
case apply(`f,`arg):
if (!f.is_variable())
fail;
match global_functions.lookup(f.toString()) {
case function(tuple(...params),`otp,`body):
if (is_persistent_type(otp))
fail;
String ac = compileE(arg);
String ret = "UserFunctions_"+user_functions_num+"."+f+"(";
for ( int i = 0; i < params.length(); i++ )
match params.nth(i) {
case bind(_,`tp):
ret += ((i==0)?"":",")+"("+get_MR_type(tp)+")((Tuple)"+ac+").get("+i+")";
};
return ret+")";
};
case apply(`f,`arg):
if (!f.is_variable())
return "("+compileF(f)+").eval("+compileE(arg)+")";
else return "(((Lambda)"+compileE(f)+").lambda().eval("+compileE(arg)+"))";
case Collect(`s):
return "Plan.collect("+compileM(s)+")";
case trace(`x):
return compileE(x);
case _:
return compileM(e);
};
throw new Exception("Cannot compile: "+e);
}
final private static String compileM ( Tree e ) throws Exception {
match e {
case cMap(`f,`s):
return "MapReduceAlgebra.cmap("+compileF(f)+",(Bag)"+compileM(s)+")";
case AggregateMap(`f,`acc,`zero,`s):
return "new Bag(MapReduceAlgebra.aggregate("+compileF(acc)+","+compileE(zero)
+","+compileM(#<cMap(`f,`s)>)+"))";
case MapReduce(`m,`r,`s,_):
return "MapReduceAlgebra.mapReduce("+compileF(m)+","
+compileF(r)+",(Bag)"+compileM(s)+")";
case MapAggregateReduce(`m,`r,`acc,`zero,`s,_):
return "new Bag(MapReduceAlgebra.aggregate("+compileF(acc)
+","+compileE(zero)+","+compileM(#<MapReduce(`m,`r,`s)>)+"))";
case MapCombineReduce(`m,`c,`r,`s,_):
return "MapReduceAlgebra.mapReduce("+compileF(m)
+","+compileF(r)+",(Bag)"+compileM(s)+")";
case MapReduce2(`mx,`my,`c,`r,`x,`y,_):
return "MapReduceAlgebra.mapReduce2("+compileF(mx)+","+compileF(my)
+","+compileF(r)+",(Bag)"+compileM(x)+",(Bag)"+compileM(y)+")";
case MapReduce2(`mx,`my,`r,`x,`y,_):
return "MapReduceAlgebra.mapReduce2("+compileF(mx)+","+compileF(my)
+","+compileF(r)+",(Bag)"+compileM(x)+",(Bag)"+compileM(y)+")";
case MapAggregateReduce2(`mx,`my,`r,`acc,`zero,`x,`y,_):
return "new Bag(MapReduceAlgebra.aggregate("+compileF(acc)+","+compileE(zero)
+","+compileM(#< MapReduce2(`mx,`my,`r,`x,`y)>)+"))";
case MapJoin(`kx,`ky,`r,`x,`y):
return "MapReduceAlgebra.mapJoin("+compileF(kx)+","+compileF(ky)
+","+compileF(r)+",(Bag)"+compileM(x)+",(Bag)"+compileM(y)+")";
case MapAggregateJoin(`kx,`ky,`r,`acc,`zero,`x,`y):
return "new Bag(MapReduceAlgebra.aggregate("+compileF(acc)
+","+compileE(zero)+","+compileM(#<MapJoin(`kx,`ky,`r,`x,`y)>)+"))";
case GroupByJoin(`kx,`ky,`gx,`gy,`acc,`zero,`r,`x,`y,`o):
return "MapReduceAlgebra.groupByJoin("+compileF(kx)+","+compileF(ky)
+","+compileF(gx)+","+compileF(gy)+","+compileF(acc)+","+compileE(zero)
+","+compileF(r)+",(Bag)"+compileM(x)+",(Bag)"+compileM(y)+")";
case CrossProduct(`mx,`my,`r,`x,`y):
return "MapReduceAlgebra.crossProduct("+compileF(mx)+","+compileF(my)
+","+compileF(r)+",(Bag)"+compileM(x)+",(Bag)"+compileM(y)+")";
case CrossAggregateProduct(`mx,`my,`r,`acc,`zero,`x,`y):
return "new Bag(MapReduceAlgebra.aggregate("+compileF(acc)+","+compileE(zero)
+","+compileM(#<CrossProduct(`mx,`my,`r,`x,`y)>)+"))";
case BSPSource(`n,BinarySource(`file,_)):
if (Config.hadoop_mode)
return "Plan.binarySource("+compileE(n)+",((MR_string)"
+compileE(file)+").get())";
else return "(Bag)MapReduceAlgebra.read_binary("+compileE(n)+",((MR_string)"
+compileE(file)+").get())";
case BinarySource(`file,_):
if (Config.hadoop_mode)
return "Plan.binarySource(((MR_string)"+compileE(file)+").get())";
else return "(Bag)MapReduceAlgebra.read_binary(((MR_string)"+compileE(file)+").get())";
case BSPSource(`n,ParsedSource(`parser,`file,...args)):
if (!(n instanceof LongLeaf))
fail;
if (!Config.hadoop_mode)
return "MapReduceAlgebra.parsedSource(((MR_int)"+compileE(n)+").get(),\""
+parser+"\",((MR_string)"+compileE(file)+").get(),"
+reify(args)+")";
Class<? extends Parser> p = DataSource.parserDirectory.get(parser.toString());
if (p == null)
throw new Error("Unknown parser: "+parser);
return "Plan.parsedSource("+p.getName()+".class,((MR_string)"+compileE(file)+").get(),"
+reify(args)+")";
case ParsedSource(`parser,`file,...args):
if (!Config.hadoop_mode)
return "MapReduceAlgebra.parsedSource(\""+parser+"\",((MR_string)"
+compileE(file)+").get(),"+reify(args)+")";
Class<? extends Parser> p = DataSource.parserDirectory.get(parser.toString());
if (p == null)
throw new Error("Unknown parser: "+parser);
return "Plan.parsedSource("+p.getName()+".class,((MR_string)"+compileE(file)+").get(),"
+reify(args)+")";
case Merge(`x,`y):
return "((Bag)"+compileM(x)+").union((Bag)"+compileM(y)+")";
case Generator(`min,`max,`size):
return "MapReduceAlgebra.generator(((MR_long)"+compileE(min)+").get(),"
+"((MR_long)"+compileE(max)+").get())";
case BSP(`n,`superstep,`state,`o,...as):
String ds = "";
for ( Tree a: as )
ds += ",(Bag)("+compileM(a)+")";
return "MapReduceAlgebra.BSP("+((LongLeaf)n).value()+","
+compileF(superstep)+","+compileE(state)+","+o+","
+"new Bag[]{"+ds.substring(1)+"})";
case DataSetCollect(`s):
return "Interpreter.dataSetCollect(\""+s+"\")";
case `v:
if (v.is_variable())
return v.toString();
};
throw new Exception("Cannot compile: "+e);
}
}