package org.rascalmpl.library.experiments.Compiler.RVM.Interpreter; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.ref.SoftReference; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import org.rascalmpl.interpreter.asserts.ImplementationError; import org.rascalmpl.interpreter.result.util.MemoizationCache; import org.rascalmpl.library.experiments.Compiler.RVM.Interpreter.traverse.DescendantDescriptor; import org.rascalmpl.uri.URIResolverRegistry; import org.rascalmpl.uri.URIUtil; import org.rascalmpl.value.IBool; import org.rascalmpl.value.IConstructor; import org.rascalmpl.value.IDateTime; import org.rascalmpl.value.IInteger; import org.rascalmpl.value.IList; import org.rascalmpl.value.IListRelation; import org.rascalmpl.value.IListWriter; import org.rascalmpl.value.IMap; import org.rascalmpl.value.IMapWriter; import org.rascalmpl.value.INode; import org.rascalmpl.value.INumber; import org.rascalmpl.value.IRational; import org.rascalmpl.value.IReal; import org.rascalmpl.value.ISet; import org.rascalmpl.value.ISetRelation; import org.rascalmpl.value.ISetWriter; import org.rascalmpl.value.ISourceLocation; import org.rascalmpl.value.IString; import org.rascalmpl.value.ITuple; import org.rascalmpl.value.IValue; import org.rascalmpl.value.IValueFactory; import org.rascalmpl.value.exceptions.FactTypeUseException; import org.rascalmpl.value.exceptions.InvalidDateTimeException; import org.rascalmpl.value.type.ITypeVisitor; import org.rascalmpl.value.type.Type; import org.rascalmpl.value.type.TypeFactory; import org.rascalmpl.value.type.TypeStore; import org.rascalmpl.values.ValueFactoryFactory; import org.rascalmpl.values.uptr.IRascalValueFactory; import org.rascalmpl.values.uptr.ITree; import org.rascalmpl.values.uptr.ProductionAdapter; import org.rascalmpl.values.uptr.RascalValueFactory; import org.rascalmpl.values.uptr.SymbolAdapter; import org.rascalmpl.values.uptr.TreeAdapter; /* * The primitives that can be called via the CALLPRIM instruction are defined here. * Each primitive with name P (e.g., int_add_int) is defined by: * - an enumeration constant P (e.g., int_add_int) * - a method * int execute(Object[] stack, int sp, int arity, Frame currentFrame, RascalexecutionContext rex) * associated with that enumeration constant. * * The arguments of 'execute' have the following meaning: * * - the current stack * - the current stack pointer (an index in 'stack') * - its arity * - the current stack frame * - the current RascalExecutionContext * * and returns a new stack pointer (an index in 'stack'). * * 'execute' is only allowed to make modifications to the stack and usually returns an IValue * on top of the stack. * * This enumeration is organized in the following sections: * - Creation of values and some utilities on them (~ line 90) * - Readers and writers (~ line 605) * - Operators (~ line 770) * - Type-related operators and functions (~ line 6290) * - String templates (~ line 6748) * - Fields and Field updates (~ line 6849) * - Various getters (~ line 7700) * - Slices ( ~ line 7854) * - Subscripting (~ line 8219) * - Annotations (~ line 8719) * - Type reachability for descendant match (~ line 8792) * - Miscellaneous (~ line 8871) * - Initialization and auxiliary functions (> line 9000) * * Some further clarifications: * - Completely generic primitives like 'add', 'subtract', and 'join' are needed * in cases where they operate on a parameter type. For a function that uses * one or more type parameters, still a single translation is generated that * is shared across all type instantiations of the parameters. Under those circumstances, * there is no static knowldege of the argument types of these primitives and they have to * be determined at run-time. * */ public enum RascalPrimitive { /************************************************************************************************/ /* Creation of values and some utilities on them */ /************************************************************************************************/ /** * Build a constructor * * [ ..., Type type, IValue[] args, Map kwArgs ] => [ ..., constructor value ] * */ constructor { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; Type type = (Type) stack[sp - 3]; IValue[] args = (IValue[]) stack[sp - 2]; @SuppressWarnings("unchecked") Map<String,IValue> kwargs = (Map<String,IValue>) stack[sp - 1]; stack[sp - 3] = vf.constructor(type, args, kwargs); return sp - 2; } }, /** * Build a node, given args and kwArgs * * [ ..., IString name, IValue[] args, Map kwArgs ] => [ ..., node value] * */ node { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; String name = ((IString) stack[sp - 3]).getValue(); IValue[] args = (IValue[]) stack[sp - 2]; @SuppressWarnings("unchecked") Map<String,IValue> kwargs = (Map<String,IValue>) stack[sp - 1]; stack[sp - 3] = vf.node(name, args, kwargs); return sp - 2; } }, /** * Build a node, given args on stack * * [ ..., IString name, IValue arg1, IValue arg2, ... ] => [ ..., name(arg1, arg2, ...) ] */ node_create { @SuppressWarnings("unchecked") @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 1; String name = ((IString) stack[sp - arity]).getValue(); IValue[] args = new IValue[arity - 2]; for(int i = 0; i < arity - 2; i ++){ args[i] = (IValue) stack[sp - arity + 1 + i]; } stack[sp - arity] = vf.node(name, args, (Map<String, IValue>)stack[sp - 1]); return sp - arity + 1; } }, /** * Build a list, given list of elements * * [ ..., IValue[] args ] => [ ..., list value] * */ list { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue[] args = (IValue[]) arg_1; return (args.length == 0) ? emptyList : vf.list(args); } }, /** * Build a list, given elements on stack * * [ ... IValue val1, IValue val2, ... ] => [ ..., [val1, val2, ...] ] */ list_create { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 0; if(arity == 0){ stack[sp] = emptyList; return sp + 1; } IListWriter writer = vf.listWriter(); for (int i = arity - 1; i >= 0; i--) { writer.append((IValue) stack[sp - 1 - i]); } int sp1 = sp - arity + 1; stack[sp1 - 1] = writer.done(); return sp1; } }, /** * size of list * * [ ... IList val] => [ ...,IInteger size ] */ list_size { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.integer(((IList) arg_1).length()); } }, /** * sublist of list * * [ ..., IList lst, IInteger offset, IInteger length ] => [ ..., lst[offset .. offset+length] ] */ sublist { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IList lst = (IList) stack[sp - 3]; int offset = ((IInteger) stack[sp - 2]).intValue(); int length = ((IInteger) stack[sp - 1]).intValue(); stack[sp - 3] = lst.sublist(offset, length); return sp - 2; } }, /** * Build a list relation, given list of elements * * [ ..., IValue[] args ] => [ ..., list relation value] * */ lrel { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue[] args = (IValue[]) arg_1; return (args.length == 0) ? emptyList : vf.list(args); } }, /** * Build a set, given list of elements * * [ ..., IValue[] args ] => [ ..., set value] * */ set { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue[] args = (IValue[]) arg_1; return (args.length == 0) ? emptySet : vf.set(args); } }, /** * Build a set, given elements on stack * * * [ ... IValue val1, IValue val2, ... ] => [ ..., {val1, val2, ...} ] */ set_create { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 0; if(arity == 0){ stack[sp] = emptySet; return sp + 1; } ISetWriter writer = vf.setWriter(); for (int i = arity - 1; i >= 0; i--) { writer.insert((IValue) stack[sp - 1 - i]); } int sp1 = sp - arity + 1; stack[sp1 - 1] = writer.done(); return sp1; } }, /** * Convert single-element set to element * * [ ..., ISet set ] => [ ..., IValue elm ] */ set2elm { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet set = (ISet) arg_1; if(set.size() != 1) throw new CompilerError("set2elm: set should have a single element", rex.getStdErr(), currentFrame); return set.iterator().next(); } }, /** * size of set * * [ ... ISet val] => [ ..., IInteger size ] */ set_size { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet set = (ISet) arg_1; return vf.integer(set.size()); } }, /** * Build a relation, given list of elements * * [ ..., IValue[] args ] => [ ..., relation value] * */ rel { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue[] args = (IValue[]) arg_1; return (args.length == 0) ? emptySet : vf.set(args); } }, /** * Build a tuple, given list of elements * * [ ..., IValue[] args ] => [ ..., tuple value] * */ tuple { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue[] args = (IValue[]) arg_1; return vf.tuple(args); } }, /** * Build a tuple, given elements on stack * * * [ ... IValue val1, IValue val2, ... ] => [ ..., <val1, val2, ...> ] */ tuple_create { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 0; IValue[] elems = new IValue[arity]; for (int i = arity - 1; i >= 0; i--) { elems[i] = (IValue) stack[sp - arity + i]; } int sp1 = sp - arity + 1; stack[sp1 - 1] = vf.tuple(elems); return sp1; } }, /** * Create a map, given key, value pairs on stack * * [ ... IValue key1, IValue val1, IValue key2, IValue val2... ] => [ ..., (key1 : val1, key2 : val2, ...) ] */ map_create { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 0; if(arity == 0){ stack[sp] = emptyMap; return sp + 1; } IMapWriter writer = vf.mapWriter(); for (int i = arity; i > 0; i -= 2) { writer.put((IValue) stack[sp - i], (IValue) stack[sp - i + 1]); } int sp1 = sp - arity + 1; stack[sp1 - 1] = writer.done(); return sp1; } }, /** * Create a loc * [ ..., IString uri ] => [ ..., ISourceLocation l ] */ loc_create { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IString uri = ((IString) arg_1); try { return vf.sourceLocation(URIUtil.createFromEncoded(uri.getValue())); } catch (URISyntaxException e) { // this is actually an unexpected run-time exception since Rascal prevents you from // creating non-encoded return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidURI(uri.getValue(), currentFrame)); } catch (UnsupportedOperationException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidURI(uri.getValue() + ":" + e.getMessage(), currentFrame)); } } }, /** * Create a loc with given offsets and length * [ ..., IString uri, IInteger offset, IInteger length, IInteger beginLine, IInteger beginCol, IInteger endLine, IInteger endCol] => [ ..., ISourceLocation l ] */ loc_with_offset_create { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 5; ISourceLocation loc = (ISourceLocation) stack[sp - arity]; int offset = ((IInteger) stack [sp - arity + 1]).intValue(); int length = ((IInteger) stack [sp - arity + 2]).intValue(); ITuple begin = (ITuple) stack [sp - arity + 3]; int beginLine = ((IInteger) begin.get(0)).intValue(); int beginCol = ((IInteger) begin.get(1)).intValue(); ITuple end = (ITuple) stack [sp - arity + 4]; int endLine = ((IInteger) end.get(0)).intValue(); int endCol = ((IInteger) end.get(1)).intValue(); stack[sp - arity] = vf.sourceLocation(loc, offset, length, beginLine, endLine, beginCol, endCol); return sp - arity + 1; } }, /** * Create a nonterminal value * * [ ..., IValue prod, IValue args ] => [ ..., appl(prod, args) ] */ appl_create { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue prod = (IValue) arg_2; IValue args = (IValue) arg_1; return vf.constructor(RascalValueFactory.Tree_Appl, prod, args); } }, /** * Create a reified type * * [ ..., IConstructor type_cons, IMap definitions ] => [ ..., Type t ] */ reifiedType_create { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IConstructor type_cons = (IConstructor) arg_2; IMap idefinitions = (IMap) arg_1; return IRascalValueFactory.getInstance().reifiedType(type_cons, idefinitions); } }, /*****************************************************************************************************/ /* Readers and writers */ /*****************************************************************************************************/ listwriter_open { @Override public Object execute0(final Frame currentFrame, final RascalExecutionContext rex) { return vf.listWriter(); } }, /** * Add values to a list writer * * [ ..., IListWriter e, IValue arg1, IValue arg2, ... ] => [ ..., IListWriter e] * */ listwriter_add { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity > 0; IListWriter writer = (IListWriter) stack[sp - arity]; for(int i = arity - 1; i > 0; i--){ writer.append((IValue) stack[sp - i]); } return sp - arity + 1; } }, listwriter_close { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IListWriter writer = (IListWriter) arg_1; return writer.done(); } }, setwriter_open { @Override public Object execute0(final Frame currentFrame, final RascalExecutionContext rex) { return vf.setWriter(); } }, /** * Add values to a set writer * * [ ..., ISetWriter e, IValue arg1, IValue arg2, ... ] => [ ..., ISetWriter e] * */ setwriter_add { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity > 0; ISetWriter writer = (ISetWriter) stack[sp - arity]; for(int i = arity - 1; i > 0; i--){ writer.insert((IValue) stack[sp - i]); } return sp - arity + 1; } }, setwriter_close { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISetWriter writer = (ISetWriter) arg_1; return writer.done(); } }, mapwriter_open { @Override public Object execute0(final Frame currentFrame, final RascalExecutionContext rex) { return vf.mapWriter(); } }, /** * Add values to a map writer * * [ ..., IMapWriter e, IValue key1, IValue val1, IValue key2, IValue val2, ... ] => [ ..., IMapWriter e] * */ mapwriter_add { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IMapWriter writer = (IMapWriter) stack[sp - 3]; writer.insert(vf.tuple((IValue) stack[sp - 2], (IValue) stack[sp - 1])); return sp - 2; } }, mapwriter_close { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IMapWriter writer = (IMapWriter) arg_1; return writer.done(); } }, /** * Create a string writer * * [ ... ] => [ ..., new StringBuilder ] */ stringwriter_open { @Override public Object execute0(final Frame currentFrame, final RascalExecutionContext rex) { return new StringBuilder(); } }, /** * Add a value to a stringwriter * * [ ... StringBuilder sb, IValue val] => [ ..., sb with val appended ] */ stringwriter_add { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { StringBuilder b = (StringBuilder) arg_2; IValue v = ((IValue) arg_1); String s; if(v.getType().isString()){ s = ((IString) v).getValue(); } else { s = v.toString(); } return b.append(s); } }, /** * Close a stringwriter * * [ ... StringBuilder sb] => [ ..., IString string value of stringwriter ] */ stringwriter_close { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { StringBuilder b = (StringBuilder) arg_1; return vf.string(b.toString()); } }, /********************************************************************************************************/ /* Operators */ /********************************************************************************************************/ /** * Definitions of all operators. The general strategy is to define a gegenric version of each operator (e.g. 'add') that * works for all argument types as well as a collection of specialized versions (e.g., 'int_add_int') that only work for specific argument types * * The following operators are defined here: * addition * compose * division * equal * greater * greaterequal * in * intersect * join * less * lessequal * mod * negative * notequal * notin * non_negative * product * remainder * subtract * transitive_closure * transitive_reflexive_closure */ /** * addition * * [ ... IValue val1, IValue val2] => [ ..., val1 + val2] * * infix Addition "+" * { * &L <: num x &R <: num -> LUB(&L, &R), * list[&L] x list[&R] -> list[LUB(&L,&R)], * list[&L] x &R -> list[LUB(&L,&R)] when &R is not a list, * &L x list[&R <: &L] -> list[LUB(&L,&R)] when &L is not a list, * set[&L] x set[&R] -> set[LUB(&L,&R)], * set[&L] x &R -> set[LUB(&L,&R)] when &R is not a list, * &L x set[&R] -> set[LUB(&L,&R)] when &L is not a list, * map[&K1,&V1] x map[&K2,&V2] -> map[LUB(&K1,&K2), LUB(&V1,&V2)], * str x str -> str, * loc x str -> loc, * tuple[&L1,&L2] x tuple[&R1,&R2,&R3] -> tuple[&L1,&L2,&R1,&R2,&R3] * } */ /** * See general remark about generic primitives */ add { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue lhs = ((IValue) arg_2); IValue rhs = ((IValue) arg_1); ToplevelType lhsType = ToplevelType.getToplevelType(lhs.getType()); ToplevelType rhsType = ToplevelType.getToplevelType(rhs.getType()); switch (lhsType) { case INT: switch (rhsType) { case INT: return int_add_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return int_add_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return int_add_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return int_add_rat.execute2(lhs, rhs, currentFrame, rex); case LIST: return elm_add_list.execute2(lhs, rhs, currentFrame, rex); case SET: return elm_add_list.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case NUM: switch (rhsType) { case INT: return num_add_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return num_add_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return num_add_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return num_add_rat.execute2(lhs, rhs, currentFrame, rex); case LIST: return elm_add_list.execute2(lhs, rhs, currentFrame, rex); case SET: return elm_add_list.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case REAL: switch (rhsType) { case INT: return real_add_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return real_add_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return real_add_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return real_add_rat.execute2(lhs, rhs, currentFrame, rex); case LIST: return elm_add_list.execute2(lhs, rhs, currentFrame, rex); case SET: return elm_add_list.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case RAT: switch (rhsType) { case INT: return rat_add_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return rat_add_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return rat_add_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return rat_add_rat.execute2(lhs, rhs, currentFrame, rex); case LIST: return elm_add_list.execute2(lhs, rhs, currentFrame, rex); case SET: return elm_add_list.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case SET: return set_add_elm.execute2(lhs, rhs, currentFrame, rex); case LIST: return list_add_elm.execute2(lhs, rhs, currentFrame, rex); case LOC: switch (rhsType) { case STR: return loc_add_str.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case LREL: switch (rhsType) { case LIST: return lrel_add_list.execute2(lhs, rhs, currentFrame, rex); case LREL: return lrel_add_lrel.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case MAP: switch (rhsType) { case MAP: return map_add_map.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case REL: switch (rhsType) { case SET: return rel_add_set.execute2(lhs, rhs, currentFrame, rex); case REL: return rel_add_rel.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case STR: switch (rhsType) { case STR: return str_add_str.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case TUPLE: switch (rhsType) { case TUPLE: return tuple_add_tuple.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } default: switch (rhsType) { case SET: return elm_add_set.execute2(lhs, rhs, currentFrame, rex); case LIST: return elm_add_list.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive add: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } } } }, /** * addition on int and int * * [ ... IInteger val1, IInteger val2] => [ ..., val1 + val2] */ int_add_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).add((IInteger) arg_1); } }, /** * addition on int and num * * [ ... IInteger val1, INumber val2] => [ ..., val1 + val2] */ int_add_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).add((INumber) arg_1); } }, /** * addition on int and rational * * [ ... IInteger val1, IRational val2] => [ ..., val1 + val2] */ int_add_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).add((IRational) arg_1); } }, /** * addition on int and real * * [ ... IInteger val1, IReal val2] => [ ..., val1 + val2] */ int_add_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).add((IReal) arg_1); } }, /** * addition on num and int * * [ ... INumber val1, IInteger val2] => [ ..., val1 + val2] */ num_add_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).add((IInteger) arg_1); } }, /** * addition on num and num * * [ ... INumber val1, INumber val2] => [ ..., val1 + val2] */ num_add_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).add((INumber) arg_1); } }, /** * addition on num and rat * * [ ... INumber val1, IRational val2] => [ ..., val1 + val2] */ num_add_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).add((IRational) arg_1); } }, /** * addition on num and real * * [ ... INumber val1, IReal val2] => [ ..., val1 + val2] */ num_add_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).add((IReal) arg_1); } }, /** * addition on rat and int * * [ ... IRational val1, IInteger val2] => [ ..., val1 + val2] */ rat_add_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).add((IInteger) arg_1); } }, /** * addition on rat and num * * [ ... IRational val1, INumber val2] => [ ..., val1 + val2] */ rat_add_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).add((INumber) arg_1); } }, /** * addition on rat and rat * * [ ... IRational val1, IRational val2] => [ ..., val1 + val2] */ rat_add_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).add((IRational) arg_1); } }, /** * addition on rat and real * * [ ... IRational val1, Ireal val2] => [ ..., val1 + val2] */ rat_add_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).add((IReal) arg_1); } }, /** * addition on real and num * * [ ... IReal val1, INumber val2] => [ ..., val1 + val2] */ real_add_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).add((INumber) arg_1); } }, /** * addition on real and int * * [ ... IReal val1, IInteger val2] => [ ..., val1 + val2] */ real_add_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).add((IInteger) arg_1); } }, /** * addition on real and real * * [ ... IReal val1, Ireal val2] => [ ..., val1 + val2] */ real_add_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).add((IReal) arg_1); } }, /** * addition on real and rat * * [ ... IReal val1, IRational val2] => [ ..., val1 + val2] */ real_add_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).add((IRational) arg_1); } }, // Add on non-numeric types /** * addition on list and list * * [ ... IList val1, IList val2] => [ ..., val1 + val2] */ list_add_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IList) arg_2).concat((IList) arg_1); } }, /** * addition on list and element * * [ ... IList val1, IValue val2] => [ ..., val1 + val2] */ list_add_elm { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IList) arg_2).append((IValue) arg_1); } }, /** * addition on element and list * * [ ... IValue val1, IList val2] => [ ..., val1 + val2] */ elm_add_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IList) arg_1).insert((IValue) arg_2); } }, /** * addition on list and list relation * * [ ... IList val1, IListRelation val2] => [ ..., val1 + val2] */ list_add_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_add_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * addition on list relation and list relation * * [ ... IListRelation val1, IListRelation val2] => [ ..., val1 + val2] */ lrel_add_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_add_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * addition on list relation and list * * [ ... IListRelation val1, IList val2] => [ ..., val1 + val2] */ lrel_add_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_add_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * addition on list relation and element * * [ ... IListRelation val1, IValue val2] => [ ..., val1 + val2] */ lrel_add_elm { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_add_elm.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * addition on element and list relation * * [ ... IListRelation val1, IValue val2] => [ ..., val1 + val2] */ elm_add_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return elm_add_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * addition on loc and str * * [ ... ISourceLocation val1, IString val2] => [ ..., val1 + val2] */ loc_add_str { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISourceLocation sloc = (ISourceLocation) arg_2; String s = ((IString) arg_1).getValue(); String path = sloc.hasPath() ? sloc.getPath() : ""; if(!path.endsWith("/")){ path = path + "/"; } path = path.concat(s); return $loc_field_update(sloc, "path", vf.string(path), currentFrame, rex); } }, /** * addition on map and map * * [ ... IMap val1, IMap val2] => [ ..., val1 + val2] */ map_add_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IMap) arg_2).join((IMap) arg_1); } }, /** * addition on set and element * * [ ... ISet val1, IValue val2] => [ ..., val1 + val2] */ set_add_elm { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((ISet) arg_2).insert((IValue) arg_1); } }, /** * addition on element and set * * [ ... IValue val1, ISet val2] => [ ..., val1 + val2] */ elm_add_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((ISet) arg_1).insert((IValue) arg_2); } }, /** * addition on set and set * * [ ... ISet val1, ISet val2] => [ ..., val1 + val2] */ set_add_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((ISet) arg_2).union((ISet) arg_1); } }, /** * addition on set and relation * * [ ... ISet val1, IRelation val2] => [ ..., val1 + val2] */ set_add_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_add_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * addition on rel and rel * * [ ... IRelation val1, IRelation val2] => [ ..., val1 + val2] */ rel_add_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((ISet) arg_2).union((ISet) arg_1); } }, /** * addition on rel and set * * [ ... IRelation val1, ISet val2] => [ ..., val1 + val2] */ rel_add_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_add_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * addition on rel and element * * [ ... IRelation val1, IValue val2] => [ ..., val1 + val2] */ rel_add_elm { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_add_elm.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * addition on element and rel * * [ ... IValue val1, IRelation val2] => [ ..., val1 + val2] */ elm_add_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return elm_add_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * addition on str and str * * [ ... IString val1, IString val2] => [ ..., val1 + val2] */ str_add_str { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 2; if(arity == 2){ stack[sp - 2] = ((IString) stack[sp - 2]).concat((IString) stack[sp - 1]); return sp - 1; } else { StringWriter w = new StringWriter(); for(int i = 0; i < arity; i++){ w.append(((IString)stack[sp - arity + i]).getValue()); } stack[sp - arity] = vf.string(w.toString()); return sp - arity + 1; } } }, /** * addition on tuple and tuple * * [ ... ITuple val1, ITuple val2] => [ ..., val1 + val2] */ tuple_add_tuple { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITuple t1 = (ITuple) arg_2; ITuple t2 = (ITuple) arg_1; int len1 = t1.arity(); int len2 = t2.arity(); IValue elems[] = new IValue[len1 + len2]; for(int i = 0; i < len1; i++) elems[i] = t1.get(i); for(int i = 0; i < len2; i++) elems[len1 + i] = t2.get(i); return vf.tuple(elems); } }, /** * subtraction on arbitary values * * [ ..., IValue val1, IValue val2 ] => [ ..., val1 - val2 ] * * infix Difference "-" { * &L <: num x &R <: num -> LUB(&L, &R), * list[&L] x list[&R] -> list[LUB(&L,&R)], * set[&L] x set[&R] -> set[LUB(&L,&R)], * map[&K1,&V1] x map[&K2,&V2] -> map[LUB(&K1,&K2), LUB(&V1,&V2)] * } */ /** * See general remark about generic primitives */ subtract { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue lhs = ((IValue) arg_2); IValue rhs = ((IValue) arg_1); ToplevelType lhsType = ToplevelType.getToplevelType(lhs.getType()); ToplevelType rhsType = ToplevelType.getToplevelType(rhs.getType()); switch (lhsType) { case INT: switch (rhsType) { case INT: return int_subtract_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return int_subtract_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return int_subtract_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return int_subtract_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, currentFrame); } case NUM: switch (rhsType) { case INT: return num_subtract_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return num_subtract_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return num_subtract_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return num_subtract_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, currentFrame); } case REAL: switch (rhsType) { case INT: return real_subtract_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return real_subtract_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return real_subtract_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return real_subtract_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, currentFrame); } case RAT: switch (rhsType) { case INT: return rat_subtract_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return rat_subtract_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return rat_subtract_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return rat_subtract_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, currentFrame); } default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, currentFrame); } } }, /** * subtraction on int and int * * [ ..., IInteger val1, IInteger val2 ] => [ ..., val1 - val2 ] */ int_subtract_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).subtract((IInteger) arg_1); } }, /** * subtraction on int and num * * [ ..., IInteger val1, INumber val2 ] => [ ..., val1 - val2 ] */ int_subtract_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).subtract((INumber) arg_1); } }, /** * subtraction on int and rat * * [ ..., IInteger val1, IRational val2 ] => [ ..., val1 - val2 ] */ int_subtract_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).subtract((IRational) arg_1); } }, /** * subtraction on int and real * * [ ..., IInteger val1, IReal val2 ] => [ ..., val1 - val2 ] */ int_subtract_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).subtract((IReal) arg_1); } }, /** * subtraction on num and int * * [ ..., INumber val1, IInteger val2 ] => [ ..., val1 - val2 ] */ num_subtract_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).subtract((IInteger) arg_1); } }, /** * subtraction on num and num * * [ ..., INumber val1, INumber val2 ] => [ ..., val1 - val2 ] */ num_subtract_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).subtract((INumber) arg_1); } }, /** * subtraction on num and rat * * [ ..., INumber val1, IRational val2 ] => [ ..., val1 - val2 ] */ num_subtract_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).subtract((IRational) arg_1); } }, /** * subtraction on num and inrealt * * [ ..., INumber val1, IReal val2 ] => [ ..., val1 - val2 ] */ num_subtract_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).subtract((IReal) arg_1); } }, /** * subtraction on rat and int * * [ ..., IRational val1, IInteger val2 ] => [ ..., val1 - val2 ] */ rat_subtract_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).subtract((IInteger) arg_1); } }, /** * subtraction on rat and inumnt * * [ ..., IRational val1, INumber val2 ] => [ ..., val1 - val2 ] */ rat_subtract_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).subtract((INumber) arg_1); } }, /** * subtraction on rat and rat * * [ ..., IRational val1, IRational val2 ] => [ ..., val1 - val2 ] */ rat_subtract_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).subtract((IRational) arg_1); } }, /** * subtraction on rat and real * * [ ..., IRational val1, IReal val2 ] => [ ..., val1 - val2 ] */ rat_subtract_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).subtract((IReal) arg_1); } }, /** * subtraction on real and number * * [ ..., IReal val1, INumber val2 ] => [ ..., val1 - val2 ] */ real_subtract_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).subtract((INumber) arg_1); } }, /** * subtraction on real and int * * [ ..., IReal val1, IInteger val2 ] => [ ..., val1 - val2 ] */ real_subtract_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).subtract((IInteger) arg_1); } }, /** * subtraction on real and real * * [ ..., IReal val1, IReal val2 ] => [ ..., val1 - val2 ] */ real_subtract_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).subtract((IReal) arg_1); } }, /** * subtraction on real and rat * * [ ..., IReal val1, IRational val2 ] => [ ..., val1 - val2 ] */ real_subtract_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).subtract((IRational) arg_1); } }, /** * subtraction on list and element * * [ ..., IList val1, IValue val2 ] => [ ..., val1 - val2 ] */ list_subtract_elm { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IList) arg_2).delete((IValue) arg_1); } }, /** * subtraction on list and list * * [ ..., IList val1, IList val2 ] => [ ..., val1 - val2 ] */ list_subtract_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IList) arg_2).subtract((IList) arg_1); } }, /** * subtraction on list and list relation * * [ ..., IList val1, IListRelation val2 ] => [ ..., val1 - val2 ] */ list_subtract_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_subtract_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * subtraction on list relation and list relation * * [ ..., IListRelation val1, IListRelation val2 ] => [ ..., val1 - val2 ] */ lrel_subtract_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_subtract_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * subtraction on list relation and list * * [ ..., IList val1, IListRelation val2 ] => [ ..., val1 - val2 ] */ lrel_subtract_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_subtract_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * subtraction on list relation and element * * [ ..., IListRelation val1, IValue val2 ] => [ ..., val1 - val2 ] */ lrel_subtract_elm { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_subtract_elm.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * subtraction on maps * * [ ..., IMap val1, IMap val2 ] => [ ..., val1 - val2 ] */ map_subtract_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IMap) arg_2).remove((IMap) arg_1); } }, /** * subtraction on rel * * [ ..., IRelation val1, IRelation val2 ] => [ ..., val1 - val2 ] */ rel_subtract_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_subtract_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * subtraction on rel and set * * [ ..., IRelation val1, ISet val2 ] => [ ..., val1 - val2 ] */ rel_subtract_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_subtract_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * subtraction on rel and element * * [ ..., IRelation val1, IValue val2 ] => [ ..., val1 - val2 ] */ rel_subtract_elm { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_subtract_elm.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * subtraction on set and element * * [ ..., ISet val1, IValue val2 ] => [ ..., val1 - val2 ] */ set_subtract_elm { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((ISet) arg_2).delete((IValue) arg_1); } }, /** * subtraction on set * * [ ..., ISet val1, ISet val2 ] => [ ..., val1 - val2 ] */ set_subtract_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((ISet) arg_2).subtract((ISet) arg_1); } }, /** * subtraction on set and rel * * [ ..., ISet val1, IRelation val2 ] => [ ..., val1 - val2 ] */ set_subtract_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_subtract_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * product of arbitrary values * * [ ..., IValue val1, IValue val2 ] => [ ..., val1 * val2 ] * * infix Product "*" { * &L <: num x &R <: num -> LUB(&L, &R), * list[&L] x list[&R] -> lrel[&L,&R], * set[&L] x set[&R] -> rel[&L,&R] * } */ /** * See general remark about generic primitives */ product { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue lhs = ((IValue) arg_2); IValue rhs = ((IValue) arg_1); ToplevelType lhsType = ToplevelType.getToplevelType(lhs.getType()); ToplevelType rhsType = ToplevelType.getToplevelType(rhs.getType()); switch (lhsType) { case INT: switch (rhsType) { case INT: return int_product_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return int_product_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return int_product_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return int_product_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case NUM: switch (rhsType) { case INT: return num_product_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return num_product_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return num_product_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return num_product_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case REAL: switch (rhsType) { case INT: return real_product_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return real_product_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return real_product_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return real_product_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case RAT: switch (rhsType) { case INT: return rat_product_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return rat_product_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return rat_product_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return rat_product_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } default: throw new CompilerError("Illegal type combination: " + lhsType + " and " + rhsType, currentFrame); } } }, /** * product of int and int * * [ ..., IInteger val1, IInteger val2 ] => [ ..., val1 * val2 ] */ int_product_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).multiply((IInteger) arg_1); } }, /** * product of int and num * * [ ..., IInteger val1, INumber val2 ] => [ ..., val1 * val2 ] */ int_product_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).multiply((INumber) arg_1); } }, /** * product of int and rat * * [ ..., IInteger val1, IRational val2 ] => [ ..., val1 * val2 ] */ int_product_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).multiply((IRational) arg_1); } }, /** * product of int and real * * [ ..., IInteger val1, IReal val2 ] => [ ..., val1 * val2 ] */ int_product_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).multiply((IReal) arg_1); } }, /** * product of num and int * * [ ..., INumber val1, IInteger val2 ] => [ ..., val1 * val2 ] */ num_product_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).multiply((IInteger) arg_1); } }, /** * product of num and num * * [ ..., INumber val1, INumber val2 ] => [ ..., val1 * val2 ] */ num_product_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).multiply((INumber) arg_1); } }, /** * product of num and rat * * [ ..., INumber val1, IRational val2 ] => [ ..., val1 * val2 ] */ num_product_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).multiply((IRational) arg_1); } }, /** * product of num and real * * [ ..., INumber val1, IReal val2 ] => [ ..., val1 * val2 ] */ num_product_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).multiply((IReal) arg_1); } }, /** * product of rat and int * * [ ..., IRational val1, IInteger val2 ] => [ ..., val1 * val2 ] */ rat_product_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).multiply((IInteger) arg_1); } }, /** * product of rat and num * * [ ..., IRational val1, INumber val2 ] => [ ..., val1 * val2 ] */ rat_product_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).multiply((INumber) arg_1); } }, /** * product of rat and rat * * [ ..., IRational val1, IRational val2 ] => [ ..., val1 * val2 ] */ rat_product_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).multiply((IRational) arg_1); } }, /** * product of rat and real * * [ ..., IRational val1, IReal val2 ] => [ ..., val1 * val2 ] */ rat_product_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).multiply((IReal) arg_1); } }, /** * product of real and num * * [ ..., IReal val1, INumber val2 ] => [ ..., val1 * val2 ] */ real_product_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).multiply((INumber) arg_1); } }, /** * product of real and int * * [ ..., IReal val1, IInteger val2 ] => [ ..., val1 * val2 ] */ real_product_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).multiply((IInteger) arg_1); } }, /** * product of real and real * * [ ..., IReal val1, IReal val2 ] => [ ..., val1 * val2 ] */ real_product_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).multiply((IReal) arg_1); } }, /** * product of real and rat * * [ ..., IReal val1, IRational val2 ] => [ ..., val1 * val2 ] */ real_product_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).multiply((IRational) arg_1); } }, /** * product of lists * * [ ..., IList val1, IList val2 ] => [ ..., val1 * val2 ] */ list_product_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList left = (IList) arg_2; IList right = (IList) arg_1; IListWriter w = vf.listWriter(); for(IValue l : left){ for(IValue r : right){ w.append(vf.tuple(l,r)); } } return w.done(); } }, /** * product of list relations * * [ ..., IListRelation val1, IListRelation val2 ] => [ ..., val1 * val2 ] */ lrel_product_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_product_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * product of sets * * [ ..., ISet val1, ISet val2 ] => [ ..., val1 * val2 ] */ set_product_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet left = (ISet) arg_2; ISet right = (ISet) arg_1; ISetWriter w = vf.setWriter(); for(IValue l : left){ for(IValue r : right){ w.insert(vf.tuple(l,r)); } } return w.done(); } }, /** * product of rel * * [ ..., IRelation val1, IRelation val2 ] => [ ..., val1 * val2 ] */ rel_product_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_product_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * remainder on arbitrary values * * [ ... IValue val1, IValue val2 ] => [ ..., val1 % val2 ] */ /** * See general remark about generic primitives */ remainder { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue lhs = ((IValue) arg_2); IValue rhs = ((IValue) arg_1); if(lhs.getType().isInteger() && rhs.getType().isInteger()){ return int_remainder_int.execute2(lhs, rhs, currentFrame, rex); } throw new CompilerError("remainder: unexpected type combination" + lhs.getType() + " and " + rhs.getType(), currentFrame); } }, /** * remainder on int and int * * [ ... IInteger val1, IINteger val2 ] => [ ..., val1 % val2 ] */ int_remainder_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).remainder((IInteger) arg_1); } }, /** *composition * * [ ... IValue val1, IValue val2] => [ ..., val1 o val2] * * infix Composition "o" { * lrel[&A,&B] x lrel[&B,&C] -> lrel[&A,&C], * rel[&A,&B] x rel[&B,&C] -> rel[&A,&C], * map[&A,&B] x map[&B,&C] -> map[&A,&C] * } */ /** * See general remark about generic primitives */ compose { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue left = (IValue) arg_2; Type leftType = left.getType(); IValue right = (IValue) arg_1; switch (ToplevelType.getToplevelType(leftType)) { case LREL: return lrel_compose_lrel.execute2(left, right, currentFrame, rex); case REL: return rel_compose_rel.execute2(left, right, currentFrame, rex); case MAP: return map_compose_map.execute2(left, right, currentFrame, rex); default: throw new CompilerError("RascalPrimtive compose: unexpected type " + leftType, rex.getStdErr(), currentFrame); } } }, /** * compose lrel and lrel * * [ ... IListRelation val1, IListRelation val2] => [ ..., val1 o val2] */ lrel_compose_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IListRelation<IList> left = ((IList) arg_2).asRelation(); IListRelation<IList> right = ((IList) arg_1).asRelation(); return left.compose(right); } }, /** * compose rel and rel * * [ ... IRelation val1, IRelation val2] => [ ..., val1 o val2] */ rel_compose_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISetRelation<ISet> left = ((ISet) arg_2).asRelation(); ISetRelation<ISet> right = ((ISet) arg_1).asRelation(); return left.compose(right); } }, /** * compose map and map * * [ ... IMap val1, IMap val2] => [ ..., val1 o val2] */ map_compose_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IMap) arg_2).compose((IMap) arg_1); } }, /** * modulo * * [ ... IValue val1, IValue val2] => [ ..., val1 mod val2] */ /** * See general remark about generic primitives */ mod { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue lhs = ((IValue) arg_2); IValue rhs = ((IValue) arg_1); if(lhs.getType().isInteger() && rhs.getType().isInteger()){ return int_mod_int.execute2(lhs, rhs, currentFrame, rex); } throw new CompilerError("RascalPrimitive mod: unexpected type combination" + lhs.getType() + " and " + rhs.getType(), rex.getStdErr(), currentFrame); } }, /** * modulo on int and int * * [ ... IValue val1, IValue val2] => [ ..., val1 mod val2] */ int_mod_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).mod((IInteger) arg_1); } }, /** * division * * * [ ... IValue val1, IValue val2] => [ ..., val1 / val2] * * infix Division "/" { &L <: num x &R <: num -> LUB(&L, &R) } */ /** * See general remark about generic primitives */ divide { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue lhs = ((IValue) arg_2); IValue rhs = ((IValue) arg_1); ToplevelType lhsType = ToplevelType.getToplevelType(lhs.getType()); ToplevelType rhsType = ToplevelType.getToplevelType(rhs.getType()); switch (lhsType) { case INT: switch (rhsType) { case INT: return int_divide_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return int_divide_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return int_divide_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return int_divide_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive divide: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case NUM: switch (rhsType) { case INT: return num_divide_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return num_divide_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return num_divide_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return num_divide_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive divide: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case REAL: switch (rhsType) { case INT: return real_divide_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return real_divide_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return real_divide_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return real_divide_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive divide: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } case RAT: switch (rhsType) { case INT: return rat_divide_int.execute2(lhs, rhs, currentFrame, rex); case NUM: return rat_divide_num.execute2(lhs, rhs, currentFrame, rex); case REAL: return rat_divide_real.execute2(lhs, rhs, currentFrame, rex); case RAT: return rat_divide_rat.execute2(lhs, rhs, currentFrame, rex); default: throw new CompilerError("RascalPrimitive divide: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } default: throw new CompilerError("RascalPrimitive divide: Illegal type combination: " + lhsType + " and " + rhsType, rex.getStdErr(), currentFrame); } } }, /** * divide on int and int * * [ ... IInteger val1, IInteger val2] => [ ..., val1 / val2] */ int_divide_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IInteger) arg_2).divide((IInteger) arg_1); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on int and num * * [ ... IInteger val1, INumber val2] => [ ..., val1 / val2] */ int_divide_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IInteger) arg_2).divide((INumber) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on int and rat * * [ ... IInteger val1, IRational val2] => [ ..., val1 / val2] */ int_divide_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IInteger) arg_2).divide((IRational) arg_1); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on int and real * * [ ... IInteger val1, IReal val2] => [ ..., val1 / val2] */ int_divide_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IInteger) arg_2).divide((IReal) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on num and int * * [ ... INumber val1, IInteger val2] => [ ..., val1 / val2] */ num_divide_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((INumber) arg_2).divide((IInteger) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on num and num * * [ ... INumber val1, INumber val2] => [ ..., val1 / val2] */ num_divide_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((INumber) arg_2).divide((INumber) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on num and rat * * [ ... INumber val1, IRational val2] => [ ..., val1 / val2] */ num_divide_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((INumber) arg_2).divide((IRational) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on num and real * * [ ... INumber val1, IReal val2] => [ ..., val1 / val2] */ num_divide_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((INumber) arg_2).divide((IReal) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on rat and int * * [ ... IRational val1, IInteger val2] => [ ..., val1 / val2] */ rat_divide_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IRational) arg_2).divide((IInteger) arg_1); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on rat and num * * [ ... IRational val1, INumber val2] => [ ..., val1 / val2] */ rat_divide_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IRational) arg_2).divide((INumber) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on rat and rat * * [ ... IRational val1, IRational val2] => [ ..., val1 / val2] */ rat_divide_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IRational) arg_2).divide((IRational) arg_1); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on rat and real * * [ ... IRational val1, IReal val2] => [ ..., val1 / val2] */ rat_divide_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IRational) arg_2).divide((IReal) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on real and num * * [ ... IReal val1, INumber val2] => [ ..., val1 / val2] */ real_divide_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IReal) arg_2).divide((INumber) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on real and int * * [ ... IReal val1, IInteger val2] => [ ..., val1 / val2] */ real_divide_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IReal) arg_2).divide((IInteger) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on real and real * * [ ... IReal val1, IReal val2] => [ ..., val1 / val2] */ real_divide_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IReal) arg_2).divide((IReal) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /** * divide on real and rat * * [ ... IReal val1, IRational val2] => [ ..., val1 / val2] */ real_divide_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { return ((IReal) arg_2).divide((IRational) arg_1, vf.getPrecision()); } catch(ArithmeticException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.arithmeticException("divide by zero", currentFrame)); } } }, /* * equal */ /** * equal on int and int * * [ ... IInteger val1, IInteger val2] => [ ..., val1 == val2] */ int_equal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).equal((IInteger) arg_1); } }, /** * equal on int and num * * [ ... IInteger val1, INumber val2] => [ ..., val1 == val2] */ int_equal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).equal((INumber) arg_1); } }, /** * equal on int and rat * * [ ... IInteger val1, IRational val2] => [ ..., val1 == val2] */ int_equal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).equal((IRational) arg_1); } }, /** * equal on int and real * * [ ... IInteger val1, IReal val2] => [ ..., val1 == val2] */ int_equal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).equal((IReal) arg_1); } }, /** * equal on num and int * * [ ... INumber val1, IInteger val2] => [ ..., val1 == val2] */ num_equal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).equal((IInteger) arg_1); } }, /** * equal on num and num * * [ ... INumber val1, INumber val2] => [ ..., val1 == val2] */ num_equal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).equal((INumber) arg_1); } }, /** * equal on num and rat * * [ ... INumber val1, IRational val2] => [ ..., val1 == val2] */ num_equal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).equal((IRational) arg_1); } }, /** * equal on num and real * * [ ... INumber val1, IReal val2] => [ ..., val1 == val2] */ num_equal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).equal((IReal) arg_1); } }, /** * equal on real and int * * [ ... IReal val1, IInteger val2] => [ ..., val1 == val2] */ real_equal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).equal((IInteger) arg_1); } }, /** * equal on real and num * * [ ... IReal val1, INumber val2] => [ ..., val1 == val2] */ real_equal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).equal((INumber) arg_1); } }, /** * equal on real and rat * * [ ... IReal val1, IRational val2] => [ ..., val1 == val2] */ real_equal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).equal((IRational) arg_1); } }, /** * equal on real and real * * [ ... IReal val1, IReal val2] => [ ..., val1 == val2] */ real_equal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).equal((IReal) arg_1); } }, /** * equal on rat and int * * [ ... IRational val1, IInteger val2] => [ ..., val1 == val2] */ rat_equal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).equal((IInteger) arg_1); } }, /** * equal on rat and num * * [ ... IRational val1, INumber val2] => [ ..., val1 == val2] */ rat_equal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).equal((INumber) arg_1); } }, /** * equal on rat and rat * * [ ... IRational val1, IRational val2] => [ ..., val1 == val2] */ rat_equal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).equal((IRational) arg_1); } }, /** * equal on rat and real * * [ ... IRational val1, IReal val2] => [ ..., val1 == val2] */ rat_equal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).equal((IReal) arg_1); } }, /** * equal on node and node * * [ ... INode val1, INode val2] => [ ..., val1 == val2] */ node_equal_node { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode leftNode = (INode) arg_2; INode rightNode = (INode) arg_1; int leftArity = leftNode.arity(); int rightArity = rightNode.arity(); if(leftArity != rightArity || !leftNode.getName().equals(rightNode.getName())){ return Rascal_FALSE; } for(int i = 0; i < leftArity; i++){ if(!$equal(leftNode.get(i), rightNode.get(i), currentFrame, rex).getValue()){ return Rascal_FALSE; } } return Rascal_TRUE; } }, // equal on other types /** * equal on arbitrary types * * [ ... IValue val1, IValue val2] => [ ..., val1 == val2] */ /** * See general remark about generic primitives */ equal { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue left = (IValue)arg_2; IValue right = (IValue)arg_1; if(left.getType().isNumber() && right.getType().isNumber()){ return num_equal_num.execute2(left,right, currentFrame, rex); } else if(left.getType().isNode() && right.getType().isNode()){ return node_equal_node.execute2(left, right, currentFrame, rex); } else { return vf.bool(left.isEqual(right)); } } }, /** * equal on types * * [ ... Type type1, Type type2] => [ ..., type1 == type2] */ type_equal_type { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((Type) arg_2) == ((Type) arg_1)); } }, // ==== greater /** * greater-than on int and int * * [ ... IInteger val1, IInteger val2] => [ ..., val1 > val2] */ int_greater_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).greater((IInteger) arg_1); } }, /** * greater-than on int and num * * [ ... IInteger val1, INumber val2] => [ ..., val1 > val2] */ int_greater_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).greater((INumber) arg_1); } }, /** * greater-than on int and rat * * [ ... IInteger val1, IRational val2] => [ ..., val1 > val2] */ int_greater_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).greater((IRational) arg_1); } }, /** * greater-than on int and real * * [ ... IInteger val1, IReal val2] => [ ..., val1 > val2] */ int_greater_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).greater((IReal) arg_1); } }, /** * greater-than on num and int * * [ ... INumber val1, IInteger val2] => [ ..., val1 > val2] */ num_greater_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).greater((IInteger) arg_1); } }, /** * greater-than on num and num * * [ ... INumber val1, INumber val2] => [ ..., val1 > val2] */ num_greater_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).greater((INumber) arg_1); } }, /** * greater-than on num and rat * * [ ... INumber val1, IRational val2] => [ ..., val1 > val2] */ num_greater_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).greater((IRational) arg_1); } }, /** * greater-than on num and real * * [ ... INumber val1, IReal val2] => [ ..., val1 > val2] */ num_greater_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).greater((IReal) arg_1); } }, /** * greater-than on rat and int * * [ ... IRational val1, IInteger val2] => [ ..., val1 > val2] */ rat_greater_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).greater((IInteger) arg_1); } }, /** * greater-than on rat and num * * [ ... IRational val1, INumber val2] => [ ..., val1 > val2] */ rat_greater_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).greater((INumber) arg_1); } }, /** * greater-than on rat and rat * * [ ... IRational val1, IRational val2] => [ ..., val1 > val2] */ rat_greater_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).greater((IRational) arg_1); } }, /** * greater-than on rat and real * * [ ... IRational val1, IReal val2] => [ ..., val1 > val2] */ rat_greater_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).greater((IReal) arg_1); } }, /** * greater-than on real and num * * [ ... IReal val1, INumber val2] => [ ..., val1 > val2] */ real_greater_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).greater((INumber) arg_1); } }, /** * greater-than on real and int * * [ ... IReal val1, IInteger val2] => [ ..., val1 > val2] */ real_greater_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).greater((IInteger) arg_1); } }, /** * greater-than on real and real * * [ ... IReal val1, IReal val2] => [ ..., val1 > val2] */ real_greater_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).greater((IReal) arg_1); } }, /** * greater-than on real and rat * * [ ... IReal val1, IRational val2] => [ ..., val1 > val2] */ real_greater_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).greater((IRational) arg_1); } }, /** * greater-than on arbitrary values * * [ ... IValue val1, IValue val2] => [ ..., val1 > val2] */ greater { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) lessequal.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than on adts * * [ ... IConstructor val1, IConstructor val2] => [ ..., val1 > val2] */ adt_greater_adt { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return node_greater_node.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * greater-than on bool * * [ ... IBool val1, IBool val2] => [ ..., val1 > val2] */ bool_greater_bool { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) arg_2).and(((IBool) arg_1).not()); } }, /** * greater-than on datetime * * [ ... IDateTime val1, IDateTime val2] => [ ..., val1 > val2] */ datetime_greater_datetime { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IDateTime) arg_2).compareTo((IDateTime) arg_1) == 1); } }, /** * greater-than on list * * [ ... IList val1, IList val2] => [ ..., val1 > val2] */ list_greater_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) list_lessequal_list.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than on list relation * * [ ... IListRelation val1, IListRelation val2] => [ ..., val1 > val2] */ lrel_greater_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) list_lessequal_list.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than on loc * * [ ... ISourceLocation val1, ISourceLocation val2] => [ ..., val1 > val2] */ loc_greater_loc { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) loc_lessequal_loc.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than on map * * [ ... IMap val1, IMap val2] => [ ..., val1 > val2] */ map_greater_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IMap left = (IMap) arg_2; IMap right = (IMap) arg_1; return vf.bool(right.isSubMap(left) && !left.isSubMap(right)); } }, /** * greater-than on node * * [ ... INode val1, INode val2] => [ ..., val1 > val2] */ node_greater_node { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) node_lessequal_node.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than on set * * [ ... ISet val1, ISet val2] => [ ..., val1 > val2] */ set_greater_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((ISet) arg_1).isSubsetOf((ISet) arg_2)); } }, /** * greater-than on rel * * [ ... IRelation val1, IRelation val2] => [ ..., val1 > val2] */ rel_greater_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((ISet) arg_1).isSubsetOf((ISet) arg_2)); } }, /** * greater-than on str * * [ ... IString val1, IString val2] => [ ..., val1 > val2] */ str_greater_str { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IString) arg_2).compare((IString) arg_1) == 1); } }, /** * greater-than on tuple * * [ ... ITuple val1, ITuple val2] => [ ..., val1 > val2] */ tuple_greater_tuple { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) tuple_lessequal_tuple.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, // ==== greaterequal /** * greater-than-or-equal on int and int * * [ ... IInteger val1, IInteger val2] => [ ..., val1 >= val2] */ int_greaterequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).greaterEqual((IInteger) arg_1); } }, /** * greater-than-or-equal on int and num * * [ ... IInteger val1, INumber val2] => [ ..., val1 >= val2] */ int_greaterequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).greaterEqual((INumber) arg_1); } }, /** * greater-than-or-equal on int and rat * * [ ... IInteger val1, IRational val2] => [ ..., val1 >= val2] */ int_greaterequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).greaterEqual((IRational) arg_1); } }, /** * greater-than-or-equal on int and real * * [ ... IInteger val1, IReal val2] => [ ..., val1 >= val2] */ int_greaterequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).greaterEqual((IReal) arg_1); } }, /** * greater-than-or-equal on num and int * * [ ... INumber val1, IInteger val2] => [ ..., val1 >= val2] */ num_greaterequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).greaterEqual((IInteger) arg_1); } }, /** * greater-than-or-equal on num and num * * [ ... INumber val1, INumber val2] => [ ..., val1 >= val2] */ num_greaterequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).greaterEqual((INumber) arg_1); } }, /** * greater-than-or-equal on num and rat * * [ ... INumber val1, IRational val2] => [ ..., val1 >= val2] */ num_greaterequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).greaterEqual((IRational) arg_1); } }, /** * greater-than-or-equal on num and real * * [ ... INumber val1, IReal val2] => [ ..., val1 >= val2] */ num_greaterequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).greaterEqual((IReal) arg_1); } }, /** * greater-than-or-equal on rat and int * * [ ... IRational val1, IInteger val2] => [ ..., val1 >= val2] */ rat_greaterequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).greaterEqual((IInteger) arg_1); } }, /** * greater-than-or-equal on rat and num * * [ ... IRational val1, INumber val2] => [ ..., val1 >= val2] */ rat_greaterequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).greaterEqual((INumber) arg_1); } }, /** * greater-than-or-equal on rat and rat * * [ ... IRational val1, IRational val2] => [ ..., val1 >= val2] */ rat_greaterequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).greaterEqual((IRational) arg_1); } }, /** * greater-than-or-equal on rat and real * * [ ... IRational val1, IReal val2] => [ ..., val1 >= val2] */ rat_greaterequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).greaterEqual((IReal) arg_1); } }, /** * greater-than-or-equal on real and num * * [ ... IReal val1, INumber val2] => [ ..., val1 >= val2] */ real_greaterequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).greaterEqual((INumber) arg_1); } }, /** * greater-than-or-equal on real and int * * [ ... IReal val1, IInteger val2] => [ ..., val1 >= val2] */ real_greaterequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).greaterEqual((IInteger) arg_1); } }, /** * greater-than-or-equal on real and real * * [ ... IReal val1, IReal val2] => [ ..., val1 >= val2] */ real_greaterequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).greaterEqual((IReal) arg_1); } }, /** * greater-than-or-equal on real and rat * * [ ... IReal val1, IRational val2] => [ ..., val1 >= val2] */ real_greaterequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).greaterEqual((IRational) arg_1); } }, /** * greater-than-or-equal on arbitrary values * * [ ... IValue val1, IValue val2] => [ ..., val1 >= val2] */ greaterequal { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) less.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than-or-equal on adts * * [ ... IConstructor val1, IConstructor val2] => [ ..., val1 >= val2] */ adt_greaterequal_adt { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return node_greaterequal_node.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * greater-than-or-equal on bool * * [ ... IBool val1, IBool val2] => [ ..., val1 >= val2] */ bool_greaterequal_bool { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { boolean left = ((IBool) arg_2).getValue(); boolean right = ((IBool) arg_1).getValue(); return vf.bool((left && !right) || (left == right)); } }, /** * greater-than-or-equal on datetime * * [ ... IDateTime val1, IDateTime val2] => [ ..., val1 >= val2] */ datetime_greaterequal_datetime { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IDateTime) arg_2).compareTo((IDateTime) arg_1) == 1); } }, /** * greater-than-or-equal on lists * * [ ... IList val1, IList val2] => [ ..., val1 >= val2] */ list_greaterequal_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) list_less_list.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than-or-equal on list relations * * [ ... IListRelation val1, IListRelation val2] => [ ..., val1 >= val2] */ lrel_greaterequal_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) list_less_list.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than-or-equal on locs * * [ ... ISourceLocation val1, ISourceLocation val2] => [ ..., val1 >= val2] */ loc_greaterequal_loc { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) loc_less_loc.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than-or-equal on nodes * * [ ... INode val1, INode val2] => [ ..., val1 >= val2] */ node_greaterequal_node { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) node_less_node.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, /** * greater-than-or-equal on maps * * [ ... IMap val1, IMap val2] => [ ..., val1 >= val2] */ map_greaterequal_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IMap left = (IMap) arg_2; IMap right = (IMap) arg_1; return vf.bool(right.isSubMap(left)); } }, /** * greater-than-or-equal on sets * * [ ... ISet val1, ISet val2] => [ ..., val1 >= val2] */ set_greaterequal_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet left = (ISet) arg_2; ISet right = (ISet) arg_1; return vf.bool(left.isEqual(right) || right.isSubsetOf(left)); } }, /** * greater-than-or-equal on rels * * [ ... IRelation val1, IRelation val2] => [ ..., val1 >= val2] */ rel_greaterequal_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet left = (ISet) arg_2; ISet right = (ISet) arg_1; return vf.bool(left.isEqual(right) || right.isSubsetOf(left)); } }, /** * greater-than-or-equal on str * * [ ... IString val1, IString val2] => [ ..., val1 >= val2] */ str_greaterequal_str { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { int c = ((IString) arg_2).compare((IString) arg_1); return vf.bool(c == 0 || c == 1); } }, /** * greater-than-or-equal on tuples * * [ ... ITuple val1, ITuple val2] => [ ..., val1 >= val2] */ tuple_greaterequal_tuple { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IBool) tuple_less_tuple.execute2(arg_2, arg_1, currentFrame, rex)).not(); } }, // ==== intersect /** * intersect of two values * * [ ... IValue val1, IValue val2 ] => [ ..., val1 & val2 ] * * infix intersect "&" { * list[&L] x list[&R] -> list[LUB(&L,&R)], * set[&L] x set[&R] -> set[LUB(&L,&R)], * map[&K1,&V1] x map[&K2,&V2] -> map[LUB(&K1,&K2), LUB(&V1,&V2)] * } */ /** * See general remark about generic primitives */ intersect { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue left = (IValue) arg_2; Type leftType = left.getType(); IValue right = (IValue) arg_1; Type rightType = right.getType(); switch (ToplevelType.getToplevelType(leftType)) { case LIST: switch (ToplevelType.getToplevelType(rightType)) { case LIST: return list_intersect_list.execute2(left, right, currentFrame, rex); case LREL: return list_intersect_lrel.execute2(left, right, currentFrame, rex); default: throw new CompilerError("intersect: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } case SET: switch (ToplevelType.getToplevelType(rightType)) { case SET: return set_intersect_set.execute2(left, right, currentFrame, rex); case REL: return set_intersect_rel.execute2(left, right, currentFrame, rex); default: throw new CompilerError("intersect: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } case MAP: return map_intersect_map.execute2(left, right, currentFrame, rex); default: throw new CompilerError("intersect: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } } }, /** * intersect on lists * * [ ... IList val1, IList val2 ] => [ ..., val1 & val2 ] */ list_intersect_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IList) arg_2).intersect((IList) arg_1); } }, /** * intersect on list and list relation * * [ ... IList val1, IListRelation val2 ] => [ ..., val1 & val2 ] */ list_intersect_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_intersect_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * intersect on list relations * * [ ... IListRelation val1, IListRelation val2 ] => [ ..., val1 & val2 ] */ lrel_intersect_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_intersect_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * intersect on list relation and list * * [ ... IListRelation val1, IList val2 ] => [ ..., val1 & val2 ] */ lrel_intersect_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_intersect_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * intersect on maps * * [ ... IMap val1, IMap val2 ] => [ ..., val1 & val2 ] */ map_intersect_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IMap) arg_2).common((IMap) arg_1); } }, /** * intersect on rels * * [ ... IRelation val1, IRelation val2 ] => [ ..., val1 & val2 ] */ rel_intersect_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_intersect_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * intersect on rel and set * * [ ... IRelation val1, ISet val2 ] => [ ..., val1 & val2 ] */ rel_intersect_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_intersect_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * intersect on sets * * [ ... ISet val1, ISet val2 ] => [ ..., val1 & val2 ] */ set_intersect_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((ISet) arg_2).intersect((ISet) arg_1); } }, /** * intersect on set and rel * * [ ... ISet val1, IRelation val2 ] => [ ..., val1 & val2 ] */ set_intersect_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_intersect_set.execute2(arg_2, arg_1, currentFrame, rex); } }, // ==== in /** * in (is-element-of) on arbitrary values * * [ ... IValue val1, IValue val2 ] => [ ..., val1 in val2 ] */ /** * See general remark about generic primitives */ in { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue left = (IValue) arg_2; Type leftType = left.getType(); IValue right = (IValue) arg_1; Type rightType = right.getType(); switch (ToplevelType.getToplevelType(leftType)) { case LIST: return elm_in_list.execute2(left, right, currentFrame, rex); case LREL: return elm_in_lrel.execute2(left, right, currentFrame, rex); case SET: return elm_in_set.execute2(left, right, currentFrame, rex); case REL: return elm_in_rel.execute2(left, right, currentFrame, rex); case MAP: return elm_in_map.execute2(left, right, currentFrame, rex); default: throw new CompilerError("in: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } } }, /** * in (is-element-of) on element and list * * [ ... IValue val1, IList val2 ] => [ ..., val1 in val2 ] */ elm_in_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IList) arg_1).contains((IValue) arg_2)); } }, /** * in (is-element-of) on element and list relation * * [ ... IValue val1, IListRelation val2 ] => [ ..., val1 in val2 ] */ elm_in_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return elm_in_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * in (is-element-of) on element and set * * [ ... IValue val1, ISet val2 ] => [ ..., val1 in val2 ] */ elm_in_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((ISet) arg_1).contains((IValue) arg_2)); } }, /** * in (is-element-of) on element and relation * * [ ... IValue val1, IRelation val2 ] => [ ..., val1 in val2 ] */ elm_in_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return elm_in_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * in (is-element-of) on element and map * * [ ... IValue val1, IMap val2 ] => [ ..., val1 in val2 ] */ elm_in_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IMap) arg_1).containsKey((IValue) arg_2)); } }, // ==== notin /** * notin (not-element-of) on arbitrary values * * [ ... IValue val1, IValue val2 ] => [ ..., val1 notin val2 ] */ /** * See general remark about generic primitives */ notin { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue left = (IValue) arg_2; Type leftType = left.getType(); IValue right = (IValue) arg_1; Type rightType = right.getType(); switch (ToplevelType.getToplevelType(leftType)) { case LIST: return elm_notin_list.execute2(left, right, currentFrame, rex); case LREL: return elm_notin_lrel.execute2(left, right, currentFrame, rex); case SET: return elm_notin_set.execute2(left, right, currentFrame, rex); case REL: return elm_notin_rel.execute2(left, right, currentFrame, rex); case MAP: return elm_notin_map.execute2(left, right, currentFrame, rex); default: throw new CompilerError("notin: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } } }, /** * notin (not-element-of) on element and list * * [ ... IValue val1, IList val2 ] => [ ..., val1 notin val2 ] */ elm_notin_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(!((IList) arg_1).contains((IValue) arg_2)); } }, /** * notin (not-element-of) on element and list relation * * [ ... IValue val1, IListRelation val2 ] => [ ..., val1 notin val2 ] */ elm_notin_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return elm_notin_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * notin (not-element-of) on element and set * * [ ... IValue val1, ISet val2 ] => [ ..., val1 notin val2 ] */ elm_notin_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(!((ISet) arg_1).contains((IValue) arg_2)); } }, /** * notin (not-element-of) on element and relation * * [ ... IValue val1, IRelation val2 ] => [ ..., val1 notin val2 ] */ elm_notin_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return elm_notin_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * notin (not-element-of) on element and map * * [ ... IValue val1, IMap val2 ] => [ ..., val1 notin val2 ] */ elm_notin_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(!((IMap) arg_1).containsKey((IValue) arg_2)); } }, // ==== non_negative /** * Non_negative * * [ ..., IInteger val ] => [ ..., val >= 0 ] */ non_negative { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { if(((IInteger)arg_1).intValue() < 0){ return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds(((IInteger)arg_1), currentFrame)); } return Rascal_TRUE; } }, // ==== join /** * See general remark about generic primitives */ join { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue left = (IValue) arg_2; Type leftType = left.getType(); IValue right = (IValue) arg_1; Type rightType = right.getType(); switch (ToplevelType.getToplevelType(leftType)) { case LIST: switch (ToplevelType.getToplevelType(rightType)) { case LIST: return list_join_list.execute2(left, right, currentFrame, rex); case LREL: return list_join_lrel.execute2(left, right, currentFrame, rex); default: throw new CompilerError("join: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } case LREL: switch (ToplevelType.getToplevelType(rightType)) { case LIST: return lrel_join_list.execute2(left, right, currentFrame, rex); case LREL: return lrel_join_lrel.execute2(left, right, currentFrame, rex); default: throw new CompilerError("join: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } case SET: switch (ToplevelType.getToplevelType(rightType)) { case SET: return set_join_set.execute2(left, right, currentFrame, rex); case REL: return set_join_rel.execute2(left, right, currentFrame, rex); default: throw new CompilerError("join: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } case REL: switch (ToplevelType.getToplevelType(rightType)) { case SET: return rel_join_set.execute2(left, right, currentFrame, rex); case REL: return rel_join_rel.execute2(left, right, currentFrame, rex); default: throw new CompilerError("join: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } default: throw new CompilerError("join: illegal combination " + leftType + " and " + rightType, rex.getStdErr(), currentFrame); } } }, /** join on lists * * [ ..., IList val1, IList val2 ] => [ ..., val1 join val2 ] */ list_join_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return list_product_list.execute2(arg_2, arg_1, currentFrame, rex); } }, /** join on list and list relation * * [ ..., IList val1, IListRelation val2 ] => [ ..., val1 join val2 ] */ list_join_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList left = (IList) arg_2; IList right = (IList) arg_1; if(left.length() == 0){ return left; } if(right.length() == 0){ return right; } Type rightType = right.get(0).getType(); assert rightType.isTuple(); int rarity = rightType.getArity(); IValue fieldValues[] = new IValue[1 + rarity]; IListWriter w =vf.listWriter(); for (IValue lval : left){ fieldValues[0] = lval; for (IValue rtuple: right) { for (int i = 0; i < rarity; i++) { fieldValues[i + 1] = ((ITuple)rtuple).get(i); } w.append(vf.tuple(fieldValues)); } } return w.done(); } }, /** join on list relations * * [ ..., IListRelation val1, IListRelation val2 ] => [ ..., val1 join val2 ] */ lrel_join_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList left = (IList) arg_2; IList right = (IList) arg_1; if(left.length() == 0){ return left; } if(right.length() == 0){ return right; } Type leftType = left.get(0).getType(); Type rightType = right.get(0).getType(); assert leftType.isTuple(); assert rightType.isTuple(); int larity = leftType.getArity(); int rarity = rightType.getArity(); IValue fieldValues[] = new IValue[larity + rarity]; IListWriter w =vf.listWriter(); for (IValue ltuple : left){ for (IValue rtuple: right) { for (int i = 0; i < larity; i++) { fieldValues[i] = ((ITuple)ltuple).get(i); } for (int i = larity; i < larity + rarity; i++) { fieldValues[i] = ((ITuple)rtuple).get(i - larity); } w.append(vf.tuple(fieldValues)); } } return w.done(); } }, /** join on list relation and list * * [ ..., IListRelation val1, IList val2 ] => [ ..., val1 join val2 ] */ lrel_join_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList left = (IList) arg_2; IList right = (IList) arg_1; if(left.length() == 0){ return left; } if(right.length() == 0){ return right; } Type leftType = left.get(0).getType(); assert leftType.isTuple(); int larity = leftType.getArity(); IValue fieldValues[] = new IValue[larity + 1]; IListWriter w =vf.listWriter(); for (IValue ltuple : left){ for (IValue rval: right) { for (int i = 0; i < larity; i++) { fieldValues[i] = ((ITuple)ltuple).get(i); } fieldValues[larity] = rval; w.append(vf.tuple(fieldValues)); } } return w.done(); } }, /** join on sets * * [ ..., ISet val1, ISet val2 ] => [ ..., val1 join val2 ] */ set_join_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return set_product_set.execute2(arg_2, arg_1, currentFrame, rex); } }, /** join on set and relation * * [ ..., ISet val1, IRelation val2 ] => [ ..., val1 join val2 ] */ set_join_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet left = (ISet) arg_2; ISet right = (ISet) arg_1; if(left.size() == 0){ return left; } if(right.size() == 0){ return right; } Type rightType = right.getElementType(); assert rightType.isTuple(); int rarity = rightType.getArity(); IValue fieldValues[] = new IValue[1 + rarity]; ISetWriter w =vf.setWriter(); for (IValue lval : left){ for (IValue rtuple: right) { fieldValues[0] = lval; for (int i = 0; i < rarity; i++) { fieldValues[i + 1] = ((ITuple)rtuple).get(i); } w.insert(vf.tuple(fieldValues)); } } return w.done(); } }, /** join on rels * * [ ..., IRelation val1, IRelation val2 ] => [ ..., val1 join val2 ] */ rel_join_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet left = (ISet) arg_2; ISet right = (ISet) arg_1; if(left.size() == 0){ return left; } if(right.size() == 0){ return right; } Type leftType = left.getElementType(); Type rightType = right.getElementType(); assert leftType.isTuple(); assert rightType.isTuple(); int larity = leftType.getArity(); int rarity = rightType.getArity(); IValue fieldValues[] = new IValue[larity + rarity]; ISetWriter w =vf.setWriter(); for (IValue ltuple : left){ for (IValue rtuple: right) { for (int i = 0; i < larity; i++) { fieldValues[i] = ((ITuple)ltuple).get(i); } for (int i = larity; i < larity + rarity; i++) { fieldValues[i] = ((ITuple)rtuple).get(i - larity); } w.insert(vf.tuple(fieldValues)); } } return w.done(); } }, /** join on relation and set * * [ ..., IRelation val1, ISet val2 ] => [ ..., val1 join val2 ] */ rel_join_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet left = (ISet) arg_2; ISet right = (ISet) arg_1; if(left.size() == 0){ return left; } if(right.size() == 0){ return right; } Type leftType = left.getElementType(); assert leftType.isTuple(); int larity = leftType.getArity(); IValue fieldValues[] = new IValue[larity + 1]; ISetWriter w =vf.setWriter(); for (IValue ltuple : left){ for (IValue rval: right) { for (int i = 0; i < larity; i++) { fieldValues[i] = ((ITuple)ltuple).get(i); } fieldValues[larity] = rval; w.insert(vf.tuple(fieldValues)); } } return w.done(); } }, // ==== less /** * less-than on arbitrary values * * [ ..., IValue val1, IValue val2 ] => [ ..., val1 < val2 ] */ /** * See general remark about generic primitives */ less { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue left = (IValue) arg_2; IValue right = (IValue) arg_1; Type leftType = left.getType(); Type rightType = right.getType(); if (leftType.isSubtypeOf(tf.numberType()) && rightType.isSubtypeOf(tf.numberType())) { return num_less_num.execute2(left, right, currentFrame, rex); } if(!leftType.comparable(rightType)){ return Rascal_FALSE; } switch (ToplevelType.getToplevelType(leftType)) { // TODO: is this really faster than a TypeVisitor?? No because getTopLevelType includes a TypeVisitor itself. case BOOL: return bool_less_bool.execute2(left, right, currentFrame, rex); case STR: return str_less_str.execute2(left, right, currentFrame, rex); case DATETIME: return datetime_less_datetime.execute2(left, right, currentFrame, rex); case LOC: return loc_less_loc.execute2(left, right, currentFrame, rex); case LIST: case LREL: return list_less_list.execute2(left, right, currentFrame, rex); case SET: case REL: return set_less_set.execute2(left, right, currentFrame, rex); case MAP: return map_less_map.execute2(left, right, currentFrame, rex); case CONSTRUCTOR: case NODE: return node_less_node.execute2(left, right, currentFrame, rex); case ADT: return adt_less_adt.execute2(left, right, currentFrame, rex); case TUPLE: return tuple_less_tuple.execute2(left, right, currentFrame, rex); default: throw new CompilerError("less: unexpected type " + leftType, rex.getStdErr(), currentFrame); } } }, /** * less-than on int and int * * [ ..., IInteger val1, IInteger val2 ] => [ ..., val1 < val2 ] */ int_less_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).less((IInteger) arg_1); } }, /** * less-than on int and num * * [ ..., IInteger val1, INumber val2 ] => [ ..., val1 < val2 ] */ int_less_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).less((INumber) arg_1); } }, /** * less-than on int and rat * * [ ..., IInteger val1, IRational val2 ] => [ ..., val1 < val2 ] */ int_less_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).less((IRational) arg_1); } }, /** * less-than on int and real * * [ ..., IInteger val1, IReal val2 ] => [ ..., val1 < val2 ] */ int_less_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).less((IReal) arg_1); } }, /** * less-than on num and int * * [ ..., INumber val1, IInteger val2 ] => [ ..., val1 < val2 ] */ num_less_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).less((IInteger) arg_1); } }, /** * less-than on num and num * * [ ..., INumber val1, INumber val2 ] => [ ..., val1 < val2 ] */ num_less_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).less((INumber) arg_1); } }, /** * less-than on num and rat * * [ ..., INumber val1, IRational val2 ] => [ ..., val1 < val2 ] */ num_less_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).less((IRational) arg_1); } }, /** * less-than on num and real * * [ ..., INumber val1, IReal val2 ] => [ ..., val1 < val2 ] */ num_less_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).less((IReal) arg_1); } }, /** * less-than on rat and int * * [ ..., IRational val1, IInteger val2 ] => [ ..., val1 < val2 ] */ rat_less_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).less((IInteger) arg_1); } }, /** * less-than on rat and num * * [ ..., IRational val1, INumber val2 ] => [ ..., val1 < val2 ] */ rat_less_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).less((INumber) arg_1); } }, /** * less-than on rat and rat * * [ ..., IRational val1, IRational val2 ] => [ ..., val1 < val2 ] */ rat_less_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).less((IRational) arg_1); } }, /** * less-than on rat and real * * [ ..., IRational val1, IReal val2 ] => [ ..., val1 < val2 ] */ rat_less_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).less((IReal) arg_1); } }, /** * less-than on real and num * * [ ..., IReal val1, INumber val2 ] => [ ..., val1 < val2 ] */ real_less_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).less((INumber) arg_1); } }, /** * less-than on real and int * * [ ..., IReal val1, IInteger val2 ] => [ ..., val1 < val2 ] */ real_less_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).less((IInteger) arg_1); } }, /** * less-than on real and numreal * * [ ..., IReal val1, IReal val2 ] => [ ..., val1 < val2 ] */ real_less_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).less((IReal) arg_1); } }, /** * less-than on real and num * * [ ..., IReal val1, IRational val2 ] => [ ..., val1 < val2 ] */ real_less_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).less((IRational) arg_1); } }, /** * less-than on adts * * [ ..., IConstructor val1, IConstructor val2 ] => [ ..., val1 < val2 ] */ adt_less_adt { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return node_less_node.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * less-than on bool * * [ ..., IBool val1, IBool val2 ] => [ ..., val1 < val2 ] */ bool_less_bool { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { boolean left = ((IBool) arg_2).getValue(); boolean right = ((IBool) arg_1).getValue(); return vf.bool(!left && right); } }, // bool_or_bool { // @Override // public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { // assert arity == 2; // boolean left = ((IBool) arg_2).getValue(); // boolean right = ((IBool) arg_1).getValue(); // // stack[sp - 2] = vf.bool(left || right); // return sp - 1; // } // }, /** * less-than on datetime * * [ ..., IDateTime val1, IDateTime val2 ] => [ ..., val1 < val2 ] */ datetime_less_datetime { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IDateTime) arg_2).compareTo((IDateTime) arg_1) == -1); } }, /** * less-than on list * * [ ..., IList val1, IList val2 ] => [ ..., val1 < val2 ] */ list_less_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList left = (IList) arg_2; IList right = (IList) arg_1; return $list_less_list(left, right); } }, /** * less-than on list relation * * [ ..., IListRelation val1, IListRelation val2 ] => [ ..., val1 < val2 ] */ lrel_less_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList left = (IList) arg_2; IList right = (IList) arg_1; return $list_less_list(left, right); } }, /** * less-than on loc * * [ ..., ISourceLocation val1, ISourceLocation val2 ] => [ ..., val1 < val2 ] */ loc_less_loc { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISourceLocation left = (ISourceLocation) arg_2; ISourceLocation right = (ISourceLocation) arg_1; int compare = left.top().toString().compareTo(right.top().toString()); if (compare < 0) { return Rascal_TRUE; } else if (compare > 0) { return Rascal_FALSE; } // but the uri's are the same // note that line/column information is superfluous and does not matter for ordering if (left.hasOffsetLength()) { if (!right.hasOffsetLength()) { return Rascal_FALSE; } int roffset = right.getOffset(); int rlen = right.getLength(); int loffset = left.getOffset(); int llen = left.getLength(); if (loffset == roffset) { return vf.bool(llen < rlen); } return vf.bool(roffset < loffset && roffset + rlen >= loffset + llen); } else if (compare == 0) { return Rascal_FALSE; } if (!right.hasOffsetLength()) { throw new CompilerError("offset length missing", rex.getStdErr(), currentFrame); } return Rascal_FALSE; } }, /** * less-than on map * * [ ..., IMap val1, IMap val2 ] => [ ..., val1 < val2 ] */ map_less_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IMap left = ((IMap) arg_2); IMap right = ((IMap) arg_1); return vf.bool(left.isSubMap(right) && !right.isSubMap(left)); } }, /** * less-than on node * * [ ..., INode val1, INode val2 ] => [ ..., val1 < val2 ] */ node_less_node { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode left = (INode) arg_2; INode right = (INode) arg_1; int compare = left.getName().compareTo(right.getName()); if (compare <= -1) { return Rascal_TRUE; } if (compare >= 1){ return Rascal_FALSE; } // if the names are not ordered, then we order lexicographically on the arguments: int leftArity = left.arity(); int rightArity = right.arity(); Object result = Rascal_FALSE; for (int i = 0; i < Math.min(leftArity, rightArity); i++) { if(leftArity < rightArity || i < leftArity - 1) result = lessequal.execute2(left.get(i), right.get(i), currentFrame, rex); else result = less.execute2(left.get(i), right.get(i), currentFrame, rex); if(!((IBool)result).getValue()){ return Rascal_FALSE; } } if (!left.mayHaveKeywordParameters() && !right.mayHaveKeywordParameters()) { if (left.asAnnotatable().hasAnnotations() || right.asAnnotatable().hasAnnotations()) { // bail out return Rascal_FALSE; } } if (!left.asWithKeywordParameters().hasParameters() && right.asWithKeywordParameters().hasParameters()) { return Rascal_TRUE; } if (left.asWithKeywordParameters().hasParameters() && !right.asWithKeywordParameters().hasParameters()) { return Rascal_FALSE; } if (left.asWithKeywordParameters().hasParameters() && right.asWithKeywordParameters().hasParameters()) { Map<String, IValue> paramsLeft = left.asWithKeywordParameters().getParameters(); Map<String, IValue> paramsRight = right.asWithKeywordParameters().getParameters(); if (paramsLeft.size() < paramsRight.size()) { return Rascal_TRUE; } if (paramsLeft.size() > paramsRight.size()) { return Rascal_FALSE; } if (paramsRight.keySet().containsAll(paramsLeft.keySet()) && !paramsRight.keySet().equals(paramsLeft.keySet())) { return Rascal_TRUE; } if (paramsLeft.keySet().containsAll(paramsLeft.keySet()) && !paramsRight.keySet().equals(paramsLeft.keySet())) { return Rascal_FALSE; } //assert paramsLeft.keySet().equals(paramsRight.keySet()); for (String k: paramsLeft.keySet()) { result = less.execute2(paramsLeft.get(k), paramsRight.get(k), currentFrame, rex); if(!((IBool)result).getValue()){ return Rascal_FALSE; } } } return vf.bool((leftArity < rightArity) || ((IBool)result).getValue()); } }, /** * less-than on set * * [ ..., ISet val1, ISet val2 ] => [ ..., val1 < val2 ] */ set_less_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet lhs = (ISet) arg_2; ISet rhs = (ISet) arg_1; return vf.bool(!lhs.isEqual(rhs) && lhs.isSubsetOf(rhs)); } }, /** * less-than on rel * * [ ..., IRelation val1, IRelation val2 ] => [ ..., val1 < val2 ] */ rel_less_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet lhs = (ISet) arg_2; ISet rhs = (ISet) arg_1; return vf.bool(!lhs.isEqual(rhs) && lhs.isSubsetOf(rhs)); } }, /** * less-than on str * * [ ..., IString val1, IString val2 ] => [ ..., val1 < val2 ] */ str_less_str { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { int c = ((IString) arg_2).compare((IString) arg_1); return vf.bool(c == -1); } }, /** * less-than on tuple * * [ ..., ITuple val1, ITuple val2 ] => [ ..., val1 < val2 ] */ tuple_less_tuple { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITuple left = (ITuple)arg_2; int leftArity = left.arity(); ITuple right = (ITuple)arg_1; int rightArity = right.arity(); for (int i = 0; i < Math.min(leftArity, rightArity); i++) { Object result; if(leftArity < rightArity || i < leftArity - 1) result = equal.execute2(left.get(i), right.get(i), currentFrame, rex); else result =less.execute2(left.get(i), right.get(i), currentFrame, rex); if(!((IBool)result).getValue()){ return Rascal_FALSE; } } return vf.bool(leftArity <= rightArity); } }, // ==== lessequal /** * less-than-or-equal on arbitrary values * * [ ... IValue val1, IValue val2 ] => [ ..., val1 <= val2 ] */ /** * See general remark about generic primitives */ lessequal { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue left = (IValue) arg_2; IValue right = (IValue) arg_1; Type leftType = ((IValue) arg_2).getType(); Type rightType = ((IValue) arg_1).getType(); if (leftType.isSubtypeOf(tf.numberType()) && rightType.isSubtypeOf(tf.numberType())) { return num_lessequal_num.execute2(left, right, currentFrame, rex); } if(!leftType.comparable(rightType)){ return Rascal_FALSE; } switch (ToplevelType.getToplevelType(leftType)) { case BOOL: return bool_lessequal_bool.execute2(left, right, currentFrame, rex); case STR: return str_lessequal_str.execute2(left, right, currentFrame, rex); case DATETIME: return datetime_lessequal_datetime.execute2(left, right, currentFrame, rex); case LOC: return loc_lessequal_loc.execute2(left, right, currentFrame, rex); case LIST: case LREL: return list_lessequal_list.execute2(left, right, currentFrame, rex); case SET: case REL: return set_lessequal_set.execute2(left, right, currentFrame, rex); case MAP: return map_lessequal_map.execute2(left, right, currentFrame, rex); case CONSTRUCTOR: case NODE: return node_lessequal_node.execute2(left, right, currentFrame, rex); case ADT: return adt_lessequal_adt.execute2(left, right, currentFrame, rex); case TUPLE: return tuple_lessequal_tuple.execute2(left, right, currentFrame, rex); default: throw new CompilerError("lessequal: unexpected type " + leftType, rex.getStdErr(), currentFrame); } } }, /** * less-than-or-equal on int and int * * [ ... IInteger val1, IInteger val2 ] => [ ..., val1 <= val2 ] */ int_lessequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).lessEqual((IInteger) arg_1); } }, /** * less-than-or-equal on int and num * * [ ... IInteger val1, INumber val2 ] => [ ..., val1 <= val2 ] */ int_lessequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).lessEqual((INumber) arg_1); } }, /** * less-than-or-equal on int and rat * * [ ... IInteger val1, IRational val2 ] => [ ..., val1 <= val2 ] */ int_lessequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).lessEqual((IRational) arg_1); } }, /** * less-than-or-equal on int and real * * [ ... IInteger val1, IReal val2 ] => [ ..., val1 <= val2 ] */ int_lessequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).lessEqual((IReal) arg_1); } }, /** * less-than-or-equal on num and int * * [ ... INumber val1, IInteger val2 ] => [ ..., val1 <= val2 ] */ num_lessequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).lessEqual((IInteger) arg_1); } }, /** * less-than-or-equal on num and num * * [ ... INumber val1, INumber val2 ] => [ ..., val1 <= val2 ] */ num_lessequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).lessEqual((INumber) arg_1); } }, /** * less-than-or-equal on num and rat * * [ ... INumber val1, IRational val2 ] => [ ..., val1 <= val2 ] */ num_lessequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).lessEqual((IRational) arg_1); } }, /** * less-than-or-equal on num and real * * [ ... INumber val1, IReal val2 ] => [ ..., val1 <= val2 ] */ num_lessequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).lessEqual((IReal) arg_1); } }, /** * less-than-or-equal on rat and int * * [ ... IRational val1, IInteger val2 ] => [ ..., val1 <= val2 ] */ rat_lessequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).lessEqual((IInteger) arg_1); } }, /** * less-than-or-equal on rat and num * * [ ... IRational val1, INumber val2 ] => [ ..., val1 <= val2 ] */ rat_lessequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).lessEqual((INumber) arg_1); } }, /** * less-than-or-equal on rat and rat * * [ ... IRational val1, IRational val2 ] => [ ..., val1 <= val2 ] */ rat_lessequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).lessEqual((IRational) arg_1); } }, /** * less-than-or-equal on rat and real * * [ ... IRational val1, IReal val2 ] => [ ..., val1 <= val2 ] */ rat_lessequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).lessEqual((IReal) arg_1); } }, /** * less-than-or-equal on real and num * * [ ... IReal val1, INumber val2 ] => [ ..., val1 <= val2 ] */ real_lessequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).lessEqual((INumber) arg_1); } }, /** * less-than-or-equal on real and int * * [ ... IReal val1, IInteger val2 ] => [ ..., val1 <= val2 ] */ real_lessequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).lessEqual((IInteger) arg_1); } }, /** * less-than-or-equal on real and real * * [ ... IReal val1, IReal val2 ] => [ ..., val1 <= val2 ] */ real_lessequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).lessEqual((IReal) arg_1); } }, /** * less-than-or-equal on real and rat * * [ ... IReal val1, IRational val2 ] => [ ..., val1 <= val2 ] */ real_lessequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).lessEqual((IRational) arg_1); } }, /** * less-than-or-equal on adt * * [ ... IConstructor val1, IConstructor val2 ] => [ ..., val1 <= val2 ] */ adt_lessequal_adt { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return node_lessequal_node.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * less-than-or-equal on bool * * [ ... IBool val1, IBool val2 ] => [ ..., val1 <= val2 ] */ bool_lessequal_bool { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { boolean left = ((IBool) arg_2).getValue(); boolean right = ((IBool) arg_1).getValue(); return vf.bool((!left && right) || (left == right)); } }, /** * less-than-or-equal on datetime * * [ ... IDateTime val1, IDateTime val2 ] => [ ..., val1 <= val2 ] */ datetime_lessequal_datetime { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { int c = ((IDateTime) arg_2).compareTo((IDateTime) arg_1); return vf.bool(c == -1 || c == 0); } }, /** * less-than-or-equal on list * * [ ... IList val1, IList val2 ] => [ ..., val1 <= val2 ] */ list_lessequal_list { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList left = (IList) arg_2; IList right = (IList) arg_1; return $list_lessequal_list(left, right); } }, /** * less-than-or-equal on list relation * * [ ... IListRelation val1, IListRelation val2 ] => [ ..., val1 <= val2 ] */ lrel_lessequal_lrel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList left = (IList) arg_2; IList right = (IList) arg_1; return $list_lessequal_list(left, right); } }, /** * less-than-or-equal on loc * * [ ... ISourceLocation val1, ISourceLocation val2 ] => [ ..., val1 <= val2 ] */ loc_lessequal_loc { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISourceLocation left = (ISourceLocation) arg_2; ISourceLocation right = (ISourceLocation) arg_1; int compare = left.top().toString().compareTo(right.top().toString()); if (compare < 0) { return Rascal_TRUE; } else if (compare > 0) { return Rascal_FALSE; } // but the uri's are the same // note that line/column information is superfluous and does not matter for ordering if (left.hasOffsetLength()) { if (!right.hasOffsetLength()) { return Rascal_FALSE; } int roffset = right.getOffset(); int rlen = right.getLength(); int loffset = left.getOffset(); int llen = left.getLength(); if (loffset == roffset) { return vf.bool(llen <= rlen); } return vf.bool(roffset < loffset && roffset + rlen >= loffset + llen); } else if (compare == 0) { return Rascal_TRUE; } if (!right.hasOffsetLength()) { throw new CompilerError("missing offset length", rex.getStdErr(), currentFrame); } return Rascal_FALSE; } }, /** * less-than-or-equal on map * * [ ... IMap val1, IMap val2 ] => [ ..., val1 <= val2 ] */ map_lessequal_map { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IMap left = (IMap) arg_2; IMap right = (IMap) arg_1; return vf.bool(left.isSubMap(right)); } }, /** * less-than-or-equal on node * * [ ... INode val1, INode val2 ] => [ ..., val1 <= val2 ] */ node_lessequal_node { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode left = (INode) arg_2; INode right = (INode) arg_1; int compare = left.getName().compareTo(right.getName()); if (compare <= -1) { return Rascal_TRUE; } if (compare >= 1){ return Rascal_FALSE; } // if the names are not ordered, then we order lexicographically on the arguments: int leftArity = left.arity(); int rightArity = right.arity(); for (int i = 0; i < Math.min(leftArity, rightArity); i++) { if(!$lessequal(left.get(i), right.get(i), currentFrame, rex).getValue()){ return Rascal_FALSE; } } return vf.bool(leftArity <= rightArity); } }, /** * less-than-or-equal on losetc * * [ ... ISet val1, ISet val2 ] => [ ..., val1 <= val2 ] */ set_lessequal_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet left = (ISet) arg_2; ISet right = (ISet) arg_1; return vf.bool(left.size() == 0 || left.isEqual(right) || left.isSubsetOf(right)); } }, /** * less-than-or-equal on rel * * [ ... IRelation val1, IRelation val2 ] => [ ..., val1 <= val2 ] */ rel_lessequal_rel { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet left = (ISet) arg_2; ISet right = (ISet) arg_1; return vf.bool(left.isEqual(right) || left.isSubsetOf(right)); } }, /** * less-than-or-equal on str * * [ ... IString val1, IString val2 ] => [ ..., val1 <= val2 ] */ str_lessequal_str { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { int c = ((IString) arg_2).compare((IString) arg_1); return vf.bool(c == -1 || c == 0); } }, /** * less-than-or-equal on tuple * * [ ... ITuple val1, ITuple val2 ] => [ ..., val1 <= val2 ] */ tuple_lessequal_tuple { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITuple left = (ITuple)arg_2; int leftArity = left.arity(); ITuple right = (ITuple)arg_1; int rightArity = right.arity(); for (int i = 0; i < Math.min(leftArity, rightArity); i++) { if(!$lessequal(left.get(i), right.get(i), currentFrame, rex).getValue()){ return Rascal_FALSE; } } return vf.bool(leftArity <= rightArity); } }, // ==== transitiveClosure /** * transitiveClosure on arbitrary values * * [ ..., IValue val ] => [ ..., val* ] * * postfix Closure "+", "*" { * lrel[&L,&L] -> lrel[&L,&L], * rel[&L,&L] -> rel[&L,&L] * } */ transitive_closure { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue lhs = (IValue) arg_1; Type lhsType = lhs.getType(); if(lhsType.isListRelation()){ return lrel_transitive_closure.execute1(arg_1, currentFrame, rex); } if(lhsType.isRelation()){ return rel_transitive_closure.execute1(arg_1, currentFrame, rex); } throw new CompilerError("transitive_closure: unexpected type " + lhsType, currentFrame); } }, /** * transitiveClosure on lrel * * [ ..., IListRelation val ] => [ ..., val* ] */ lrel_transitive_closure { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IListRelation<IList> left = ((IList) arg_1).asRelation(); return left.closure(); } }, /** * transitiveClosure on rel * * [ ..., IRelation val ] => [ ..., val* ] */ rel_transitive_closure { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISetRelation<ISet> left = ((ISet) arg_1).asRelation(); return left.closure(); } }, /** * transitiveReflexiveClosure on arbitrary values * * [ ..., IValue val ] => [ ..., val+ ] * * postfix Closure "+", "*" { * lrel[&L,&L] -> lrel[&L,&L], * rel[&L,&L] -> rel[&L,&L] */ transitive_reflexive_closure { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue lhs = (IValue) arg_1; Type lhsType = lhs.getType(); if(lhsType.isListRelation()){ return lrel_transitive_reflexive_closure.execute1(arg_1, currentFrame, rex); } if(lhsType.isRelation()){ return rel_transitive_reflexive_closure.execute1(arg_1, currentFrame, rex); } throw new CompilerError("transitive_reflexive_closure: unexpected type " + lhsType, currentFrame); } }, /** * transitiveReflexiveClosure on lrel * * [ ..., IListRelation val ] => [ ..., val+ ] */ lrel_transitive_reflexive_closure { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IListRelation<IList> left = ((IList) arg_1).asRelation(); return left.closureStar(); } }, /** * transitiveReflexiveClosure on rel * * [ ..., IRelation val ] => [ ..., val+ ] */ rel_transitive_reflexive_closure { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISetRelation<ISet> left = ((ISet) arg_1).asRelation(); return left.closureStar(); } }, /** * notequal on arbitrary values * * [ ..., IValue val1, IValue val2 ] => [ ..., val1 != val2 ] */ /** * See general remark about generic primitives */ notequal { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(!((IValue) arg_2).isEqual((IValue) arg_1)); } }, /** * notequal on int and int * * [ ..., IInteger val1, IInteger val2 ] => [ ..., val1 != val2 ] */ int_notequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).equal((IInteger) arg_1).not(); } }, /** * notequal on int and num * * [ ..., IInteger val1, INumber val2 ] => [ ..., val1 != val2 ] */ int_notequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).equal((INumber) arg_1).not(); } }, /** * notequal on int and rat * * [ ..., IInteger val1, IRational val2 ] => [ ..., val1 != val2 ] */ int_notequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).equal((IRational) arg_1).not(); } }, /** * notequal on int and real * * [ ..., IInteger val1, IReal val2 ] => [ ..., val1 != val2 ] */ int_notequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_2).equal((IReal) arg_1).not(); } }, /** * notequal on num and int * * [ ..., INumber val1, IInteger val2 ] => [ ..., val1 != val2 ] */ num_notequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).equal((IInteger) arg_1).not(); } }, /** * notequal on num and int * * [ ..., INumber val1, INumber val2 ] => [ ..., val1 != val2 ] */ num_notequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).equal((INumber) arg_1).not(); } }, /** * notequal on num and rat * * [ ..., INumber val1, IRational val2 ] => [ ..., val1 != val2 ] */ num_notequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).equal((IRational) arg_1).not(); } }, /** * notequal on num and real * * [ ..., INumber val1, IReal val2 ] => [ ..., val1 != val2 ] */ num_notequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_2).equal((IReal) arg_1).not(); } }, /** * notequal on real and int * * [ ..., IReal val1, IInteger val2 ] => [ ..., val1 != val2 ] */ real_notequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).equal((IInteger) arg_1).not(); } }, /** * notequal on real and num * * [ ..., IReal val1, INumber val2 ] => [ ..., val1 != val2 ] */ real_notequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).equal((INumber) arg_1).not(); } }, /** * notequal on real and rat * * [ ..., IReal val1, IRational val2 ] => [ ..., val1 != val2 ] */ real_notequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).equal((IRational) arg_1).not(); } }, /** * notequal on real and irealnt * * [ ..., IReal val1, IReal val2 ] => [ ..., val1 != val2 ] */ real_notequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_2).equal((IReal) arg_1).not(); } }, /** * notequal on rat and int * * [ ..., IRational val1, IInteger val2 ] => [ ..., val1 != val2 ] */ rat_notequal_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).equal((IInteger) arg_1).not(); } }, /** * notequal on rat and num * * [ ..., IRational val1, INUmber val2 ] => [ ..., val1 != val2 ] */ rat_notequal_num { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).equal((INumber) arg_1).not(); } }, /** * notequal on rat and rat * * [ ..., IRational val1, IRational val2 ] => [ ..., val1 != val2 ] */ rat_notequal_rat { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).equal((IRational) arg_1).not(); } }, /** * notequal on rat and real * * [ ..., IRational val1, IReal val2 ] => [ ..., val1 != val2 ] */ rat_notequal_real { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_2).equal((IReal) arg_1).not(); } }, /** * negative on arbitrary value * * [ ..., IValue val ] => [ ..., -val ] * * prefix UnaryMinus "-" { &L <: num -> &L } */ /** * See general remark about generic primitives */ negative { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue left = (IValue) arg_1; Type leftType = left.getType(); switch (ToplevelType.getToplevelType(leftType)) { case INT: return negative_int.execute1(left, currentFrame, rex); case NUM: return negative_num.execute1(left, currentFrame, rex); case REAL: return negative_real.execute1(left, currentFrame, rex); case RAT: return negative_rat.execute1(left, currentFrame, rex); default: throw new CompilerError("negative: unexpected type " + leftType, currentFrame); } } }, /** * negative on int * * [ ..., IInteger val ] => [ ..., -val ] */ negative_int { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IInteger) arg_1).negate(); } }, /** * negative on real * * [ ..., IReal val ] => [ ..., -val ] */ negative_real { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IReal) arg_1).negate(); } }, /** * negative on rat * * [ ..., IRational val ] => [ ..., -val ] */ negative_rat { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((IRational) arg_1).negate(); } }, /** * negative on num * * [ ..., INumber val ] => [ ..., -val ] */ negative_num { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_1).negate(); } }, /********************************************************************************************************/ /* Type-related operators and functions */ /********************************************************************************************************/ /** * is (is-type) on arbitrary value * * [ ... IValue val1, IString typeName] => [ ..., val1 is typeName ] */ is { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue val = (IValue) arg_2; Type tp = val.getType(); String name = ((IString) arg_1).getValue(); if(tp.isAbstractData()){ if(tp.getName().equals("Tree")){ IConstructor cons = (IConstructor) val; if(cons.getName().equals("appl")){ IConstructor prod = (IConstructor) cons.get(0); IConstructor def = (IConstructor) prod.get(0); if(def.getName().equals("label")){ return vf.bool(((IString) def.get(0)).getValue().equals(name)); } } } else { String consName = ((IConstructor)val).getConstructorType().getName(); if(consName.startsWith("\\")){ consName = consName.substring(1); } return vf.bool(consName.equals(name)); } } else if(tp.isNode()){ String nodeName = ((INode) val).getName(); if(nodeName.startsWith("\\")){ nodeName = nodeName.substring(1); } return vf.bool(nodeName.equals(name)); } return Rascal_FALSE; } }, /** * is (is-type) for bool type * * [ ... IValue val1] => [ ..., val1 is bool ] */ is_bool { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isBool()); } }, /** * is (is-type) for datetime type * * [ ... IValue val1] => [ ..., val1 is datetime ] */ is_datetime { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isDateTime()); } }, /** * is (is-type) for int type * * [ ... IValue val1] => [ ..., val1 is int ] */ is_int { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isInteger()); } }, /** * is (is-type) for list type * * [ ... IValue val1] => [ ..., val1 is list ] */ is_list { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isList()); } }, /** * is (is-type) for loc type * * [ ... IValue val1] => [ ..., val1 is loc ] */ is_loc { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isSourceLocation()); } }, /** * is (is-type) for list relation type * * [ ... IValue val1] => [ ..., val1 is lrel ] */ is_lrel { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isListRelation()); } }, /** * is (is-type) for map type * * [ ... IValue val1] => [ ..., val1 is map ] */ is_map { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isMap()); } }, /** * is (is-type) for node type * * [ ... IValue val1] => [ ..., val1 is node ] */ is_node { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isNode()); } }, /** * is (is-type) for num type * * [ ... IValue val1] => [ ..., val1 is num ] */ is_num { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isNumber()); } }, /** * is (is-type) for rat type * * [ ... IValue val1] => [ ..., val1 is rat ] */ is_rat { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isRational()); } }, /** * is (is-type) for real type * * [ ... IValue val1] => [ ..., val1 is real ] */ is_real { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isReal()); } }, /** * is (is-type) for rel type * * [ ... IValue val1] => [ ..., val1 is rel ] */ is_rel { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isRelation()); } }, /** * is (is-type) for set type * * [ ... IValue val1] => [ ..., val1 is set ] */ is_set { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isSet()); } }, /** * is (is-type) for str type * * [ ... IValue val1] => [ ..., val1 is str ] */ is_str { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isString()); } }, /** * is (is-type) for tuple type * * [ ... IValue val1] => [ ..., val1 is tuple ] */ is_tuple { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_1).getType().isTuple()); } }, /** * is (is-type) for nonterminal type * * [ ... IValue val1] => [ ..., val1 is appl ] */ is_appl { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { Object treeSubject = arg_1; return vf.bool(treeSubject instanceof ITree && TreeAdapter.isAppl((ITree) treeSubject)); } }, /** * is (is-type) for amb type * * [ ... IValue val1] => [ ..., val1 is amb ] */ is_amb { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { Object treeSubject = arg_1; return vf.bool(treeSubject instanceof ITree && TreeAdapter.isAmb((ITree) treeSubject)); } }, /** * is (is-type) for datetimelayout type * * [ ... IValue val1] => [ ..., val1 is layout ] */ is_layout { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue treeSubject = (IValue) arg_1; Type subjectType = treeSubject.getType(); return vf.bool(subjectType.isAbstractData() && TreeAdapter.isLayout((ITree)treeSubject)); } }, /** * is (is-type) for concrete list type * * [ ... IValue val1] => [ ..., val1 is concretelist ] */ is_concretelist { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue treeSubject = (IValue) arg_1; Type subjectType = treeSubject.getType(); return vf.bool(subjectType.isAbstractData() && (TreeAdapter.isList((ITree)treeSubject) || TreeAdapter.isOpt((ITree)treeSubject))); } }, /** * is (is-type) for lexical type * * [ ... IValue val1] => [ ..., val1 is lexical ] */ is_lexical { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue treeSubject = (IValue) arg_1; Type subjectType = treeSubject.getType(); return vf.bool(subjectType.isAbstractData() && TreeAdapter.isLexical((ITree)treeSubject)); } }, /** * is (is-type) for char type * * [ ... IValue val1] => [ ..., val1 is char ] */ is_char { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue treeSubject = (IValue) arg_1; Type subjectType = treeSubject.getType(); return vf.bool(subjectType.isAbstractData() && TreeAdapter.isChar((ITree)treeSubject)); } }, /** * subtype-of * * [ ..., Type t1, Type t1 ] => [ ..., t1 <: t2 ] */ subtype { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((Type) arg_2).isSubtypeOf((Type) arg_1)); //return vf.bool(rex.isSubtypeOf((Type) arg_2, (Type) arg_1)); } }, /** * subtype-of-value * * [ ..., IValue v, Type t ] => [ ..., typeOf(v) <: t ] */ subtype_value_type { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_2).getType().isSubtypeOf((Type) arg_1)); //return vf.bool(rex.isSubtypeOf(((IValue) arg_2).getType(), (Type) arg_1)); } }, /** * subtype-of-value-value * * [ ..., IValue v1, Value v2 ] => [ ..., typeOf(v1) <: typeOf(v2) ] */ subtype_value_value { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.bool(((IValue) arg_2).getType().isSubtypeOf(((IValue) arg_1).getType())); //return vf.bool(rex.isSubtypeOf(((IValue) arg_2).getType(), (Type) arg_1)); } }, /** * typeOf a value * * [ ..., IValue v ] => ..., typeOf(v) ] */ @SuppressWarnings("unchecked") typeOf { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { if(arg_1 instanceof HashSet<?>){ // For the benefit of set matching // Move to muPrimitives? HashSet<IValue> mset = (HashSet<IValue>) arg_1; if(mset.isEmpty()){ return tf.setType(tf.voidType()); } else { IValue v = mset.iterator().next(); // TODO: this is incorrect for set[value]! return tf.setType(v.getType()); } } else { return ((IValue) arg_1).getType(); } } }, /** * Convert from type to Symbol * * [ ..., Type t ] => [ ... Symbol s ] * * TODO redundant arg here */ type2symbol { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { Type type = (Type) arg_2; return rex.typeToSymbol(type); //return $type2symbol(type); } }, /** * Get the element type of a composite type. * * [ ..., Type t ] => [ ..., elementTypeOf(t) ] */ elementTypeOf { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { Type tp = (Type) arg_1; return tp.getElementType(); } }, /*******************************************************************************************************/ /* String templates */ /******************************************************************************************************/ /** * Create a string template * * [ ... ] => [ ... ] * or * [ ..., IString initial ] => [ ..., initial] * * Note: The string builder is maintained implicitly on the templateBuilderStack. * This may cause problems (i.e. leaving spurious builders on that stack) when an exception * occurs during template construction. */ template_open { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity <= 1; String pre = ""; if(arity == 1){ pre = ((IString) stack[sp - 1]).getValue(); stack[sp - 1] = vf.string(""); } else { stack[sp] = vf.string(""); } $pushIndent("", rex); rex.getTemplateBuilderStack().push(rex.getTemplateBuilder()); StringBuilder templateBuilder = new StringBuilder(); templateBuilder.append($unescape(pre)); rex.setTemplateBuilder(templateBuilder); return arity == 1 ? sp : sp + 1; } }, /** * Increase indentation in string template * * [ ..., IString indent ] => [ ..., ""] */ template_indent { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { String ind = ((IString) arg_1).getValue(); $indent(ind, rex); return vf.string(""); } }, /** * Decrease indentation in string template * * [ ..., IString indent ] => [ ..., ""] */ template_unindent { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { String ind = ((IString) arg_1).getValue(); $unindent(ind, rex); return vf.string(""); } }, /** * Add string to string template * * [ ..., IString val ] => [ ..., ""] */ template_add { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IString iarg_s = vf.string($value_to_string(arg_1, currentFrame, rex)); String arg_s = $removeMargins(iarg_s, rex).getValue(); rex.getTemplateBuilder().append(arg_s); return vf.string(""); } }, /** * Close string template * * [ ... ] => [ ..., IString value_of_template] */ template_close { @Override public Object execute0(final Frame currentFrame, final RascalExecutionContext rex) { $popIndent(rex); IString result = vf.string(rex.getTemplateBuilder().toString()); StringBuilder templateBuilder = rex.getTemplateBuilderStack().pop(); rex.setTemplateBuilder(templateBuilder); return result; } }, /******************************************************************************************/ /* Fields and Field updates */ /******************************************************************************************/ /** * Runtime check whether given constructor has a named field * * [ ..., IConstructor cons, IString fieldName, IMap fieldMap ] => [ ..., IBool true if cons does have fieldName ] */ adt_has_field { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IConstructor cons = (IConstructor) stack[sp - 3]; IString field = ((IString) stack[sp - 2]); String fieldName = field.getValue(); IMap fieldNames = (IMap) stack[sp - 1]; ISet fields = (ISet) fieldNames.get(vf.string(cons.getName())); if(fields != null && fields.contains(field)){ stack[sp - 3] = Rascal_TRUE; } else { if(TreeAdapter.isTree(cons) && TreeAdapter.isAppl((ITree) cons)) { IConstructor prod = ((ITree) cons).getProduction(); for(IValue elem : ProductionAdapter.getSymbols(prod)) { IConstructor arg = (IConstructor) elem; if (SymbolAdapter.isLabel(arg) && SymbolAdapter.getLabel(arg).equals(fieldName)) { stack[sp - 3] = Rascal_TRUE; return sp - 2; } } } if(cons.isAnnotatable()){ stack[sp - 3] = cons.asAnnotatable().getAnnotation(fieldName) == null ? Rascal_FALSE : Rascal_TRUE; } else { stack[sp - 3] = Rascal_FALSE; } } return sp - 2; } }, /** * Runtime check whether a node has a named field * * [ ..., INode nd, IString fieldName ] => [ ..., IBool true if cons does have fieldName ] */ node_has_field { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode nd = (INode) arg_2; IString field = ((IString) arg_1); String fieldName = field.getValue(); if ((nd.mayHaveKeywordParameters() && nd.asWithKeywordParameters().getParameter(fieldName) != null)){ return Rascal_TRUE; } else { if(nd.isAnnotatable()){ return nd.asAnnotatable().getAnnotation(fieldName) == null ? Rascal_FALSE : Rascal_TRUE; } else { return Rascal_FALSE; } } } }, /** * Retrieve value of named field of constructor * * [ ..., IConstructor cons, IString fieldName ] => [ ..., IValue value of field fieldName ] */ adt_field_access { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IConstructor cons = (IConstructor) stack[sp - 3]; IString field = ((IString) stack[sp - 2]); String fieldName = field.getValue(); Type tp = cons.getConstructorType(); try { // A positional field? if(tp.hasField(fieldName)){ stack[sp - 3] = cons.get(fieldName); return sp - 2; } // A default field that was set? IValue v = null; if(cons.mayHaveKeywordParameters()){ v = cons.asWithKeywordParameters().getParameter(fieldName); } if(v != null){ stack[sp - 3] = v; return sp - 2; } // A default field that was not set but has a constant value? String consName = cons.getName(); IMap constructorConstantDefaultExpressions = (IMap) stack[sp - 1]; IMap constantFields = (IMap) constructorConstantDefaultExpressions.get(vf.string(consName)); if(constantFields != null){ IValue constantValue = constantFields.get(vf.string(fieldName)); if(constantValue != null){ stack[sp - 3] = constantValue; return sp - 2; } } // TODO jurgen rewrite to ITree API if(TreeAdapter.isTree(cons)){ ITree tree = (ITree) cons; if(TreeAdapter.isAppl(tree)){ IConstructor prod = tree.getProduction(); IList prod_symbols = (IList) prod.get("symbols"); int n = prod_symbols.length(); IList appl_args = (IList) tree.get("args"); // TODO getArgs() gives UnsupportedOperation for(int i = 0; i < n; i++){ IConstructor arg = (IConstructor) prod_symbols.get(i); if(arg.getConstructorType() == RascalValueFactory.Symbol_Label){ if(((IString) arg.get(0)).equals(field)){ stack[sp - 3] = appl_args.get(i); return sp - 2; } } } } } // Next resort: an unset default field with a computed value? Function getDefaults = rex.getCompanionDefaultsFunction(consName, tp); if(getDefaults != RVMCore.noCompanionFunction){ IValue[] posArgs = new IValue[cons.arity()]; for(int i = 0; i < cons.arity(); i++){ posArgs[i] = cons.get(i); } Map<String, IValue> kwArgs = cons.asWithKeywordParameters().getParameters(); @SuppressWarnings("unchecked") Map<String, Map.Entry<Type, IValue>> defaults = (Map<String, Map.Entry<Type, IValue>>) rex.getRVM().executeRVMFunction(getDefaults, posArgs, kwArgs); Entry<Type, IValue> def = defaults.get(fieldName); if(def != null){ stack[sp - 3] = def.getValue(); return sp - 2; } } // Final resort: an unset common data field with a computed value? Function getFieldDefault = rex.getCompanionFieldDefaultFunction(tp.getAbstractDataType(), fieldName); if(getFieldDefault != RVMCore.noCompanionFunction){ IValue[] posArgs = new IValue[0]; Map<String, IValue> kwArgs = cons.asWithKeywordParameters().getParameters(); IValue defaultValue = (IValue) rex.getRVM().executeRVMFunction(getFieldDefault, posArgs, kwArgs); stack[sp - 3] = defaultValue; return sp - 2; } rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField(fieldName, currentFrame)); } catch(FactTypeUseException e) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField(fieldName, currentFrame)); } return sp - 2; } }, /** * Is a named field of a constructor defined? Returns false when: * - constructor does not have the field * - the field is a default field with unset value. * * [ ..., IConstructor cons, IString fieldName ] => [ ..., bool ] */ is_defined_adt_field_access_get { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IConstructor cons = (IConstructor) arg_2; IString field = ((IString) arg_1); String fieldName = field.getValue(); Type tp = cons.getConstructorType(); try { // A positional field? if(tp.hasField(fieldName)){ temp_array_of_2[0] = Rascal_TRUE; int fld_index = tp.getFieldIndex(fieldName); temp_array_of_2[1] = cons.get(fld_index); return temp_array_of_2; } // A default field that was set? IValue v = null; if(cons.mayHaveKeywordParameters()){ v = cons.asWithKeywordParameters().getParameter(fieldName); } if(v != null){ temp_array_of_2[0] = Rascal_TRUE; temp_array_of_2[1] = v; return temp_array_of_2; } // TODO jurgen rewrite to ITree API if(TreeAdapter.isTree(cons)){ ITree tree = (ITree) cons; if(TreeAdapter.isAppl(tree)){ IConstructor prod = tree.getProduction(); IList prod_symbols = (IList) prod.get("symbols"); int n = prod_symbols.length(); IList appl_args = (IList) tree.get("args"); // TODO getArgs() gives UnsupportedOperation for(int i = 0; i < n; i++){ IConstructor arg = (IConstructor) prod_symbols.get(i); if(arg.getConstructorType() == RascalValueFactory.Symbol_Label){ if(((IString) arg.get(0)).equals(field)){ temp_array_of_2[0] = Rascal_TRUE; temp_array_of_2[1] = appl_args.get(i); return temp_array_of_2; } } } } } // Final resort: an unset default field: fall through and return false } catch(FactTypeUseException e) { } temp_array_of_2[0] = Rascal_FALSE; return temp_array_of_2; } }, /** * Is a named field of a node defined? Returns true when: * - the field is a default field with set value. * * [ ..., INode nd, IString fieldName ] => [ ..., bool ] */ is_defined_node_field_access_get { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode nd = (INode) arg_2; IString field = ((IString) arg_1); String fieldName = field.getValue(); try { // A default field that was set? IValue v = null; if(nd.mayHaveKeywordParameters()){ v = nd.asWithKeywordParameters().getParameter(fieldName); } if(v != null){ temp_array_of_2[0] = Rascal_TRUE; temp_array_of_2[1] = v; return temp_array_of_2; } // Final resort: an unset default field: fall through and return false } catch(FactTypeUseException e) { } temp_array_of_2[0] = Rascal_FALSE; return temp_array_of_2; } }, /** * Is a named field of a location defined? * * [ ..., ISourceLocation nd, IString fieldName ] => [ ..., bool ] */ // is_defined_loc_field_access_get { // @Override // public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { // // try { // temp_array_of_2[0] = Rascal_TRUE; // temp_array_of_2[1] = loc_field_access.execute2(arg_2, arg_1, currentFrame, rex);; // return temp_array_of_2; // // } catch(Exception e) { // temp_array_of_2[0] = Rascal_FALSE; // } // return temp_array_of_2; // } // }, /** * Retrieve value of named field of datetime value * * [ ..., IDateTime dt, IString fieldName ] => [ ..., IValue value of field fieldName ] */ datetime_field_access { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IDateTime dt = ((IDateTime) arg_2); String field = ((IString) arg_1).getValue(); IValue v; try { switch (field) { case "isDate": v = vf.bool(dt.isDate()); break; case "isTime": v = vf.bool(dt.isTime()); break; case "isDateTime": v = vf.bool(dt.isDateTime()); break; case "century": if (!dt.isTime()) { v = vf.integer(dt.getCentury()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the century on a time value", currentFrame)); case "year": if (!dt.isTime()) { v = vf.integer(dt.getYear()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the year on a time value", currentFrame)); case "month": if (!dt.isTime()) { v = vf.integer(dt.getMonthOfYear()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the month on a time value", currentFrame)); case "day": if (!dt.isTime()) { v = vf.integer(dt.getDayOfMonth()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the day on a time value", currentFrame)); case "hour": if (!dt.isDate()) { v = vf.integer(dt.getHourOfDay()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the hour on a date value", currentFrame)); case "minute": if (!dt.isDate()) { v = vf.integer(dt.getMinuteOfHour()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the minute on a date value", currentFrame)); case "second": if (!dt.isDate()) { v = vf.integer(dt.getSecondOfMinute()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the second on a date value", currentFrame)); case "millisecond": if (!dt.isDate()) { v = vf.integer(dt.getMillisecondsOfSecond()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the millisecond on a date value", currentFrame)); case "timezoneOffsetHours": if (!dt.isDate()) { v = vf.integer(dt.getTimezoneOffsetHours()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the timezone offset hours on a date value", currentFrame)); case "timezoneOffsetMinutes": if (!dt.isDate()) { v = vf.integer(dt.getTimezoneOffsetMinutes()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the timezone offset minutes on a date value", currentFrame)); case "justDate": if (!dt.isTime()) { v = vf.date(dt.getYear(), dt.getMonthOfYear(), dt.getDayOfMonth()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the date component of a time value", currentFrame)); case "justTime": if (!dt.isDate()) { v = vf.time(dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute(), dt.getMillisecondsOfSecond(), dt.getTimezoneOffsetHours(), dt.getTimezoneOffsetMinutes()); break; } return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("Can not retrieve the time component of a date value", currentFrame)); default: return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField(field, currentFrame)); } return v; } catch (InvalidDateTimeException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(dt, currentFrame, e.getMessage())); } } }, /** * Update value of named field of datetime value * * [ ..., IDateTime dt, IString fieldName, IValue repl ] => [ ..., new IDateTime value with updated value for field fieldName ] */ datetime_field_update { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IDateTime dt = ((IDateTime) stack[sp - 3]); String field = ((IString) stack[sp - 2]).getValue(); IValue repl = (IValue) stack[sp - 1]; // Individual fields int year = dt.getYear(); int month = dt.getMonthOfYear(); int day = dt.getDayOfMonth(); int hour = dt.getHourOfDay(); int minute = dt.getMinuteOfHour(); int second = dt.getSecondOfMinute(); int milli = dt.getMillisecondsOfSecond(); int tzOffsetHour = dt.getTimezoneOffsetHours(); int tzOffsetMin = dt.getTimezoneOffsetMinutes(); try { switch (field) { case "year": if (dt.isTime()) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfTime("Can not update the year on a time value", currentFrame)); } year = ((IInteger)repl).intValue(); break; case "month": if (dt.isTime()) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfTime("Can not update the month on a time value", currentFrame)); } month = ((IInteger)repl).intValue(); break; case "day": if (dt.isTime()) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfTime("Can not update the day on a time value", currentFrame)); } day = ((IInteger)repl).intValue(); break; case "hour": if (dt.isDate()) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfDate("Can not update the hour on a date value", currentFrame)); } hour = ((IInteger)repl).intValue(); break; case "minute": if (dt.isDate()) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfDate("Can not update the minute on a date value", currentFrame)); } minute = ((IInteger)repl).intValue(); break; case "second": if (dt.isDate()) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfDate("Can not update the second on a date value", currentFrame)); } second = ((IInteger)repl).intValue(); break; case "millisecond": if (dt.isDate()) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfDate("Can not update the millisecond on a date value", currentFrame)); } milli = ((IInteger)repl).intValue(); break; case "timezoneOffsetHours": if (dt.isDate()) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfDate("Can not update the timezone offset hours on a date value", currentFrame)); } tzOffsetHour = ((IInteger)repl).intValue(); break; case "timezoneOffsetMinutes": if (dt.isDate()) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfDate("Can not update the timezone offset minutes on a date value", currentFrame)); } tzOffsetMin = ((IInteger)repl).intValue(); break; default: rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField(field, currentFrame)); } IDateTime newdt = null; if (dt.isDate()) { newdt = vf.date(year, month, day); } else if (dt.isTime()) { newdt = vf.time(hour, minute, second, milli, tzOffsetHour, tzOffsetMin); } else { newdt = vf.datetime(year, month, day, hour, minute, second, milli, tzOffsetHour, tzOffsetMin); } stack[sp - 3] = newdt; return sp - 2; } catch (IllegalArgumentException e) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(repl, currentFrame, "Cannot update field " + field + ", this would generate an invalid datetime value")); } catch (InvalidDateTimeException e) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(dt, currentFrame, e.getMessage())); } return sp - 2; } }, /** * Retrieve value of named field of loc value * * [ ..., ISourceLocation sloc, IString fieldName ] => [ ..., IValue value of field fieldName ] */ loc_field_access { @SuppressWarnings("deprecation") @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISourceLocation sloc = ((ISourceLocation) arg_2); String field = ((IString) arg_1).getValue(); IValue v; switch (field) { case "scheme": String s = sloc.getScheme(); v = vf.string(s == null ? "" : s); break; case "authority": v = vf.string(sloc.hasAuthority() ? sloc.getAuthority() : ""); break; case "host": if (!URIResolverRegistry.getInstance().supportsHost(sloc)) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField("The scheme " + sloc.getScheme() + " does not support the host field, use authority instead.", currentFrame)); } s = sloc.getURI().getHost(); v = vf.string(s == null ? "" : s); break; case "path": v = vf.string(sloc.hasPath() ? sloc.getPath() : "/"); break; case "parent": String path = sloc.getPath(); if (path.equals("")) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noParent(sloc, currentFrame)); } int i = path.lastIndexOf("/"); if (i != -1) { path = path.substring(0, i); if (sloc.getScheme().equalsIgnoreCase("file")) { // there is a special case for file references to windows paths. // the root path should end with a / (c:/ not c:) if (path.lastIndexOf((int)'/') == 0 && path.endsWith(":")) { path += "/"; } } v = $loc_field_update(sloc, "path", vf.string(path), currentFrame, rex); } else { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noParent(sloc, currentFrame)); } break; case "file": path = sloc.hasPath() ? sloc.getPath() : ""; i = path.lastIndexOf((int)'/'); if (i != -1) { path = path.substring(i+1); } v = vf.string(path); break; case "ls": try { // Why is this needed: ISourceLocation resolved = rex.resolveSourceLocation(sloc); ISourceLocation resolved = sloc; IListWriter w = vf.listWriter(); for (ISourceLocation elem : URIResolverRegistry.getInstance().list(resolved)) { w.append(elem); } v = w.done(); break; } catch (IOException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.io(vf.string(e.getMessage()), currentFrame)); } case "extension": path = sloc.hasPath() ? sloc.getPath() : ""; i = path.lastIndexOf('.'); if (i != -1) { v = vf.string(path.substring(i + 1)); } else { v = vf.string(""); } break; case "fragment": v = vf.string(sloc.hasFragment() ? sloc.getFragment() : ""); break; case "query": v = vf.string(sloc.hasQuery() ? sloc.getQuery() : ""); break; case "params": String query = sloc.hasQuery() ? sloc.getQuery() : ""; IMapWriter res = vf.mapWriter(tf.stringType(), tf.stringType()); if (query.length() > 0) { String[] params = query.split("&"); for (String param : params) { String[] keyValue = param.split("="); res.put(vf.string(keyValue[0]), vf.string(keyValue[1])); } } v = res.done(); break; case "user": if (!URIResolverRegistry.getInstance().supportsHost(sloc)) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField("The scheme " + sloc.getScheme() + " does not support the user field, use authority instead.", currentFrame)); } s = sloc.getURI().getUserInfo(); v = vf.string(s == null ? "" : s); break; case "port": if (!URIResolverRegistry.getInstance().supportsHost(sloc)) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField("The scheme " + sloc.getScheme() + " does not support the port field, use authority instead.", currentFrame)); } int n = sloc.getURI().getPort(); v = vf.integer(n); break; case "length": if(sloc.hasOffsetLength()){ v = vf.integer(sloc.getLength()); break; } else { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("length", currentFrame)); } case "offset": if(sloc.hasOffsetLength()){ v = vf.integer(sloc.getOffset()); break; } else { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("offset", currentFrame)); } case "begin": if(sloc.hasLineColumn()){ v = vf.tuple(lineColumnType, vf.integer(sloc.getBeginLine()), vf.integer(sloc.getBeginColumn())); break; } else { return RascalRuntimeException.unavailableInformation("begin", currentFrame); } case "end": if(sloc.hasLineColumn()){ v = vf.tuple(lineColumnType, vf.integer(sloc.getEndLine()), vf.integer(sloc.getEndColumn())); break; } else { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.unavailableInformation("end", currentFrame)); } case "uri": v = vf.string(sloc.getURI().toString()); break; case "top": v = sloc.top(); break; default: return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField(field, currentFrame)); } return v; } }, /** * Is a named field of a location defined? Returns * - <true, field value> when the field exists and its value is defined * - false, _> otherwise * * [ ..., INode nd, IString fieldName ] => [ ..., [bool, value] ] */ is_defined_loc_field_access_get { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { try { temp_array_of_2[1] = loc_field_access.execute2(arg_2, arg_1, currentFrame, rex); temp_array_of_2[0] = Rascal_TRUE; } catch (Exception e) { // TODO: this hides implementation bugs and its not the semantics of isDefined. temp_array_of_2[0] = Rascal_FALSE; } return temp_array_of_2; } }, /** * Update value of named field of loc value * * [ ..., ISourceLocation sloc, IString fieldName, IValue repl ] => [ ..., new ISourceLocation value with updated value for field fieldName ] */ loc_field_update { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; ISourceLocation sloc = ((ISourceLocation) stack[sp - 3]); String field = ((IString) stack[sp - 2]).getValue(); IValue repl = (IValue) stack[sp - 1]; stack[sp - 3] = $loc_field_update(sloc, field, repl, currentFrame, rex); return sp - 2; } }, /** * retrieve value of named field of lrel value * * [ ..., IListRelation sloc, IString fieldName ] => [ ..., IValue value for field fieldName ] */ lrel_field_access { @SuppressWarnings("deprecation") @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IListRelation<IList> left = ((IList) arg_2).asRelation(); return left.projectByFieldNames(((IString) arg_1).getValue()); } }, /** * retrieve value of named field of rel value * * [ ..., IRelation sloc, IString fieldName ] => [ ..., IValue value for field fieldName ] */ rel_field_access { @SuppressWarnings("deprecation") @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISetRelation<ISet> left = ((ISet) arg_2).asRelation(); return left.projectByFieldNames(((IString) arg_1).getValue()); } }, // TODO document this reified_field_access { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IConstructor reified = (IConstructor) arg_2; String field = ((IString) arg_1).getValue(); return reified.get(field); } }, /** * retrieve value of named field of nonterminal value * * [ ..., IConstructor appl, IString fieldName ] => [ ..., IValue value for field fieldName ] */ nonterminal_field_access { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITree appl = (ITree) arg_2; IString field = ((IString) arg_1); IList appl_args = (IList) appl.get("args"); // TODO getArgs() gives UnsupportedOperation // Note: the "args" fields is used to access the arguments of concrete lists // So far, there has been no need to support other fields but more fields might // be added here. if(field.getValue().equals("args")){ return appl_args; } IConstructor prod = appl.getProduction(); IList prod_symbols = (IList) prod.get("symbols"); int n = prod_symbols.length(); for(int i = 0; i < n; i++){ IConstructor arg = (IConstructor) prod_symbols.get(i); if(arg.getConstructorType() == RascalValueFactory.Symbol_Conditional){ arg = (IConstructor) arg.get(0); } if(arg.getConstructorType() == RascalValueFactory.Symbol_Label){ if(((IString) arg.get(0)).equals(field)){ return appl_args.get(i); } } } return RascalRuntimeException.noSuchField(field.getValue(), currentFrame); } }, /** * Update value of named field of nonterminal value * * [ ..., IConstructor appl, IString fieldName, IValue repl ] => [ ..., new IConstructor value with updated value for field fieldName ] */ nonterminal_field_update { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; ITree appl = (ITree) stack[sp - 3]; IString field = ((IString) stack[sp - 2]); ITree repl = (ITree) stack[sp - 1]; IList appl_args = (IList) appl.get("args"); // TODO getArgs() gives UnsupportedOperation // // Note: the "args" fields is used to access the arguments of concrete lists // // So far, there has been no need to support other fields but more fields might // // be added here. // if(field.getValue().equals("args")){ // return appl_args; // return sp - 1; // } IConstructor prod = appl.getProduction(); IList prod_symbols = (IList) prod.get("symbols"); int n = prod_symbols.length(); for(int i = 0; i < n; i++){ IConstructor arg = (IConstructor) prod_symbols.get(i); if(arg.getConstructorType() == RascalValueFactory.Symbol_Conditional){ arg = (IConstructor) arg.get(0); } if(arg.getConstructorType() == RascalValueFactory.Symbol_Label){ if(((IString) arg.get(0)).equals(field)){ appl_args = appl_args.put(i, repl); stack[sp - 3] = vf.constructor(RascalValueFactory.Tree_Appl, prod, appl_args); return sp - 2; } } } rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField(field.getValue(), currentFrame)); return sp - 2; } }, /** * Run-time check that nonterminal value has a given named field. * * [ ..., IConstructor appl, IString fieldName ] => [ ..., IBool true if named field is present ] */ nonterminal_has_field { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITree appl = (ITree) arg_2; IString field = ((IString) arg_1); IConstructor prod = appl.getProduction(); IList prod_symbols = (IList) prod.get("symbols"); int n = prod_symbols.length(); for(int i = 0; i < n; i++){ IConstructor arg = (IConstructor) prod_symbols.get(i); if(arg.getConstructorType() == RascalValueFactory.Symbol_Conditional){ arg = (IConstructor) arg.get(0); } if(arg.getConstructorType() == RascalValueFactory.Symbol_Label){ if(((IString) arg.get(0)).equals(field)){ return Rascal_TRUE; } } } return Rascal_FALSE; } }, /** * Get value of a named field of a tuple * * [ ..., ITuple tup, IString fieldName ] => [ ..., IValue value of field fieldName ] */ tuple_field_access { @SuppressWarnings("deprecation") @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((ITuple) arg_2).get(((IString) arg_1).getValue()); } }, /** * Set value of a named field of a tuple * * [ ..., ITuple tup, IString fieldName, IValue repl ] => [ ..., new ITuple with field fieldName set to repl ] */ tuple_field_update { @SuppressWarnings("deprecation") @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; stack[sp - 3] = ((ITuple) stack[sp - 3]).set(((IString) stack[sp - 2]).getValue(), (IValue) stack[sp - 1]); return sp - 2; } }, /** * Get projection of tuple elements by field name or index * * [ ..., ITuple tup, IValue nameOrIndex1, IValue nameOrIndex2, ... ] => [ ..., new ITuple containing the projected elements ] */ tuple_field_project { @SuppressWarnings("deprecation") @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 2; ITuple tup = (ITuple) stack[sp - arity]; IValue [] newFields = new IValue[arity - 1]; for(int i = 0; i < arity - 1; i++){ IValue field = (IValue) stack[sp - arity + 1 + i]; newFields[i] = field.getType().isInteger() ? tup.get(((IInteger) field).intValue()) : tup.get(((IString) field).getValue()); } stack[sp - arity] = (arity - 1 > 1) ? vf.tuple(newFields) : newFields[0]; return sp - arity + 1; } }, /** * Set named field of constructor value * * [ ..., IConstructor cons, IString fieldName, IValue repl... ] => [ ..., new IConstructor with named field set to repl ] */ adt_field_update { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IConstructor cons = (IConstructor) stack[sp - 3]; IString field = ((IString) stack[sp - 2]); String fieldName = field.getValue(); IValue repl = (IValue) stack[sp - 1]; Type tp = cons.getConstructorType(); try { //stack[sp - 3] = ((IConstructor) stack[sp - 3]).set(((IString) stack[sp - 2]).getValue(), (IValue) stack[sp -1]); if(tp.hasField(fieldName)){ // A positional field int fld_index = tp.getFieldIndex(fieldName); stack[sp - 3] = cons.set(fld_index, repl); return sp - 2; } if(cons.mayHaveKeywordParameters()){ stack[sp - 3] = cons.asWithKeywordParameters().setParameter(fieldName, repl); return sp - 2; } rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.notImplemented("Assignment to parse tree field not yet implemented", currentFrame.src, currentFrame)); } catch(FactTypeUseException e) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField(((IString) stack[sp - 2]).getValue(), currentFrame)); } return sp - 2; } }, /** * Get projection of a relation consisting of tuple elements projected by field name or index * * [ ..., IRelation rel, IValue nameOrIndex1, IValue nameOrIndex2, ... ] => [ ..., new IRelation containing the projected elements ] */ rel_field_project { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 2; ISet rel = (ISet) stack[sp - arity]; int indexArity = arity - 1; int[] fields = new int[arity - 1]; for(int i = 1; i < arity; i++){ fields[i - 1] = ((IInteger)stack[sp - arity + i]).intValue(); } ISetWriter w = vf.setWriter(); IValue[] elems = new IValue[arity - 1]; for(IValue vtup : rel){ ITuple tup = (ITuple) vtup; for(int j = 0; j < fields.length; j++){ elems[j] = tup.get(fields[j]); } w.insert((indexArity > 1) ? vf.tuple(elems) : elems[0]); } stack[sp - arity] = w.done(); return sp - arity + 1; } }, /** * Get projection of a list relation consisting of tuple elements projected by field name or index * * [ ..., IListRelation lrel, IValue nameOrIndex1, IValue nameOrIndex2, ... ] => [ ..., new IListRelation containing the projected elements ] */ lrel_field_project { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 2; IList lrel = (IList) stack[sp - arity]; int indexArity = arity - 1; int[] fields = new int[arity - 1]; for(int i = 1; i < arity; i++){ fields[i - 1] = ((IInteger)stack[sp - arity + i]).intValue(); } IListWriter w = vf.listWriter(); IValue[] elems = new IValue[arity - 1]; for(IValue vtup : lrel){ ITuple tup = (ITuple) vtup; for(int j = 0; j < fields.length; j++){ elems[j] = tup.get(fields[j]); } w.append((indexArity > 1) ? vf.tuple(elems) : elems[0]); } stack[sp - arity] = w.done(); return sp - arity + 1; } }, /** * Get projection of a map with elements projected by field name or index * * [ ..., IMap map, IValue nameOrIndex1, IValue nameOrIndex2, ... ] => [ ..., new IMap containing the projected elements ] */ map_field_project { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 2; IMap map = (IMap) stack[sp - arity]; int indexArity = arity - 1; int[] fields = new int[indexArity]; for(int i = 1; i < arity; i++){ fields[i - 1] = ((IInteger)stack[sp - arity + i]).intValue(); } ISetWriter w = vf.setWriter(); IValue[] elems = new IValue[indexArity]; Iterator<Entry<IValue,IValue>> iter = map.entryIterator(); while (iter.hasNext()) { Entry<IValue,IValue> entry = iter.next(); for(int j = 0; j < fields.length; j++){ elems[j] = fields[j] == 0 ? entry.getKey() : entry.getValue(); } w.insert((indexArity > 1) ? vf.tuple(elems) : elems[0]); } stack[sp - arity] = w.done(); return sp - arity + 1; } }, /************************************************************************************************/ /* Various getters */ /************************************************************************************************/ /** * Get the non-layout arguments of a nonterminal value * * [ ... ITree val1] => [ ..., IList args ] */ get_nonlayout_args { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue treeSubject = (IValue) arg_1; return TreeAdapter.getNonLayoutArgs((ITree)treeSubject); } }, /** * Get the arguments of a nonterminal value * * [ ... ITree val1] => [ ..., IList args ] */ get_appl_args { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue treeSubject = (IValue) arg_1; return TreeAdapter.getArgs((ITree)treeSubject); } }, /** * Get the alternmatives of an amb value * * [ ... ITree val1] => [ ..., IList alternatives ] */ get_amb_alternatives { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITree treeSubject = (ITree) arg_1; return TreeAdapter.getAlternatives(treeSubject); } }, /** * Get the non-layout elements of a concrete list * * [ ... ITree val1] => [ ..., IList elements ] */ get_concrete_list_elements { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITree treeSubject = (ITree) arg_1; if (!(TreeAdapter.isList(treeSubject) || TreeAdapter.isOpt(treeSubject))) { // Fixes TreeAdapter.getListASTArgs for the case of lexical list in concrete context throw new ImplementationError( "This is not a context-free list production: " + treeSubject); } IList children = TreeAdapter.getArgs(treeSubject); IListWriter writer = ValueFactoryFactory.getValueFactory().listWriter(); IConstructor symbol = TreeAdapter.getType(treeSubject); boolean layoutPresent = false; if(children.length() > 1){ ITree child1 = (ITree)children.get(1); if(TreeAdapter.isLayout(child1)){ layoutPresent = true; } } int delta = layoutPresent ? 2 : 1; if(SymbolAdapter.isIterPlusSeps(symbol) || SymbolAdapter.isIterStarSeps(symbol)){ IList separators = SymbolAdapter.getSeparators(symbol); boolean nonLayoutSeparator = false; for(IValue sep : separators){ if(!((IConstructor) sep).getName().equals("layouts")){ nonLayoutSeparator = true; break; } } delta = nonLayoutSeparator && layoutPresent ? 4 : 2; } for (int i = 0; i < children.length();) { IValue kid = children.get(i); writer.append(kid); // skip layout and/or separators i += delta; } return writer.done(); } }, /** * Strip a conditional from a lexical node * * [ ... IConstructor val1] => [ ..., IConstructor val2 ] */ strip_lexical { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IConstructor lexSubject = (IConstructor) arg_1; if(lexSubject.getName().equals("conditional")){ lexSubject = (IConstructor) lexSubject.get("symbol"); } return lexSubject; } }, /** * Get the type of a nonterminal value as Symbol * * [ ... ITree val1] => [ ..., IConstructor type ] */ get_tree_type_as_symbol { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue treeSubject = (IValue) arg_1; return TreeAdapter.getType((ITree)treeSubject); } }, /** * Get the type of a nonterminal value as Type * * [ ... ITree val1] => [ ..., IConstructor type ] */ get_tree_type_as_type { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue treeSubject = (IValue) arg_1; IConstructor symbol = TreeAdapter.getType((ITree)treeSubject); String typeName = ((IString)symbol.get(0)).getValue(); return vf.constructor(RascalValueFactory.Symbol_Sort, vf.string(typeName)); } }, /************************************************************************************************/ /* Slices */ /************************************************************************************************/ /** * Replace a list slice * [ ... IList lst, IInteger from, IInteger by, IInteger to, IList repl ] => [ ..., new IList lst with slice elements replaced by elements of repl ] */ list_slice_replace { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { return $list_slice_operator(stack, sp, arity, SliceOperator.replace(), currentFrame, rex); } }, /** * Add value to a list slice * [ ... IList lst, IInteger from, IInteger by, IInteger to, IValue val ] => [ ..., new IList lst with val added to slice elements ] */ list_slice_add { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { return $list_slice_operator(stack, sp, arity, SliceOperator.add(), currentFrame, rex); } }, /** * Subtract value from a list slice * [ ... IList lst, IInteger from, IInteger by, IInteger to, IValue val ] => [ ..., new IList lst with val subtracted from slice elements ] */ list_slice_subtract { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { return $list_slice_operator(stack, sp, arity, SliceOperator.subtract(), currentFrame, rex); } }, /** * Multiply elements of a list slice by a value * [ ... IList lst, IInteger from, IInteger by, IInteger to, IValue val ] => [ ..., new IList lst with slice elements multiplied by val ] */ list_slice_product { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { return $list_slice_operator(stack, sp, arity, SliceOperator.product(), currentFrame, rex); } }, /** * Divide elements of a list slice by a value * [ ... IList lst, IInteger from, IInteger by, IInteger to, IValue val ] => [ ..., new IList lst with slice elements divided by val ] */ list_slice_divide { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { return $list_slice_operator(stack, sp, arity, SliceOperator.divide(), currentFrame, rex); } }, /** * Intersect elements of a list slice * [ ... IList lst, IInteger from, IInteger by, IInteger to, IValue val ] => [ ..., new IList lst with slice elements intersected with val ] */ list_slice_intersect { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { return $list_slice_operator(stack, sp, arity, SliceOperator.intersect(), currentFrame, rex); } }, /** * Replace string slice by a value * [ ... IString s, IInteger from, IInteger by, IInteger to, IString val ] => [ ..., new IString s with slice elements replaced by val ] */ str_slice_replace { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 5; IString str = (IString) stack[sp - 5]; SliceDescriptor sd = $makeSliceDescriptor($getInt((IValue) stack[sp - 4]), $getInt((IValue) stack[sp - 3]), $getInt((IValue) stack[sp - 2]), str.length(), currentFrame); IString repl = (IString) stack[sp - 1]; stack[sp - 5] = str.replace(sd.first, sd.second, sd.end, repl); return sp - 4; } }, /** * Replace elements in node slice * [ ... IString s, IInteger from, IInteger by, IInteger to, IList val ] => [ ..., new INode s with slice elements replaced by elements in val ] */ node_slice_replace { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 5; INode node = (INode) stack[sp - 5]; int nd_arity = node.arity(); SliceDescriptor sd = $makeSliceDescriptor($getInt((IValue) stack[sp - 4]), $getInt((IValue) stack[sp - 3]), $getInt((IValue) stack[sp - 2]), nd_arity, currentFrame); IList repl = (IList) stack[sp - 1]; stack[sp - 5] = node.replace(sd.first, sd.second, sd.end, repl); return sp - 4; } }, /** * Create list slice * [ ... IList lst, IInteger from, IInteger by, IInteger to] => [ ..., new IList with slice elements ] */ list_slice { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 4; IList lst = (IList) stack[sp - 4]; stack[sp - 4] = $makeSlice(lst, $makeSliceDescriptor($getInt((IValue) stack[sp - 3]), $getInt((IValue) stack[sp - 2]), $getInt((IValue) stack[sp - 1]), lst.length(), currentFrame)); return sp - 3; } }, /** * Create str slice * [ ... IString s, IInteger from, IInteger by, IInteger to] => [ ..., new IString with slice elements ] */ str_slice { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 4; IString str = (IString) stack[sp - 4]; stack[sp - 4] = $makeSlice(str, $makeSliceDescriptor($getInt((IValue) stack[sp - 3]), $getInt((IValue) stack[sp - 2]), $getInt((IValue) stack[sp - 1]), str.length(), currentFrame)); return sp - 3; } }, /** * Create node slice * [ ... INode node, IInteger from, IInteger by, IInteger to] => [ ..., new INode with slice elements as args ] */ node_slice { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 4; INode node = (INode) stack[sp - 4]; int nd_arity = node.arity(); stack[sp - 4] = $makeSlice(node, $makeSliceDescriptor($getInt((IValue) stack[sp - 3]), $getInt((IValue) stack[sp - 2]), $getInt((IValue) stack[sp - 1]), nd_arity, currentFrame)); return sp - 3; } }, /** * Create concrete list slice * [ ... ITree tree, IInteger from, IInteger by, IInteger to] => [ ..., new INode with slice elements as args ] */ concrete_list_slice { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 5; ITree tree = (ITree) stack[sp - 5]; IList elems = TreeAdapter.getArgs(tree); int len = elems.length(); int sep_count = TreeAdapter.getSeparatorCount(tree); int list_length = (len == 0) ? 0 : ((sep_count == 0 ? len : 1 + len/(1 + sep_count))); int min_length = $getInt((IValue) stack[sp - 1]); stack[sp - 5] = $makeSlice(tree, sep_count, min_length, $makeSliceDescriptor($getInt((IValue) stack[sp - 4]), $getInt((IValue) stack[sp - 3]), $getInt((IValue) stack[sp - 2]), list_length, currentFrame)); if(stack[sp - 5] == null){ rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(tree, currentFrame, "sliced value should have length of at least " + min_length)); } return sp - 4; } }, /** * Create nonterminal slice * [ ... ITree tree, IInteger from, IInteger by, IInteger to] => [ ..., new INode with slice elements as args ] */ nonterminal_slice { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 4; ITree tree = (ITree) stack[sp - 4]; int tree_arity = TreeAdapter.getArgs(tree).length(); stack[sp - 4] = $makeSlice(tree, $makeSliceDescriptor($getInt((IValue) stack[sp - 3]), $getInt((IValue) stack[sp - 2]), $getInt((IValue) stack[sp - 1]), tree_arity, currentFrame)); return sp - 3; } }, /** * Create lexical slice * [ ... ITree tree, IInteger from, IInteger by, IInteger to] => [ ..., new INode with slice elements as args ] */ lex_slice { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 4; ITree tree = (ITree) stack[sp - 4]; int tree_arity = TreeAdapter.getArgs(tree).length(); stack[sp - 4] = $makeSlice(tree, $makeSliceDescriptor($getInt((IValue) stack[sp - 3]), $getInt((IValue) stack[sp - 2]), $getInt((IValue) stack[sp - 1]), tree_arity, currentFrame)); return sp - 3; } }, /** * Splice elements in a list writer * * [ ..., IListWriter w, IListOrISet val ] => [ ..., w with val's elements spliced in ] */ listwriter_splice { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IListWriter writer = (IListWriter)arg_2; if(arg_1 instanceof IList){ IList lst = (IList) arg_1; for(IValue v : lst){ writer.append(v); } } else if(arg_1 instanceof ISet){ ISet set = (ISet) arg_1; for(IValue v : set){ writer.append(v); } } else { writer.append((IValue) arg_1); } return writer; } }, /** * Splice elements in a set writer * * [ ..., ISetWriter w, IListOrISet val ] => [ ..., w with val's elements spliced in ] */ setwriter_splice { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISetWriter writer = (ISetWriter)arg_2; if(arg_1 instanceof IList){ IList lst = (IList) arg_1; for(IValue v : lst){ writer.insert(v); } } else if(arg_1 instanceof ISet){ ISet set = (ISet) arg_1; for(IValue v : set){ writer.insert(v); } } else { writer.insert((IValue) arg_1); } return writer; } }, /** * Splice elements of a concrete list in a list writer * * [ ..., IListWriter w, ConcreteList val ] => [ ..., w with val's elements spliced in ] */ listwriter_splice_concrete_list_var { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IListWriter writer = (IListWriter)arg_2; IConstructor nonterm = (IConstructor) arg_1; // stdout.println("nonterm = " + nonterm); IList nonterm_args = (IList) nonterm.get("args"); // stdout.println("nonterm_args = " + nonterm_args); if($getIterDelta((IConstructor) ((IConstructor) nonterm.get("prod")).get(0)) >= 0){ for(IValue v : nonterm_args) { // stdout.println("append: " + v); writer.append(v); } } else { IConstructor iter = (IConstructor) nonterm_args.get(0); // stdout.println("iter = " + iter); IList iter_args = (IList) iter.get("args"); // stdout.println("iter_args = " + iter_args); for(IValue v : iter_args) { // stdout.println("append: " + v); writer.append(v); } } return writer; } }, /************************************************************************************************/ /* Subscripting */ /************************************************************************************************/ /** * Get subscripted element from adt * * [ ..., IConstructor cons, IInteger idx ] => [ ..., IValue argument idx from cons ] */ adt_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IConstructor cons = (IConstructor) arg_2; int idx = ((IInteger) arg_1).intValue(); try { return cons.get((idx >= 0) ? idx : (cons.arity() + idx)); } catch(IndexOutOfBoundsException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds((IInteger) arg_1, currentFrame)); } } }, /** * Has adt constructor an argument with given index? * * [ ..., IConstructor cons, IInteger idx ] => [ ..., IBool true if idx is legal index] */ is_defined_adt_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IConstructor cons = (IConstructor) arg_2; int idx = ((IInteger) arg_1).intValue(); try { temp_array_of_2[1] = cons.get((idx >= 0) ? idx : (cons.arity() + idx)); temp_array_of_2[0] = Rascal_TRUE; } catch(IndexOutOfBoundsException e) { temp_array_of_2[0] = Rascal_FALSE; } return temp_array_of_2; } }, /** * Get subscripted element from node * * [ ..., INode nd, IInteger idx ] => [ ..., IValue argument idx from nd ] */ node_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode node = (INode) arg_2; int idx = ((IInteger) arg_1).intValue(); try { if(idx < 0){ idx = node.arity() + idx; } return node.get(idx); } catch(IndexOutOfBoundsException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds((IInteger) arg_1, currentFrame)); } } }, /** * Has node an argument with given index? * * [ ..., INode nd, IInteger idx ] => [ ..., IBool true if idx is legal index] */ is_defined_node_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode node = (INode) arg_2; int idx = ((IInteger) arg_1).intValue(); try { if(idx < 0){ idx = node.arity() + idx; } temp_array_of_2[0] = Rascal_TRUE; temp_array_of_2[1] = node.get(idx); } catch(IndexOutOfBoundsException e) { temp_array_of_2[0] = Rascal_FALSE; } return temp_array_of_2; } }, /** * Get element with given index from list * * [ ..., IList lst, IInteger idx ] => [ ..., IValue list element with index idx ] */ list_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList lst = ((IList) arg_2); int idx = ((IInteger) arg_1).intValue(); try { return lst.get((idx >= 0) ? idx : (lst.length() + idx)); } catch(IndexOutOfBoundsException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds((IInteger) arg_1, currentFrame)); } } }, /** * Has list an element with given index? * * [ ..., IList lst, IInteger idx ] => [ ..., IBool true if idx is legal index ] */ is_defined_list_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IList lst = ((IList) arg_2); int idx = ((IInteger) arg_1).intValue(); try { temp_array_of_2[0] = Rascal_TRUE; temp_array_of_2[1] = lst.get((idx >= 0) ? idx : (lst.length() + idx)); } catch(IndexOutOfBoundsException e) { temp_array_of_2[0] = Rascal_FALSE; } return temp_array_of_2; } }, /** * Get element with given key from map * * [ ..., IMap mp, IValue key ] => [ ..., mp[key] ] */ map_subscript { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue result = ((IMap) arg_2).get((IValue) arg_1); if(result == null) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchKey((IValue) arg_1, currentFrame)); } return result; } }, /** * Has map an element with given key? * * [ ..., IMap mp, IValue key ] => [ ..., IBool true if key is legal key ] */ is_defined_map_subscript { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { Object v = ((IMap) arg_2).get((IValue) arg_1); temp_array_of_2[0] = (v == null) ? Rascal_FALSE : Rascal_TRUE; temp_array_of_2[1] = v; return temp_array_of_2; } }, /** * Get element with given index from str * * [ ..., IString s, IInteger idx ] => [ ..., IString s[idx] ] */ str_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IString str = ((IString) arg_2); int idx = ((IInteger) arg_1).intValue(); try { return (idx >= 0) ? str.substring(idx, idx+1) : str.substring(str.length() + idx, str.length() + idx + 1); } catch(IndexOutOfBoundsException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds((IInteger) arg_1, currentFrame)); } } }, /** * Has str an element with given index? str * * [ ..., IString s, IInteger idx ] => [ ..., IBool true if idx is legal index in s ] */ is_defined_str_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IString str = ((IString) arg_2); int idx = ((IInteger) arg_1).intValue(); try { temp_array_of_2[0] = Rascal_TRUE; temp_array_of_2[1] = (idx >= 0) ? str.substring(idx, idx+1) : str.substring(str.length() + idx, str.length() + idx + 1); } catch(IndexOutOfBoundsException e) { temp_array_of_2[0] = Rascal_FALSE; } return temp_array_of_2; } }, /** * Get element with given index from tuple * * [ ..., ITuple tup, IInteger idx ] => [ ..., IValue tup[idx] ] */ tuple_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITuple tup = (ITuple) arg_2; int idx = ((IInteger) arg_1).intValue(); try { return tup.get((idx >= 0) ? idx : tup.arity() + idx); } catch(IndexOutOfBoundsException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds((IInteger) arg_1, currentFrame)); } } }, /** * Has tuple an element with given index? * * [ ..., ITuple tup, IInteger idx ] => [ ..., IBool true if idx is legal index in tup ] */ is_defined_tuple_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITuple tup = (ITuple) arg_2; int idx = ((IInteger) arg_1).intValue(); try { temp_array_of_2[0] = Rascal_TRUE; temp_array_of_2[1] = tup.get((idx >= 0) ? idx : tup.arity() + idx); } catch(IndexOutOfBoundsException e) { temp_array_of_2[0] = Rascal_FALSE; } return temp_array_of_2; } }, /** * Subscript of a binary rel with a single subscript (no set and unequal to _) * * [ ..., IRelation r, IValue idx1] => r[idx1] ] */ rel2_subscript1_noset { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet rel = (ISet) arg_2; if(rel.isEmpty()){ return rel; } IValue index = (IValue) arg_1; ISetWriter wset = vf.setWriter(); for (IValue v : rel) { ITuple tup = (ITuple)v; if(tup.get(0).isEqual(index)){ wset.insert(tup.get(1)); } } return wset.done(); } }, /** * Subscript of a binary rel with a single subscript (a set but unequal to _) * * [ ..., IRelation r, IValue idx1] => r[idx1] ] */ rel2_subscript1_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet rel = (ISet) arg_2; if(rel.isEmpty()){ return rel; } IValue index = (IValue) arg_1; ISetWriter wset = vf.setWriter(); for (IValue v : rel) { ITuple tup = (ITuple)v; if((((ISet) index).contains(tup.get(0)))){ wset.insert(tup.get(1)); } } return wset.done(); } }, /** * Subscript of an n-ary (n > 2) rel with a single subscript (not a set and unequal to _) * * [ ..., IRelation r, IValue idx1] => r[idx1] ] */ rel_subscript1_noset { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet rel = (ISet) arg_2; if(rel.isEmpty()){ return rel; } int relArity = rel.getElementType().getArity(); IValue index = (IValue) arg_1; ISetWriter wset = vf.setWriter(); IValue args[] = new IValue[relArity - 1]; for (IValue v : rel) { ITuple tup = (ITuple)v; if(tup.get(0).isEqual(index)){ for (int i = 1; i < relArity; i++) { args[i - 1] = tup.get(i); } wset.insert(vf.tuple(args)); } } return wset.done(); } }, /** * Subscript of an n-ary (n > 2) rel with a single subscript (a set and unequal to _) * * [ ..., IRelation r, IValue idx1] => r[idx1] ] */ rel_subscript1_set { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet rel = (ISet) arg_2; if(rel.isEmpty()){ return rel; } int relArity = rel.getElementType().getArity(); IValue index = (IValue) arg_1; ISetWriter wset = vf.setWriter(); IValue args[] = new IValue[relArity - 1]; for (IValue v : rel) { ITuple tup = (ITuple)v; if((((ISet) index).contains(tup.get(0)))){ for (int i = 1; i < relArity; i++) { args[i - 1] = tup.get(i); } wset.insert(vf.tuple(args)); } } return wset.done(); } }, /** * Subscript of rel, general case * subsDesc is a subscript descriptor: a list with integers: 0: noset, 1: set, 2: wildcard * * [ ..., IRelation r, IList subsDesc, IValue idx1, IValue idx2, ...] => rel[idx1, idx2, ...] ] */ rel_subscript { @Override public int executeN(final Object[] stack, final int sp, final int arity, final Frame currentFrame, final RascalExecutionContext rex) { //assert arity >= 4; ISet rel = ((ISet) stack[sp - arity]); if(rel.isEmpty()){ stack[sp - arity] = rel; return sp - arity + 1; } IList subsDesc = ((IList) stack[sp - arity + 1]); int indexArity = arity - 2; int relArity = rel.getElementType().getArity(); ISetWriter wset = vf.setWriter(); int indexBase = sp - arity + 2 ; if(relArity - indexArity == 1){ // Return a set allValues: for (IValue v : rel) { ITuple tup = (ITuple)v; for(int k = 0; k < indexArity; k++){ switch(((IInteger)subsDesc.get(k)).intValue()){ case 0: if(!tup.get(k).isEqual((IValue)stack[indexBase + k])) continue allValues; continue; case 1: if(!((ISet)stack[indexBase + k]).contains(tup.get(k))) continue allValues; } } wset.insert(tup.get(indexArity)); } } else { // Return a relation IValue args[] = new IValue[relArity - indexArity]; allValues: for (IValue v : rel) { ITuple tup = (ITuple)v; for(int k = 0; k < indexArity; k++){ switch(((IInteger)subsDesc.get(k)).intValue()){ case 0: if(!tup.get(k).isEqual((IValue)stack[indexBase + k])) continue allValues; continue; case 1: if(!((ISet)stack[indexBase + k]).contains(tup.get(k))) continue allValues; } } for (int i = indexArity; i < relArity; i++) { args[i - indexArity] = tup.get(i); } wset.insert(vf.tuple(args)); } } stack[sp - arity] = wset.done(); return sp - arity + 1; } }, is_defined_rel_subscript { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ISet rel = (ISet) arg_2; int arity = rel.getElementType().getArity(); IValue idx = ((IValue) arg_1); if(idx.getType().isString()){ String sidx = ((IString) idx).getValue(); if(sidx.equals("_")){ return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.notImplemented("Wild card _ not implemented", currentFrame.src, currentFrame)); } } try { temp_array_of_2[0] = Rascal_TRUE; temp_array_of_2[1] = idx.getType().isSet() ? (arity == 2 ? RascalPrimitive.rel2_subscript1_set.execute2(arg_2, arg_1, currentFrame, rex) : RascalPrimitive.rel_subscript1_set.execute2(arg_2, arg_1, currentFrame, rex)) : (arity == 2 ? RascalPrimitive.rel2_subscript1_noset.execute2(arg_2, arg_1, currentFrame, rex) : RascalPrimitive.rel_subscript1_noset.execute2(arg_2, arg_1, currentFrame, rex)); } catch(Exception e) { temp_array_of_2[0] = Rascal_FALSE; } return temp_array_of_2; } }, /** * Subscript of a lrel * * [ ..., IListRelation r, IValue idx1, IValue idx2, ...] => r[idx1, idx2, ...] ] */ lrel_subscript { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity >= 2; IList lrel = ((IList) stack[sp - arity]); if(lrel.isEmpty()){ stack[sp - arity] = lrel; return sp - arity + 1; } int indexArity = arity - 1; int lrelArity = lrel.getElementType().getArity(); assert indexArity < lrelArity ; IValue[] indices = new IValue[indexArity]; Type subscriptType[] = new Type[indexArity]; boolean subscriptIsSet[] = new boolean[indexArity]; boolean yieldList = (lrelArity - indexArity) == 1; Type resFieldType[] = new Type[lrelArity - indexArity]; for(int i = 0; i < indexArity; i++ ){ indices[i] = (IValue) stack[sp - arity + i + 1]; if(indices[i].getType().isString()){ String s = ((IString) indices[i]).getValue(); if(s.equals("_")) indices[i] = null; } subscriptType[i] = indices[i] == null ? valueType : indices[i].getType(); } for (int i = 0; i < lrelArity; i++) { Type relFieldType = lrel.getType().getFieldType(i); if (i < indexArity) { if (subscriptType[i].isSet() && relFieldType.comparable(subscriptType[i].getElementType())){ subscriptIsSet[i] = true; } else if (indices[i] == null || relFieldType.comparable(subscriptType[i])){ subscriptIsSet[i] = false; } } else { resFieldType[i - indexArity] = relFieldType; } } IListWriter wlist = vf.listWriter(); for (IValue v : lrel) { ITuple tup = (ITuple)v; boolean allEqual = true; for(int k = 0; k < indexArity; k++){ if(subscriptIsSet[k] && ((indices[k] == null) || ((ISet) indices[k]).contains(tup.get(k)))){ /* ok */ } else if (indices[k] == null || tup.get(k).isEqual(indices[k])){ /* ok */ } else { allEqual = false; } } if (allEqual) { IValue args[] = new IValue[lrelArity - indexArity]; for (int i = indexArity; i < lrelArity; i++) { args[i - indexArity] = tup.get(i); } if(yieldList){ wlist.append(args[0]); } else { wlist.append(vf.tuple(args)); } } } stack[sp - arity] = wlist.done(); return sp - arity + 1; } }, /** * Subscript of a lrel with single int index * * [ ..., IListRelation r, IValue idx1] => r[idx1, idx2, ...] ] */ lrel_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, Frame currentFrame, RascalExecutionContext rex) { return list_subscript_int.execute2(arg_2, arg_1, currentFrame, rex); } }, /** * Get argument with given index from nonterminal * * [ ..., ITree tree, IInteger idx ] => [ ..., tree[idx] ] */ nonterminal_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITree tree = (ITree) arg_2; if(!TreeAdapter.isList(tree) && TreeAdapter.isInjectionOrSingleton(tree)){ tree = (ITree) TreeAdapter.getArgs(tree).get(0); } if(!TreeAdapter.isList(tree)){ throw new CompilerError("subscript not supported on " + TreeAdapter.getProduction(tree), currentFrame); } IList elems = TreeAdapter.getArgs(tree); int phys_length = elems.length(); int sep_count = TreeAdapter.getSeparatorCount(tree); int log_length = (phys_length == 0) ? 0 : ((sep_count == 0 ? phys_length : 1 + phys_length/(1 + sep_count))); int index = ((IInteger) arg_1).intValue(); if(index < 0){ index = log_length + index; } if(index < 0 || index >= log_length){ return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds((IInteger) arg_1, currentFrame)); } IValue result = elems.get(index * (sep_count + 1)); if(result == null){ return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds((IInteger) arg_1, currentFrame)); } return result; } }, /** * Get argument with given index from lexical * * [ ..., ITree tree, IInteger idx ] => [ ..., tree[idx] ] */ lex_subscript_int { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITree tree = (ITree) arg_2; if(!TreeAdapter.isList(tree) && TreeAdapter.isInjectionOrSingleton(tree)){ tree = (ITree) TreeAdapter.getArgs(tree).get(0); } if(!TreeAdapter.isList(tree)){ throw new CompilerError("subscript not supported on " + TreeAdapter.getProduction(tree), currentFrame); } int index = ((IInteger) arg_1).intValue(); int delta = 1; if(TreeAdapter.isSeparatedList(tree)){ delta = TreeAdapter.getSeparatorCount(tree) + 1; } return TreeAdapter.getArgs(tree).get(index * delta); } }, /*************************************************************************************************/ /* Update parts of a structured value */ /*************************************************************************************************/ /** * Update argument of adt constructor by its field name * * [ ..., IConstructor cons, IString fieldName, IValue repl ] => [ ..., new IConmstructor with cons.fieldName == repl ] */ adt_update { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IConstructor cons = (IConstructor) stack[sp - 3]; String field = ((IString) stack[sp - 2]).getValue(); stack[sp - 3] = cons.set(field, (IValue) stack[sp - 1]); return sp - 2; } }, /** * Update list element * * [ ..., IList cons, IInteger idx, IValue repl ] => [ ..., new IList with lst[idx] == repl ] */ list_update { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IList lst = (IList) stack[sp - 3]; int n = ((IInteger) stack[sp - 2]).intValue(); if(n < 0){ n = lst.length() + n; } try { stack[sp - 3] = lst.put(n, (IValue) stack[sp - 1]); return sp - 2; } catch (IndexOutOfBoundsException e){ rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds(vf.integer(n), currentFrame)); return sp - 2; } } }, /** * Update list element * * [ ..., IList cons, IInteger idx, IValue repl ] => [ ..., new IList with lst[idx] == repl ] */ lrel_update { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { return list_update.executeN(stack, sp, arity, currentFrame, rex); } }, /** * Update map element * * [ ..., IMap mp, IValue key, IValue repl ] => [ ..., new IMap with mp[key] == repl ] */ map_update { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IMap map = (IMap) stack[sp - 3]; IValue key = (IValue) stack[sp - 2]; stack[sp - 3] = map.put(key, (IValue) stack[sp - 1]); return sp - 2; } }, /** * Update tuple element * * [ ..., ITuple tup, IInteger idx, IValue repl ] => [ ..., new ITuple with tup[idx] == repl ] */ tuple_update { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; ITuple tup = (ITuple) stack[sp - 3]; int n = ((IInteger) stack[sp - 2]).intValue(); try { stack[sp - 3] = tup.set(n, (IValue) stack[sp - 1]); return sp - 2; } catch (IndexOutOfBoundsException e){ rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.indexOutOfBounds(vf.integer(n), currentFrame)); return sp - 2; } } }, /************************************************************************************************/ /* Annotations */ /************************************************************************************************/ /** * Get value of an annotation * * [ ..., IConstructor val, IString label ] => [ ..., IValue value of annotation label ] */ annotation_get { @SuppressWarnings("deprecation") @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue val = (IValue) arg_2; String label = ((IString) arg_1).getValue(); try { IValue result = val.asAnnotatable().getAnnotation(label); if(result == null) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchAnnotation(label, currentFrame)); } return result; } catch (FactTypeUseException e) { return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchAnnotation(label, currentFrame)); } } }, /** * Get value of an annotation, if it is defined * * [ ..., IConstructor val, IString label ] => [ ..., [ IBool present, IValue value of annotation label] ] */ is_defined_annotation_get { @SuppressWarnings("deprecation") @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue val = (IValue) arg_2; String label = ((IString) arg_1).getValue(); try { IValue v = val.asAnnotatable().getAnnotation(label); temp_array_of_2[0] = (v == null) ? Rascal_FALSE : Rascal_TRUE; temp_array_of_2[1] = v; } catch (FactTypeUseException e) { temp_array_of_2[0] = Rascal_FALSE; } return temp_array_of_2; } }, /** * Set value of an annotation * * [ ..., IConstructor val, IString label, IValue repl ] => [ ..., IConstructor val with annotation label set to repl ] */ annotation_set { @SuppressWarnings("deprecation") @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IValue val = (IValue) stack[sp - 3]; String label = ((IString) stack[sp - 2]).getValue(); IValue repl = (IValue) stack[sp - 1]; stack[sp - 3] = val.asAnnotatable().setAnnotation(label, repl); return sp - 2; } }, /**********************************************************************************************/ /* Type reachability for descendant match */ /**********************************************************************************************/ /** * Given a subject value and a descriptor, should we descent in it as abstract value? * * [ ..., subject value, descriptor] => true/false */ should_descent_in_abstract { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue subject = (IValue) arg_2; DescendantDescriptor descriptor = (DescendantDescriptor) arg_1; return descriptor.shouldDescentInAbstractValue(subject); } }, /** * Given a subject value and a descriptor, should we descent in it as concrete value? * * [ ..., subject value, descriptor] => true/false */ should_descent_in_concrete { @Override public Object execute2(final Object arg_2, final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { ITree subject = (ITree) arg_2; DescendantDescriptor descriptor = (DescendantDescriptor) arg_1; return descriptor.shouldDescentInConcreteValue(subject); } }, /** * Create a descendant descriptor given * - a unique id * - symbolset, set of symbols * - prodset, set of productions * - concreteMatch, indicates a concrete or abstract match * - definitions needed for type reifier * * [ IString id, ISet symbolset, ISET prodset, IBool concreteMatch, IMap definitions] => DescendantDescriptor */ make_descendant_descriptor { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 5; IString id = (IString) stack[sp - 5]; stack[sp - 5] = rex.getDescendantDescriptorCache() .get(id, k -> { ISet symbolset = (ISet) stack[sp - 4]; ISet prodset = (ISet) stack[sp - 3]; IBool concreteMatch = (IBool) stack[sp - 2]; IMap definitions = (IMap) stack[sp - 1]; return new DescendantDescriptor(vf, symbolset, prodset, definitions, concreteMatch, rex); }); return sp - 4; }; }, /************************************************************************************************/ /* Miscellaneous */ /************************************************************************************************/ /** * Report a failing assertion * * [ ..., IValue msg ] => raise assertionFailedException * */ assert_fails { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IString message = (IString) arg_1; return rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.assertionFailed(message, currentFrame.src, currentFrame)); } }, /** * str_escape_for_regexp: escape the regexp meta-characters in a string * * [ ... IValue val] => [ ..., IString escaped_val] */ str_escape_for_regexp { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue v = ((IValue) arg_1); String s; if(v.getType().isString()){ s = ((IString) v).getValue(); } else { s = v.toString(); } StringBuilder b = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if ("^.|?*+()[\\".indexOf(ch) != -1) { b.append('\\'); } b.append(ch); } return vf.string(b.toString()); } }, /** * Convert a value to string * * [ ..., IValue val] => [ ..., IString converted_value] */ value_to_string { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return vf.string($value_to_string(arg_1, currentFrame, rex)); } }, /** * Convert num to real * * [ ..., INumber nval ] => [ ,,,., IReal rval ] */ num_to_real { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { return ((INumber) arg_1).toReal(vf.getPrecision()); } }, /** * parse a string according to type defined in moduleName * * [ ..., IString moduleName, IConstructor type, IStringOrSourceLocation src ] => [ ..., ITree parseTree ] */ parse { @Override public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { assert arity == 3; IString module_name = (IString) stack[sp - 3]; IConstructor type = (IConstructor) stack[sp - 2]; IValue source = (IValue) stack[sp - 1]; if(source.getType().isString()){ IString s = (IString) source; stack[sp - 3] = rex.getParsingTools().parse(module_name, type, s, currentFrame.src, true, currentFrame, rex); } else { ISourceLocation s = (ISourceLocation) source; stack[sp - 3] = rex.getParsingTools().parse(module_name, type, s, true, currentFrame, rex); } return sp - 2; } }, /** * memoize result of executing a function for given parameters * * [ ..., IValue result ] => [ ..., IValue result ] */ memoize { @SuppressWarnings("unchecked") @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { IValue result = (IValue) arg_1; Function fun = currentFrame.function; int nformals = fun.nformals; IValue[] args = new IValue[nformals - 1]; for(int i = 0; i < nformals - 1; i++){ args[i] = (IValue) currentFrame.stack[i]; } MemoizationCache<IValue> cache = fun.memoization == null ? null : fun.memoization.get(); if(cache == null){ cache = new MemoizationCache<>(); fun.memoization = new SoftReference<>(cache); } cache.storeResult(args, (Map<String,IValue>)currentFrame.stack[nformals - 1], result); return result; } }, /************************************************************************************************/ /* Keyword-related (former) MuPrimitives that need access to rex */ /* NOTE: these primitives violate the convention that all RascalPrimitives return an IValue */ /* Reason: they need access to keyword parameter handling */ /************************************************************************************************/ /** * Given a constructor or node get an array consisting of * - node/constructor name * - positional arguments * - keyword parameters collected in a mmap * * [ ..., node ] => [ ..., array ] */ get_name_and_children_and_keyword_mmap { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode v = (INode) arg_1; int cons_arity = v.arity(); Object[] elems = new Object[cons_arity + 2]; elems[0] = vf.string(v.getName()); for (int i = 0; i < cons_arity; i++) { elems[i + 1] = v.get(i); } elems[cons_arity + 1] = $getAllKeywordParameters(v, rex); return elems; } }, /** * Given a constructor or node get an array consisting of * - positional arguments * - keyword parameters collected in a mmap * * [ ..., node ] => [ ..., array ] */ get_children_and_keyword_mmap { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode v = (INode) arg_1; int cons_arity = v.arity(); Object[] elems = new Object[cons_arity + 1]; for (int i = 0; i < cons_arity; i++) { elems[i] = v.get(i); } elems[cons_arity] = $getAllKeywordParameters(v, rex); return elems; } }, /** * Given a constructor or node get an array consisting of * - its positional arguments * - the values of its keyword arguments * * [ ... node ] => [ ..., array ] */ get_children_and_keyword_values { @Override public Object execute1(final Object arg_1, final Frame currentFrame, final RascalExecutionContext rex) { INode v = (INode) arg_1; int cons_arity = v.arity(); Map<String, IValue> m = $getAllKeywordParameters(v, rex); int kw_arity = m.size(); Object[] elems = new Object[cons_arity + kw_arity]; for (int i = 0; i < cons_arity; i++) { elems[i] = v.get(i); } int j = cons_arity; for(IValue val : m.values()){ elems[j++] = val; } return elems; } } ; /********************************************************************************************************/ /* End of enumeration */ /********************************************************************************************************/ /** * Abstract declaration for the execute method in each RascalPrimitive: * @param stack stack in currentFrame * @param sp stack pointer in currentFrame * @param arity arity of this primitive * @param currentFrame the stackFram of the function that calls this primitive * @param rex the current RascalExecutionContext * @return new value for stack pointer (sp) */ public Object execute0(Frame currentFrame, RascalExecutionContext rex) { throw RascalRuntimeException.notImplemented("RascalPrimitive.execute0 " + name(), currentFrame.src, currentFrame); } public Object execute1(Object arg_1, Frame currentFrame, RascalExecutionContext rex) { throw RascalRuntimeException.notImplemented("RascalPrimitive.execute1 " + name(), currentFrame.src, currentFrame); } public Object execute2(Object arg_2, Object arg_1, Frame currentFrame, RascalExecutionContext rex) { throw RascalRuntimeException.notImplemented("RascalPrimitive.execute2 " + name(), currentFrame.src, currentFrame); } public int executeN(Object[] stack, int sp, int arity, Frame currentFrame, RascalExecutionContext rex) { throw RascalRuntimeException.notImplemented("RascalPrimitive.executeN " + name(), currentFrame.src, currentFrame); } /** * Array of all RascalPrimitives */ static final RascalPrimitive[] values = RascalPrimitive.values(); /** * Return a RascalPrimtive based on its index */ public static RascalPrimitive fromInteger(int prim){ return values[prim]; } // Some global variables and constants public static final IValueFactory vf = ValueFactoryFactory.getValueFactory(); private static final TypeFactory tf = TypeFactory.getInstance(); @SuppressWarnings("deprecation") private static final Type lineColumnType = TypeFactory.getInstance().tupleType(new Type[] {TypeFactory.getInstance().integerType(), TypeFactory.getInstance().integerType()}, new String[] {"line", "column"}); public static final Type nodeType = tf.nodeType(); public static final Type valueType = tf.valueType(); private static final IMap emptyMap = vf.mapWriter().done(); private static final IList emptyList = vf.listWriter().done(); private static final ISet emptySet = vf.setWriter().done(); public static final IBool Rascal_TRUE = ValueFactoryFactory.getValueFactory().bool(true); public static final IBool Rascal_FALSE = ValueFactoryFactory.getValueFactory().bool(false); // Constants for test generation private static final int MAXDEPTH = 5; private static final int TRIES = 500; // For profiling of RascalPrimitives private static final Object[] temp_array_of_2 = new Object[2]; private static final long timeSpent[] = new long[values.length]; private static final boolean profileRascalPrimitives = false; /** * Record spent in a RascalPrimitive * @param index of RascalPrimitive * @param duration spents in its execution */ public void recordTime(final int n, final long duration){ timeSpent[n] += duration; } /** * Generic exit function that allows some post execution actions (like printing a profile) * @param rex */ public static void exit(RascalExecutionContext rex){ if(profileRascalPrimitives) printProfile(rex.getStdOut()); } private static void printProfile(PrintWriter stdout){ stdout.println("\nRascalPrimitive execution times (ms)"); long total = 0; TreeMap<Long,String> data = new TreeMap<Long,String>(); for(int i = 0; i < values.length; i++){ if(timeSpent[i] > 0 ){ data.put(timeSpent[i], values[i].name()); total += timeSpent[i]; } } for(long t : data.descendingKeySet()){ stdout.printf("%30s: %3d%% (%d ms)\n", data.get(t), t * 100 / total, t); } } /************************************************************************************ * AUXILIARY FUNCTIONS (prefixed with $) used in RascalPrimitives * ************************************************************************************/ /* * String templates */ void $pushIndent(final String s, final RascalExecutionContext rex){ //stdout.println("$indent: " + indentStack.size() + ", \"" + s + "\""); rex.getIndentStack().push(s); } void $popIndent(final RascalExecutionContext rex){ rex.getIndentStack().pop(); } public String $getCurrentIndent(final RascalExecutionContext rex) { return rex.getIndentStack().isEmpty() ? "" : rex.getIndentStack().peek(); } public String $indent(final String s, final RascalExecutionContext rex) { String ind = rex.getIndentStack().pop(); // TODO: check empty? rex.getIndentStack().push(ind + s); return s; } public String $unindent(final String s, final RascalExecutionContext rex) { String ind = rex.getIndentStack().pop(); // TODO: check empty? int indLen = ind.length(); int sLen = s.length(); int endIndex = Math.max(indLen - sLen, 0); rex.getIndentStack().push(ind.substring(0, endIndex)); return s; } IString $removeMargins(final IString s, final RascalExecutionContext rex) { // NB: ignored margin indents can only start *after* a new line. // So atBeginning is initially false. boolean atBeginning = false; StringBuffer buf = new StringBuffer(); String indent = $getCurrentIndent(rex); StringBuilder sb = new StringBuilder(s.length()); for (int i = 0; i < s.length(); i++) { int ch = s.charAt(i); if (atBeginning && (ch == ' ' || ch == '\t')) { buf.appendCodePoint(ch); continue; } if (atBeginning && ch == '\'') { // we've only seen ' ' and/or '\t' so we're about // to reach real content, don't add to buf. buf = new StringBuffer(); atBeginning = false; continue; } if (ch == '\n') { // atBeginning && sb.append(buf); buf = new StringBuffer(indent); atBeginning = true; sb.appendCodePoint(ch); continue; } if (atBeginning) { // we were in the margin, but found something other // than ' ', '\t' and '\'', so anything in buf // is actual content; add it. sb.append(buf); buf = new StringBuffer(); sb.appendCodePoint(ch); atBeginning = false; continue; } sb.appendCodePoint(ch); } // Add trailing whitespace (fixes #543) sb.append(buf.toString()); String jstr = sb.toString(); // TODO: inline this to avoid another pass over the string. return vf.string(jstr); //return vf.string(org.rascalmpl.interpreter.utils.StringUtils.unescapeSingleQuoteAndBackslash(jstr)); } private static ISourceLocation $loc_field_update(final ISourceLocation sloc, final String field, final IValue repl, final Frame currentFrame, RascalExecutionContext rex) { Type replType = repl.getType(); int iLength = sloc.hasOffsetLength() ? sloc.getLength() : -1; int iOffset = sloc.hasOffsetLength() ? sloc.getOffset() : -1; int iBeginLine = sloc.hasLineColumn() ? sloc.getBeginLine() : -1; int iBeginColumn = sloc.hasLineColumn() ? sloc.getBeginColumn() : -1; int iEndLine = sloc.hasLineColumn() ? sloc.getEndLine() : -1; int iEndColumn = sloc.hasLineColumn() ? sloc.getEndColumn() : -1; URI uri; boolean uriPartChanged = false; String scheme = sloc.getScheme(); String authority = sloc.hasAuthority() ? sloc.getAuthority() : ""; String path = sloc.hasPath() ? sloc.getPath() : null; String query = sloc.hasQuery() ? sloc.getQuery() : null; String fragment = sloc.hasFragment() ? sloc.getFragment() : null; try { String newStringValue = null; if(replType.isString()){ newStringValue = ((IString)repl).getValue(); } switch (field) { case "uri": uri = URIUtil.createFromEncoded(newStringValue); // now destruct it again scheme = uri.getScheme(); authority = uri.getAuthority(); path = uri.getPath(); query = uri.getQuery(); fragment = uri.getFragment(); uriPartChanged = true; break; case "scheme": scheme = newStringValue; uriPartChanged = true; break; case "authority": authority = newStringValue; uriPartChanged = true; break; case "host": if (!URIResolverRegistry.getInstance().supportsHost(sloc)) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField("The scheme " + sloc.getScheme() + " does not support the host field, use authority instead.", currentFrame)); } uri = URIUtil.changeHost(sloc.getURI(), newStringValue); authority = uri.getAuthority(); uriPartChanged = true; break; case "path": path = newStringValue; uriPartChanged = true; break; case "file": int i = path.lastIndexOf("/"); if (i != -1) { path = path.substring(0, i) + "/" + newStringValue; } else { path = path + "/" + newStringValue; } uriPartChanged = true; break; case "parent": i = path.lastIndexOf("/"); String parent = newStringValue; if (i != -1) { path = parent + path.substring(i); } else { path = parent; } uriPartChanged = true; break; case "ls": rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField("Cannot update the children of a location", currentFrame)); case "extension": String ext = newStringValue; if (path.length() > 1) { int index = path.lastIndexOf('.'); if (index == -1 && !ext.isEmpty()) { path = path + (!ext.startsWith(".") ? "." : "") + ext; } else if (!ext.isEmpty()) { path = path.substring(0, index) + (!ext.startsWith(".") ? "." : "") + ext; } else { path = path.substring(0, index); } } uriPartChanged = true; break; case "top": if (replType.isString()) { uri = URIUtil.assumeCorrect(newStringValue); scheme = uri.getScheme(); authority = uri.getAuthority(); path = uri.getPath(); query = uri.getQuery(); fragment = uri.getFragment(); } else if (replType.isSourceLocation()) { ISourceLocation rep = (ISourceLocation) repl; scheme = rep.getScheme(); authority = rep.hasAuthority() ? rep.getAuthority() : null; path = rep.hasPath() ? rep.getPath() : null; query = rep.hasQuery() ? rep.getQuery() : null; fragment = rep.hasFragment() ? rep.getFragment() : null; } uriPartChanged = true; break; case "fragment": fragment = newStringValue; uriPartChanged = true; break; case "query": query = newStringValue; uriPartChanged = true; break; case "user": if (!URIResolverRegistry.getInstance().supportsHost(sloc)) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField("The scheme " + sloc.getScheme() + " does not support the user field, use authority instead.", currentFrame)); } uri = sloc.getURI(); if (uri.getHost() != null) { uri = URIUtil.changeUserInformation(uri, newStringValue); } authority = uri.getAuthority(); uriPartChanged = true; break; case "port": if (!URIResolverRegistry.getInstance().supportsHost(sloc)) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField("The scheme " + sloc.getScheme() + " does not support the port field, use authority instead.", currentFrame)); } if (sloc.getURI().getHost() != null) { int port = Integer.parseInt(((IInteger) repl).getStringRepresentation()); uri = URIUtil.changePort(sloc.getURI(), port); } authority = sloc.getURI().getAuthority(); uriPartChanged = true; break; case "length": iLength = ((IInteger) repl).intValue(); if (iLength < 0) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(repl, currentFrame)); } break; case "offset": iOffset = ((IInteger) repl).intValue(); if (iOffset < 0) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(repl, currentFrame)); } break; case "begin": iBeginLine = ((IInteger) ((ITuple) repl).get(0)).intValue(); iBeginColumn = ((IInteger) ((ITuple) repl).get(1)).intValue(); if (iBeginColumn < 0 || iBeginLine < 0) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(repl, currentFrame)); } break; case "end": iEndLine = ((IInteger) ((ITuple) repl).get(0)).intValue(); iEndColumn = ((IInteger) ((ITuple) repl).get(1)).intValue(); if (iEndColumn < 0 || iEndLine < 0) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(repl, currentFrame)); } break; default: rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.noSuchField("Modification of field " + field + " in location not allowed", currentFrame)); } ISourceLocation newLoc = sloc; if (uriPartChanged) { newLoc = vf.sourceLocation(scheme, authority, path, query, fragment); } if (sloc.hasLineColumn()) { // was a complete loc, and thus will be now return vf.sourceLocation(newLoc, iOffset, iLength, iBeginLine, iEndLine, iBeginColumn, iEndColumn); } if (sloc.hasOffsetLength()) { // was a partial loc if (iBeginLine != -1 || iBeginColumn != -1) { //will be complete now. iEndLine = iBeginLine; iEndColumn = iBeginColumn; return vf.sourceLocation(newLoc, iOffset, iLength, iBeginLine, iEndLine, iBeginColumn, iEndColumn); } else if (iEndLine != -1 || iEndColumn != -1) { // will be complete now. iBeginLine = iEndLine; iBeginColumn = iEndColumn; return vf.sourceLocation(newLoc, iOffset, iLength, iBeginLine, iEndLine, iBeginColumn, iEndColumn); } else { // remains a partial loc return vf.sourceLocation(newLoc, iOffset, iLength); } } // used to have no offset/length or line/column info, if we are here if (iBeginColumn != -1 || iEndColumn != -1 || iBeginLine != -1 || iBeginColumn != -1) { // trying to add line/column info to a uri that has no offset length rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidUseOfLocation("Can not add line/column information without offset/length", currentFrame)); } // trying to set offset that was not there before, adding length automatically if (iOffset != -1 ) { if (iLength == -1) { iLength = 0; } } // trying to set length that was not there before, adding offset automatically if (iLength != -1) { if (iOffset == -1) { iOffset = 0; } } if (iOffset != -1 || iLength != -1) { // used not to no offset/length, but do now return vf.sourceLocation(newLoc, iOffset, iLength); } // no updates to offset/length or line/column, and did not used to have any either: return newLoc; } catch (IllegalArgumentException e) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(currentFrame)); } catch (URISyntaxException e) { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidURI(e.getMessage(), currentFrame)); } return null; } private static IBool $list_less_list(IList left, IList right) { if(left.length() > right.length()){ return Rascal_FALSE; } OUTER:for (int l = 0, r = 0; l < left.length(); l++) { for (r = Math.max(l, r) ; r < right.length(); r++) { if (left.get(l).isEqual(right.get(r))) { r++; continue OUTER; } } return Rascal_FALSE; } return vf.bool(left.length() != right.length()); } static IValue $add(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex){ return (IValue) add.execute2(left, right, currentFrame, rex); } static IValue $subtract(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex){ return (IValue) subtract.execute2(left, right, currentFrame, rex); } static IValue $product(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex){ return (IValue) product.execute2(left, right, currentFrame, rex); } static IValue $divide(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex){ return (IValue) divide.execute2(left, right, currentFrame, rex); } static IValue $intersect(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex){ return (IValue) intersect.execute2(left, right, currentFrame, rex); } private static IBool $equal(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex){ return (IBool) equal.execute2(left, right, currentFrame, rex); } private static IBool $lessequal(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex){ return (IBool) lessequal.execute2(left, right, currentFrame, rex); } private static IBool $list_lessequal_list(IList left, IList right) { if (left.length() == 0) { return Rascal_TRUE; } else if (left.length() > right.length()) { return Rascal_FALSE; } OUTER:for (int l = 0, r = 0; l < left.length(); l++) { for (r = Math.max(l, r) ; r < right.length(); r++) { if (left.get(l).isEqual(right.get(r))) { continue OUTER; } } return Rascal_FALSE; } return vf.bool(left.length() <= right.length()); } private static Integer $getInt(IValue v){ return v instanceof IInteger ? ((IInteger) v).intValue() : null; } public SliceDescriptor $makeSliceDescriptor(Integer first, Integer second, Integer end, int len, Frame currentFrame) { int firstIndex = 0; int secondIndex = 1; int endIndex = len; if(first != null){ firstIndex = first; if(firstIndex < 0) firstIndex += len; } if(end != null){ endIndex = end; if(endIndex < 0){ endIndex += len; } } if(second == null){ secondIndex = firstIndex + ((firstIndex <= endIndex) ? 1 : -1); } else { secondIndex = second; if(secondIndex < 0) secondIndex += len; if(!(first == null && end == null)){ if(first == null && secondIndex > endIndex) firstIndex = len - 1; if(end == null && secondIndex < firstIndex) endIndex = -1; } } if(len == 0 || firstIndex >= len){ firstIndex = secondIndex = endIndex = 0; } else if(endIndex > len){ endIndex = len; } // else if(endIndex == -1){ // endIndex = 0; // } return new SliceDescriptor(firstIndex, secondIndex, endIndex); } // Slices on list public IList $makeSlice(IList lst, SliceDescriptor sd){ IListWriter w = vf.listWriter(); int increment = sd.second - sd.first; if(sd.first == sd.end || increment == 0){ // nothing to be done } else if(sd.first <= sd.end){ for(int i = sd.first; i >= 0 && i < sd.end; i += increment){ w.append(lst.get(i)); } } else { for(int j = sd.first; j >= 0 && j > sd.end && j < lst.length(); j += increment){ w.append(lst.get(j)); } } return w.done(); } public int $list_slice_operator(final Object[] stack, final int sp, final int arity, final SliceOperator op, final Frame currentFrame, final RascalExecutionContext rex) { assert arity == 5; IList lst = (IList) stack[sp - 5]; SliceDescriptor sd = $makeSliceDescriptor($getInt((IValue) stack[sp - 4]), $getInt((IValue) stack[sp - 3]), $getInt((IValue) stack[sp - 2]), lst.length(), currentFrame); IList repl = (IList) stack[sp - 1]; stack[sp - 5] = $updateListSlice(lst, sd, op, repl, currentFrame, rex); return sp - 4; } public IList $updateListSlice(final IList lst, final SliceDescriptor sd, final SliceOperator op, final IList repl, final Frame currentFrame, final RascalExecutionContext rex){ IListWriter w = vf.listWriter(); int increment = sd.second - sd.first; int replIndex = 0; int rlen = repl.length(); boolean wrapped = false; if(sd.first == sd.end || increment == 0){ // nothing to be done } else if(sd.first <= sd.end){ assert increment > 0; int listIndex = 0; while(listIndex < sd.first){ w.append(lst.get(listIndex++)); } while(listIndex >= 0 && listIndex < sd.end){ w.append(op.execute(lst.get(listIndex), repl.get(replIndex++), currentFrame, rex)); if(replIndex == rlen){ replIndex = 0; wrapped = true; } for(int q = 1; q < increment && listIndex + q < sd.end; q++){ w.append(lst.get(listIndex + q)); } listIndex += increment; } listIndex = sd.end; if(!wrapped){ while(replIndex < rlen){ w.append(repl.get(replIndex++)); } } while(listIndex < lst.length()){ w.append(lst.get(listIndex++)); } } else { assert increment < 0; int j = lst.length() - 1; while(j > sd.first){ w.insert(lst.get(j--)); } while(j >= 0 && j > sd.end && j < lst.length()){ w.insert(op.execute(lst.get(j), repl.get(replIndex++), currentFrame, rex)); if(replIndex == rlen){ replIndex = 0; wrapped = true; } for(int q = -1; q > increment && j + q > sd.end; q--){ w.insert(lst.get(j + q)); } j += increment; } j = sd.end; if(!wrapped){ while(replIndex < rlen){ w.insert(repl.get(replIndex++)); } } while(j >= 0){ w.insert(lst.get(j--)); } } return w.done(); } public IString $makeSlice(final IString str, final SliceDescriptor sd){ StringBuilder buffer = new StringBuilder(); int increment = sd.second - sd.first; if(sd.first == sd.end || increment == 0){ // nothing to be done } else if(sd.first <= sd.end){ for(int i = sd.first; i >= 0 && i < sd.end; i += increment){ buffer.appendCodePoint(str.charAt(i)); } } else { for(int j = sd.first; j >= 0 && j > sd.end && j < str.length(); j += increment){ buffer.appendCodePoint(str.charAt(j)); } } return vf.string(buffer.toString()); } public IList $makeSlice(final INode node, final SliceDescriptor sd){ IListWriter w = vf.listWriter(); int increment = sd.second - sd.first; if(sd.first == sd.end || increment == 0){ // nothing to be done } else if(sd.first <= sd.end){ for(int i = sd.first; i >= 0 && i < sd.end; i += increment){ w.append(node.get(i)); } } else { for(int j = sd.first; j >= 0 && j > sd.end && j < node.arity(); j += increment){ w.append(node.get(j)); } } return w.done(); } public IConstructor $makeSlice(final ITree tree, final int separatorCount, final int minLength, final SliceDescriptor sd){ IListWriter w = vf.listWriter(); IList elems = TreeAdapter.getArgs(tree); int increment = sd.second - sd.first; if(sd.first == sd.end){ // nothing to be done } else if(sd.first <= sd.end){ for(int i = sd.first; i >= 0 && i < sd.end; i += increment){ int base_i = i * (separatorCount + 1); w.append(elems.get(base_i)); if(i < sd.end - increment){ for(int k = 1; k <= separatorCount; k++){ w.append(elems.get(base_i + k)); } } } } else { for(int j = sd.first; j >= 0 && j > sd.end && j < elems.length(); j += increment){ int base_j = j * (separatorCount + 1); w.append(elems.get(base_j)); if(j > sd.end && j > 0){ for(int k = 1; k <= separatorCount; k++){ w.append(elems.get(base_j - k)); } } } } IConstructor prod = TreeAdapter.getProduction(tree); IList new_elems = w.done(); if(new_elems.length() < minLength){ return null; } IConstructor result = vf.constructor(RascalValueFactory.Tree_Appl, prod, new_elems); return result; } private static boolean $isTree(final IValue v){ return v.getType().isSubtypeOf(RascalValueFactory.Tree); } static int $getIterDelta(final IConstructor cons){ Type tp = cons.getConstructorType(); if(tp == RascalValueFactory.Symbol_IterPlus || tp == RascalValueFactory.Symbol_IterStar){ return 2; } if(tp == RascalValueFactory.Symbol_IterSepX || tp == RascalValueFactory.Symbol_IterStarSepX){ return 4; } return -1; } public String $unescape(final String s) { StringBuilder b = new StringBuilder(s.length() * 2); int sLength = s.length(); for (int c = 0; c < sLength; c++) { String schr = s.substring(c, c+1); String sub = schr; switch(schr){ case "\\\"": sub = "\""; break; case "\\\'": sub = "\'"; break; case "\\\\": sub = "\\"; break; case "\\<": sub = "<"; break; case "\\>": sub = ">"; break; } b.append(sub); } return b.toString(); } // TODO: merge the following two functions private static String $value_to_string(final Object given, final Frame currentFrame, RascalExecutionContext rex) { String res = null; if(given instanceof IValue){ IValue val = (IValue) given; Type tp = val.getType(); if(tp.isList()){ Type elemType = tp.getElementType(); if(!elemType.equals(tf.voidType()) && elemType.isNode() && elemType.isSubtypeOf(RascalValueFactory.Tree)){ IList lst = (IList) val; StringWriter w = new StringWriter(); for(int i = 0; i < lst.length(); i++){ w.write($value2string(lst.get(i))); } res = w.toString(); } else { res = $value2string(val); } } else { res = $value2string(val); } } else if(given instanceof Integer){ res = ((Integer) given).toString(); } else { rex.getFrameObserver().exception(currentFrame, RascalRuntimeException.invalidArgument(vf.string(given.toString()), currentFrame)); } return res; } public static String $value2string(final IValue val){ if(val.getType().isString()){ return ((IString) val).getValue(); } if($isTree(val)){ StringWriter w = new StringWriter(); try { IConstructor c = (IConstructor) val; TreeAdapter.unparse(c, w); return w.toString(); } catch (FactTypeUseException | IOException e) { throw new RuntimeException(e); } } return val.toString(); } /** * @param t the given type * @return t converted to a symbol */ static IConstructor $type2symbol(final Type t){ return t.asSymbol(vf, new TypeStore(), vf.setWriter(), new HashSet<>()); } private static Map<String,IValue> $getAllKeywordParameters(IValue v, RascalExecutionContext rex){ Type tp = v.getType(); if(tp.isAbstractData()){ IConstructor cons = (IConstructor) v; if(cons.mayHaveKeywordParameters()){ Map<String, IValue> setKwArgs = cons.asWithKeywordParameters().getParameters(); String consName = cons.getName(); Function getDefaults = rex.getCompanionDefaultsFunction(consName, tp); if(getDefaults != RVMCore.noCompanionFunction){ IValue[] posArgs = new IValue[cons.arity()]; for(int i = 0; i < cons.arity(); i++){ posArgs[i] = cons.get(i); } @SuppressWarnings("unchecked") Map<String, Map.Entry<Type, IValue>> defaults = (Map<String, Map.Entry<Type, IValue>>) rex.getRVM().executeRVMFunction(getDefaults, posArgs, setKwArgs); HashMap<String, IValue> allKwArgs = new HashMap<>(defaults.size()); for(String key : defaults.keySet()){ IValue val = setKwArgs.get(key); if(val != null){ allKwArgs.put(key, val); } else { allKwArgs.put(key, defaults.get(key).getValue()); } } //System.err.println(", returns " + allKwArgs); return allKwArgs; } } else { return RVMCore.emptyKeywordMap; } } if(tp.isNode()){ INode nd = (INode) v; if(nd.mayHaveKeywordParameters()){ return nd.asWithKeywordParameters().getParameters(); } else { return RVMCore.emptyKeywordMap; } } throw new CompilerError("getAllKeywordParameters"); } /* * Main program: handy to map a primitive index back to its name (e.g., in profiles!) */ public static void main(String[] args) { int n = 364; System.err.println("RascalPrimitive: " + fromInteger(n) + " (" + n + ")"); } } /* * Internal class to describe slices */ class SliceDescriptor{ final int first; final int second; final int end; SliceDescriptor(int first, int second, int end){ this.first = first; this.second = second; this.end = end; } } enum SliceOperator { replace(0) { @Override public IValue execute(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex) { return right; } }, add(1) { @Override public IValue execute(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex) { return RascalPrimitive.$add(left, right, currentFrame, rex); } }, subtract(2){ @Override public IValue execute(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex) { return RascalPrimitive.$subtract(left, right, currentFrame, rex); } }, product(3){ @Override public IValue execute(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex) { return RascalPrimitive.$product(left, right, currentFrame, rex); } }, divide(4){ @Override public IValue execute(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex) { return RascalPrimitive.$divide(left, right, currentFrame, rex); } }, intersect(5){ @Override public IValue execute(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex) { return RascalPrimitive.$intersect(left, right, currentFrame, rex); } }; final int operator; public static final SliceOperator[] values = SliceOperator.values(); public static SliceOperator fromInteger(int n) { return values[n]; } public abstract IValue execute(final IValue left, final IValue right, final Frame currentFrame, final RascalExecutionContext rex); public static SliceOperator replace() { return values[0]; } public static SliceOperator add() { return values[1]; } public static SliceOperator subtract() { return values[2]; } public static SliceOperator product() { return values[3]; } public static SliceOperator divide() { return values[4]; } public static SliceOperator intersect() { return values[5]; } SliceOperator(int op) { this.operator = op; } }