@BIF public static EObject halt(EProc proc, EObject value) { int exitCode = 1; String message = null; if (value != null) { ESmall val = value.testSmall(); if (val != null) { exitCode = val.value; } EString str = value.testString(); if (str != null) { message = str.stringValue(); } } /* // TODO: create crash file if (message != null) { log.severe("halting system: " + message); } else { log.info("halting system"); } */ ERT.shutdown(); throw new ErlangHalt(); }
@BIF public static EObject keysearch(EObject k, EObject n, EObject list) { ESmall idx = n.testSmall(); ESeq src = list.testSeq(); if (k == null || idx == null || src == null || idx.value < 1) throw ERT.badarg(k, n, list); int index = idx.value; while (!src.isNil()) { EObject elm = src.head(); ETuple tup; if ((tup = elm.testTuple()) != null) { if (tup.arity() >= index) { if (tup.elm(index).equals(k)) { return new ETuple2(ERT.am_value, tup); } } } src = src.tail(); } return ERT.FALSE; }
@BIF public static EObject register(EObject name, EObject pid) { EAtom aname; EHandle handle = pid.testHandle(); if ((aname = name.testAtom()) == null || handle == null) throw ERT.badarg(name, pid); ERT.register(aname, handle); return ERT.TRUE; }
@BIF public static ESeq reverse(EObject hd, EObject tl) { ESeq res = tl.testSeq(); ESeq front = hd.testSeq(); if (res == null) throw ERT.badarg(hd, tl); return reverse(front, res); }
@BIF static EObject group_leader(EObject group_leader, EObject pid) { EPID p = pid.testPID(); EPID gl = group_leader.testPID(); if (p == null || gl == null) throw ERT.badarg(group_leader, pid); p.set_group_leader(gl); return ERT.TRUE; }
@BIF public static EAtom member(EObject e, EObject l) { ESeq list = l.testSeq(); if (list == null) throw ERT.badarg(e, l); while (!list.isNil()) { if (e.equals(list.head())) return ERT.TRUE; list = list.tail(); } return ERT.FALSE; }
@BIF public static EAtom check_process_code(EObject pid_arg, EObject mod_arg) { EPID pid = pid_arg.testPID(); EAtom mod = mod_arg.testAtom(); if (pid == null || mod == null) { throw ERT.badarg(pid_arg, mod_arg); } log.log(Level.FINE, "check_process_code not implemented (" + pid + ", " + mod + ")"); return ERT.FALSE; }
@BIF public static EObject hibernate(EProc self, EObject a1, EObject a2, EObject a3) { EAtom m = a1.testAtom(); EAtom f = a2.testAtom(); ESeq a = a3.testSeq(); if (m == null || f == null || a == null) { throw ERT.badarg(a1, a2, a3); } int arity = a.length(); EFun target = EModuleManager.resolve(new FunID(m, f, arity)); if (target == null) { throw new ErlangUndefined(m, f, new ESmall(arity)); } self.tail = target; a = a.reverse(); switch (arity) { default: throw new NotImplemented("hibernate w/" + arity + " args"); case 7: self.arg6 = a.head(); a = a.tail(); case 6: self.arg5 = a.head(); a = a.tail(); case 5: self.arg4 = a.head(); a = a.tail(); case 4: self.arg3 = a.head(); a = a.tail(); case 3: self.arg2 = a.head(); a = a.tail(); case 2: self.arg1 = a.head(); a = a.tail(); case 1: self.arg0 = a.head(); // a = a.tail(); case 0: } throw ErjangHibernateException.INSTANCE; }
@BIF public static EObject spawn(EProc proc, EObject mod, EObject fun, EObject args) { EAtom m = mod.testAtom(); EAtom f = fun.testAtom(); ESeq a = args.testSeq(); if (m == null || f == null || a == null) throw ERT.badarg(mod, fun, args); EProc p2 = new EProc(proc.group_leader(), m, f, a); ERT.run(p2); return p2.self_handle(); }
@BIF public static EObject process_info(EObject pid, EObject what) { EPID p = pid.testPID(); if (p == null) throw ERT.badarg(pid, what); // TODO: validate WHAT locally before going remote? return p.process_info(what); }
@BIF public static ESeq map(EProc proc, EObject f, EObject s) throws Pausable { EFun fun = f.testFunction2(1); ESeq seq = s.testSeq(); if (fun == null || seq == null) throw ERT.badarg(f, s); EObject[] arg = new EObject[1]; ESeq rev = ERT.NIL; for (; !seq.isNil(); seq = seq.tail()) { arg[0] = seq.head(); rev = rev.cons(fun.invoke(proc, arg)); } return reverse(rev, ERT.NIL); }
public static EObject demonitor(ETask<?> self, EObject ref, EObject options) throws Pausable { ERef r = ref.testReference(); ESeq o = options.testSeq(); if (r == null || o == null) throw ERT.badarg(ref, options); boolean flush = (!o.isNil() && o.head() == am_flush); EObject found = self.demonitor(r); if (found == null) { return ERT.FALSE; } EHandle h; ETuple tup; EAtom name; EAtom node; if ((h = found.testHandle()) != null) { h.remove_monitor(self.self_handle(), r, flush); } else if ((tup = found.testTuple()) != null && tup.arity() == 2 && (name = tup.elm(1).testAtom()) != null && (node = tup.elm(2).testAtom()) != null) { EAbstractNode n = EAbstractNode.get_or_connect(self, node); if (n != null) { n.dsig_demonitor(self.self_handle(), r, name); } } if (flush && (self instanceof EProc)) { flush_monitor_message.invoke((EProc) self, new EObject[] {ref, ERT.am_ok}); } return ERT.TRUE; }
@BIF public static EAtom exit(EProc proc, EObject p, EObject reason) throws Pausable { // System.err.println(proc.self_handle() + ":: erlang:exit(" + p + ", " + reason + ")"); EHandle pid = p.testHandle(); if (pid == null) throw ERT.badarg(p, reason); if (pid == proc.self_handle()) { throw new ErlangExit(reason, proc.self_handle()); } pid.exit_signal(proc.self_handle(), reason, true); return ERT.TRUE; }
@BIF static EPort open_port(EProc proc, EObject portName, EObject portSetting) { ETuple t; if ((t = portName.testTuple()) == null) throw ERT.badarg(portName, portSetting); ETuple2 name; if ((name = ETuple2.cast(t)) == null) throw ERT.badarg(portName, portSetting); if (name.elem1 == am_spawn) { throw new ErlangError(ERT.AM_NOT_IMPLEMENTED, portName, portSetting); } else if (name.elem1 == am_spawn_driver) { throw new NotImplemented(); } else if (name.elem1 == am_spawn_executable) { ETask<? extends EPort> task = new EExecDriverTask(proc, name, portSetting); return task.self(); } throw ERT.badarg(portName, portSetting); }
@BIF public static EObject keyfind(EObject key, EObject nth_arg, EObject list_arg) { ESmall nth = nth_arg.testSmall(); ESeq list = list_arg.testSeq(); if (key == null || nth == null | list == null) throw ERT.badarg(key, nth_arg, list_arg); while (!list.isNil()) { EObject elm = list.head(); ETuple tup = elm.testTuple(); // test that it is a tuple of the right size if (tup != null && tup.arity() >= nth.value) { EObject val = tup.elm(nth.value); if (val.equals(key)) { return tup; } } list = list.tail(); } return ERT.FALSE; }
@BIF public static EObject unregister(EObject name) { EAtom aname; if ((aname = name.testAtom()) == null || !ERT.unregister(aname)) throw ERT.badarg(name); return ERT.TRUE; }
@BIF public static EAtom is_process_alive(EObject p) { EPID pid = p.testPID(); if (pid == null) throw ERT.badarg(p); return ERT.box(pid.is_alive()); }
@BIF static EAtom module_loaded(EObject mod) { EAtom m; if ((m = mod.testAtom()) == null) throw ERT.badarg(mod); return EModuleManager.module_loaded(m) ? ERT.TRUE : ERT.FALSE; }
@BIF public static EObject process_info(EObject pid) { EPID p = pid.testPID(); if (p == null) throw ERT.badarg(pid); return p.process_info(); }
@BIF public static EObject monitor(EProc self, EObject how, EObject object) throws Pausable { if (how != am_process) throw ERT.badarg(how, object); // case 1: object is a PID EHandle h = EHandle.cast(object); if (h != null) { ERef ref = ERT.getLocalNode().createRef(); if (!self.monitor(h, h, ref)) { self.mbox_send(ETuple.make(ERT.am_DOWN, ref, am_process, object, ERT.am_noproc)); } return ref; } // case 2: object is a name EAtom name; if (h == null && (name = object.testAtom()) != null) { ERef ref = ERT.getLocalNode().createRef(); boolean success = false; object = new ETuple2(name, ErlDist.node()); if ((h = ERT.whereis(name).testHandle()) != null) { success = self.monitor(h, object, ref); } if (!success) { self.mbox_send(ETuple.make(ERT.am_DOWN, ref, am_process, object, ERT.am_noproc)); } return ref; } // case 3: object is {name, node} ETuple tup; EAtom node; if ((tup = object.testTuple()) != null && tup.arity() == 2 && (name = tup.elm(1).testAtom()) != null && (node = tup.elm(2).testAtom()) != null) { if (node == ErlDist.node()) { ERef ref = ERT.getLocalNode().createRef(); boolean success = false; if ((h = ERT.whereis(name).testHandle()) != null) { success = self.monitor(h, object, ref); } if (!success) { self.mbox_send(ETuple.make(ERT.am_DOWN, ref, am_process, object, ERT.am_noproc)); } return ref; } else { EPeer peer = (EPeer) EPeer.get(node); if (peer != null) { ERef ref = ERT.getLocalNode().createRef(); self.monitor(tup, ref); peer.dsig_monitor(self.self_handle(), name, ref); return ref; } return ErlDist.dmonitor_p2_trap.invoke(self, new EObject[] {how, object}); } } throw ERT.badarg(how, object); }
@BIF public static EObject spawn_opt(EProc self, EObject tup) throws Pausable { ETuple t; EAtom m; EAtom f; ESeq a; ESeq o; if ((t = tup.testTuple()) == null || t.arity() != 4 || (m = t.elm(1).testAtom()) == null || (f = t.elm(2).testAtom()) == null || (a = t.elm(3).testSeq()) == null || (o = t.elm(4).testSeq()) == null) throw ERT.badarg(tup); boolean link = false; boolean monitor = false; EAtom priority = null; for (; !o.isNil(); o = o.tail()) { EObject val = o.head(); ETuple2 t2; if (val == am_link) { link = true; } else if (val == am_monitor) { monitor = true; } else if ((t2 = ETuple2.cast(val)) != null) { if (t2.elm(1) == am_priority) { EAtom am = t2.elm(2).testAtom(); if (am != null) priority = am; } // ignore full_sweep_after and min_heap_size } } EProc p2 = new EProc(self.group_leader(), m, f, a); if (link) { self.link_to(p2); } if (priority != null) { // may throw badarg! p2.process_flag(am_priority, priority); } ERef ref = null; if (monitor) { ref = ERT.getLocalNode().createRef(); if (!self.monitor(p2.self_handle(), p2.self_handle(), ref)) { throw new InternalError("cannot monitor new process?"); // self.mbox_send(ETuple.make(ERT.am_DOWN, ref, p2.self_handle(), ERT.am_noproc)); } } ERT.run(p2); if (monitor) { return new ETuple2(p2.self_handle(), ref); } else { return p2.self_handle(); } }