Last active
February 7, 2016 09:29
-
-
Save nexpr/118fa2c47fae0b93c45c to your computer and use it in GitHub Desktop.
phjs >=7.0.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require "lib.php"; | |
class EvE { | |
static $eve; | |
private $evs = []; | |
function on(...$args){ | |
overload($args, [ | |
[ | |
"type" => ["string", "function", "int"], | |
"action" => function($evname, $evaction, $count){ | |
$this->addEventListenerLimited($evname, $evaction, $count); | |
} | |
],[ | |
"type" => ["string", "function"], | |
"action" => function($evname, $evaction){ | |
$this->addEventListenerPermanent($evname, $evaction); | |
} | |
],[ | |
"type" => null, | |
"action" => null | |
] | |
]); | |
} | |
private function addEventListenerPermanent($evname, $evaction){ | |
$this->evs[$evname][] = [ | |
"action" => $evaction, | |
"count" => -1 | |
]; | |
} | |
private function addEventListenerLimited($evname, $evaction, $count){ | |
if($count <= 0){ | |
throw new Exception("count must be positive integer value."); | |
} | |
$this->evs[$evname][] = [ | |
"action" => $evaction, | |
"count" => $count | |
]; | |
} | |
function off(...$args){ | |
overload($args, [ | |
[ | |
"type" => ["string", "function"], | |
"action" => function($evname, $evaction){ | |
$this->removeEventListener($evname, $evaction); | |
} | |
],[ | |
"type" => ["string"], | |
"action" => function($evname){ | |
$this->removeEventListenerByName($evname); | |
} | |
],[ | |
"type" => ["function"], | |
"action" => function($evaction){ | |
$this->removeEventListenerByAction($evaction); | |
} | |
],[ | |
"type" => null, | |
"action" => null | |
] | |
]); | |
} | |
function clear(){ | |
$this->evs = []; | |
} | |
private function removeEventListenerByName($evname){ | |
unset($this->evs[$evname]); | |
} | |
private function removeEventListenerByAction($evaction){ | |
foreach($this->evs as &$evactions){ | |
foreach($evactions as $idx => $val){ | |
if($val === $evaction) unset($evactions[$idx]); | |
} | |
} | |
} | |
private function removeEventListener($evname, $evaction){ | |
if(isset($this->evs[$evname])){ | |
foreach($this->evs[$evname] as $idx => $val){ | |
if($val === $evaction) unset($this->evs[$evname][$idx]); | |
} | |
} | |
} | |
function emit($evname, ...$args){ | |
if(isset($this->evs[$evname]) && is_array($this->evs[$evname])){ | |
foreach($this->evs[$evname] as $idx => &$ev){ | |
$is_stop = $ev["action"](...$args) === false; | |
if(--$ev["count"] === 0){ | |
unset($this->evs[$evname][$idx]); | |
} | |
if($is_stop){ | |
break; | |
} | |
} | |
} | |
} | |
} | |
EvE::$eve = new EvE(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function overload($args, $condition){ | |
$result = null; | |
$typeMatch = function($args, $types){ | |
if($types == null){ | |
return true; | |
} | |
if(!is_array($types)){ | |
return false; | |
} | |
foreach($types as $idx => $type){ | |
$val = $args[$idx] ?? null; | |
switch($type){ | |
case "int": | |
case "integer": | |
if(!is_int($val)) return false; | |
break; | |
case "float": | |
case "double": | |
if(!is_double($val)) return false; | |
break; | |
case "string": | |
if(!is_string($val)) return false; | |
break; | |
case "array": | |
if(!is_array($val)) return false; | |
break; | |
case "object": | |
if(!is_object($val)) return false; | |
break; | |
case "closure": | |
if(!($val instanceof Closure)) return false; | |
break; | |
case "function": | |
if(!is_callable($val)) return false; | |
break; | |
case null: | |
break; | |
default: | |
if(!($val instanceof $type)) | |
return false; | |
} | |
} | |
return true; | |
}; | |
foreach($condition as $ovfunc){ | |
if($typeMatch($args, $ovfunc["type"])){ | |
if(!$ovfunc["action"]){ | |
throw new Exception("TypeError"); | |
exit; | |
}else{ | |
$result = $ovfunc["action"](...$args); | |
} | |
break; | |
} | |
} | |
return $result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$ls = new LocalStorage("test"); | |
$ls->set("a", "abc"); | |
$ls->set("b", "bcd"); | |
$ls->set("c", "cde"); | |
$ls->set("d", "def"); | |
var_dump($ls->get("a")); | |
$ls->remove("a"); | |
var_dump($ls->get("a")); | |
$als = new ALocalStorage("test"); | |
$als->get("b", function($value){var_dump($value);}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function setTimeout($cb, $msec, ...$args){ | |
async("setTimeout", $msec, function($result) use ($cb, $args) { | |
$cb(...$args); | |
}); | |
} | |
class LocalStorage { | |
const STORAGE_PATH = "phjs.storage"; | |
protected $name = null; | |
function __construct(string $name){ | |
if($name === "") throw new Exception("storage name must be needed."); | |
$this->name = $name; | |
} | |
function get(string $key){ | |
$db = $this->getDB(); | |
return $db[$this->name][$key] ?? null; | |
} | |
function set(string $key, $val){ | |
$db = $this->getDB(); | |
$db[$this->name][$key] = $val; | |
$this->update($db); | |
} | |
function remove(string $key){ | |
$db = $this->getDB(); | |
unset($db[$this->name][$key]); | |
$this->update($db); | |
} | |
private function update($db){ | |
$json = json_encode($db); | |
file_put_contents(self::STORAGE_PATH, $json); | |
} | |
private function getDB(){ | |
$json = file_get_contents(self::STORAGE_PATH); | |
$data = json_decode($json, true) ?? []; | |
return $data; | |
} | |
static function init(){ | |
if(is_readable(self::STORAGE_PATH)){ | |
$data = json_decode(file_get_contents(self::STORAGE_PATH), true); | |
if(is_array($data)){ | |
return; | |
} | |
} | |
// not ok | |
file_put_contents(self::STORAGE_PATH, "{}"); | |
} | |
} | |
LocalStorage::init(); | |
class ALocalStorage extends LocalStorage { | |
function get(string $key, $cb){ | |
$opt = [ | |
"name" => $this->name, | |
"key" => $key | |
]; | |
async("localStorage_get", $opt, function($result) use ($cb) { | |
$cb($result); | |
}); | |
} | |
function set(string $key, $val, $cb){ | |
$opt = [ | |
"name" => $this->name, | |
"key" => $key, | |
"val" => $val | |
]; | |
async("localStorage_set", $opt, function($result) use ($cb) { | |
$cb($result); | |
}); | |
} | |
function remove(string $key, $cb){ | |
$opt = [ | |
"name" => $this->name, | |
"key" => $key, | |
]; | |
async("localStorage_remove", $opt, function($result) use ($cb) { | |
$cb($result); | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
if($argc !== 3){ | |
throw new Exception("arguments count must be 3. This script is executed by other script only."); | |
} | |
function main($fn_name, $tmp){ | |
try{ | |
$data = json_decode(file_get_contents($tmp), true); | |
$result = is_callable($fn_name) ? $fn_name($data) : [ | |
"error" => "unknown async function `${fn_name}'" | |
]; | |
}catch(Exception $e){ | |
$result = [ | |
"error" => $e->getMessage() | |
]; | |
} | |
$result_path = $tmp . ".return"; | |
$fp = fopen($result_path, "w"); | |
flock($fp, LOCK_EX); | |
fwrite($fp, json_encode($result)); | |
flock($fp, LOCK_UN); | |
fclose($fp); | |
} | |
function setTimeout($msec){ | |
usleep($msec * 1000); | |
} | |
function localStorage_get($opt){ | |
$name = $opt["name"]; | |
$key = $opt["key"]; | |
return (new LocalStorage($name))->get($key); | |
} | |
function localStorage_set($opt){ | |
$name = $opt["name"]; | |
$key = $opt["key"]; | |
$value = $opt["value"]; | |
return (new LocalStorage($name))->set($key, $set); | |
} | |
function localStorage_remove($opt){ | |
$name = $opt["name"]; | |
$key = $opt["key"]; | |
return (new LocalStorage($name))->remove($key); | |
} | |
class LocalStorage { | |
const STORAGE_PATH = "phjs.storage"; | |
protected $name = null; | |
function __construct(string $name){ | |
if($name === "") throw new Exception("storage name must be needed."); | |
$this->name = $name; | |
} | |
function get(string $key){ | |
$db = $this->getDB(); | |
return $db[$this->name][$key] ?? null; | |
} | |
function set(string $key, $val){ | |
$db = $this->getDB(); | |
$db[$this->name][$key] = $val; | |
$this->update($db); | |
} | |
function remove(string $key){ | |
$db = $this->getDB(); | |
unset($db[$this->name][$key]); | |
$this->update($db); | |
} | |
private function update($db){ | |
$json = json_encode($db); | |
file_put_contents(self::STORAGE_PATH, $json); | |
} | |
private function getDB(){ | |
$json = file_get_contents(self::STORAGE_PATH); | |
$data = json_decode($json, true); | |
return $data; | |
} | |
static function init(){ | |
if(is_readable(self::STORAGE_PATH)){ | |
$data = json_decode(file_get_contents(self::STORAGE_PATH), true); | |
if(is_array($data)){ | |
return; | |
} | |
} | |
// not ok | |
file_put_contents(self::STORAGE_PATH, "{}"); | |
} | |
} | |
LocalStorage::init(); | |
main($argv[1], $argv[2]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// extends | |
Object::$prototype->dump = function($full = false){ | |
if($full === false || $full() == false){ | |
var_dump($this()); | |
}else{ | |
var_dump($this); | |
} | |
}; | |
Object::$prototype->isArray = function(){ | |
return $this->constructor === "__A__"; | |
}; | |
Object::$prototype->isString = function(){ | |
return $this->constructor === "__S__"; | |
}; | |
Object::$prototype->isBoolean = function(){ | |
return $this->constructor === "__B__"; | |
}; | |
Object::$prototype->isNumber = function(){ | |
return $this->constructor === "__N__"; | |
}; | |
Object::$prototype->isNull = function(){ | |
return $this->constructor === "__Null__"; | |
}; | |
Object::$prototype->isUndefined = function(){ | |
return $this->constructor === "Undefined"; | |
}; | |
Object::$prototype->compareTo = function($arg){ | |
return $this === $arg; | |
}; | |
Object::$prototype->isTrue = function(){ | |
return true; | |
}; | |
__A__::$prototype->join = function($sep){ | |
$sep = $this->raw($sep); | |
return join($sep, $this()); | |
}; | |
__S__::$prototype->isTrue = function(){ | |
return $this() !== ""; | |
}; | |
__S__::$prototype->split = function($sep){ | |
$sep = $this->raw($sep); | |
return explode($sep, $this()); | |
}; | |
__B__::$prototype->isTrue = function(){ | |
return $this(); | |
}; | |
__N__::$prototype->isTrue = function(){ | |
return $this() !== 0; | |
}; | |
__F__::$prototype->call = function($bindThis, ...$args){ | |
return $this()->bindTo($bindThis())(...$args); | |
}; | |
__F__::$prototype->apply = function($bindThis, $args){ | |
$args = array_map("_", $args()); | |
return $this()->bindTo($bindThis())(...$args); | |
}; | |
__Null__::$prototype->isTrue = function(){ | |
return false; | |
}; | |
Undefined::$prototype->isTrue = function(){ | |
return false; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Object | |
class Object{ | |
// search property with prim and following prototype chain, and call it | |
function __call($name, $arguments){ | |
$meth = null; | |
if(is_object($this->prim) && property_exists($this->prim, $name)){ | |
$meth = $this->prim->$name; | |
} | |
if(is_object($this->__proto__)){ | |
$meth = $this->__proto__->$name; | |
} | |
if($meth instanceof Undefined){ | |
throw new Exception("`{$name}' is not defined."); | |
} | |
if(!is_callable($meth)){ | |
throw new Exception("`{$name}' is not function."); | |
} | |
$arguments = array_map("_", $arguments); | |
return _($meth->bindTo($this)(...$arguments)); | |
} | |
// search property with prim and following prototype chain | |
function __get($name){ | |
if(is_object($this->prim) && property_exists($this->prim, $name)){ | |
return $this->prim->$name; | |
} | |
if(is_object($this->__proto__)){ | |
return $this->__proto__->$name; | |
}else{ | |
return new Undefined(); | |
} | |
} | |
// set property of prim when prim is object | |
function __set($name, $value){ | |
if(is_object($this->prim)){ | |
$this->prim->$name = $value; | |
} | |
} | |
// get raw prim value | |
function __invoke(){ | |
$prim = $this->prim; | |
while($prim instanceof Object){ | |
$prim = $prim->prim; | |
} | |
return $prim; | |
} | |
function __construct($data = null){ | |
if(isset(static::$prototype)){ | |
$this->__proto__ = static::$prototype; | |
} | |
if(get_class($this) === get_class()){ | |
$this->prim = new StdClass(); | |
}else{ | |
$this->prim = $data; | |
} | |
} | |
function raw(...$args){ | |
if(count($args) === 0){ | |
return $this(); | |
}else{ | |
$raws = array_map(function($arg){ | |
return $arg instanceof Object ? $arg() : $arg; | |
}, $args); | |
return count($args) === 1 ? array_pop($raws) : $raws; | |
} | |
} | |
public $prim = null; | |
public $__proto__ = null; | |
static $prototype = null; | |
} | |
Object::$prototype = new Object(); | |
Object::$prototype->constructor = "Object"; | |
Object::$prototype->toString = function(){ | |
return json_encode($this()); | |
}; | |
// Array | |
class __A__ extends Object{ | |
function __get($key){ | |
if($key === 'length'){ | |
return count($this()); | |
} | |
return parent::__get($key); | |
} | |
function __invoke($pos = null){ | |
if(func_num_args() == 0){ | |
return parent::__invoke(); | |
}else{ | |
$pos = $this->raw($pos); | |
$arr = $this(); | |
return array_key_exists($pos, $arr) ? _($arr[$pos]) : new Undefined(); | |
} | |
} | |
static $prototype = null; | |
} | |
__A__::$prototype = new Object(); | |
__A__::$prototype->constructor = "__A__"; | |
// String | |
class __S__ extends Object{ | |
function __get($key){ | |
if($key === 'length'){ | |
return strlen($this()); | |
} | |
return parent::__get($key); | |
} | |
function __invoke($pos = null){ | |
if(func_num_args() == 0){ | |
return parent::__invoke(); | |
}else{ | |
$pos = $this->raw($pos); | |
$str = $this(); | |
return _(mb_substr($str, $pos, 1)); | |
} | |
} | |
static $prototype = null; | |
} | |
__S__::$prototype = new Object(); | |
__S__::$prototype->constructor = "__S__"; | |
__S__::$prototype->toString = function(){ | |
return $this(); | |
}; | |
// Boolean | |
class __B__ extends Object{ | |
static $prototype = null; | |
} | |
__B__::$prototype = new Object(); | |
__B__::$prototype->constructor = "__B__"; | |
// Number | |
class __N__ extends Object{ | |
static $prototype = null; | |
} | |
__N__::$prototype = new Object(); | |
__N__::$prototype->constructor = "__N__"; | |
// Function | |
class __F__ extends Object{ | |
static $prototype = null; | |
} | |
__F__::$prototype = new Object(); | |
__F__::$prototype->constructor = "__F__"; | |
__F__::$prototype->toString = function(){ | |
return "function (){}"; | |
}; | |
// null | |
class __Null__ extends Object{ | |
static $prototype = null; | |
} | |
__Null__::$prototype = new Object(); | |
__Null__::$prototype->constructor = "__Null__"; | |
__Null__::$prototype->toString = function(){ | |
return "null"; | |
}; | |
// undefined | |
class Undefined extends Object{ | |
static $prototype = null; | |
} | |
Undefined::$prototype = new Object(); | |
Undefined::$prototype->constructor = "Undefined"; | |
Undefined::$prototype->toString = function(){ | |
return "undefined"; | |
}; | |
class RegExp extends Object{ | |
static $prototype = null; | |
} | |
RegExp::$prototype = new Object(); | |
RegExp::$prototype->constructor = "RegExp"; | |
class Date extends Object{ | |
static $prototype = null; | |
} | |
Date::$prototype = new Object(); | |
Date::$prototype->constructor = "Date"; | |
function _($prim = null){ | |
if(func_num_args() === 0){ | |
return new Undefined($prim); | |
} | |
if($prim instanceof Object){ | |
return $prim; | |
} | |
if($prim instanceof Closure){ | |
return new __F__($prim); | |
} | |
if(is_array($prim)){ | |
return new __A__($prim); | |
} | |
if(is_string($prim)){ | |
return new __S__($prim); | |
} | |
if(is_bool($prim)){ | |
return new __B__($prim); | |
} | |
if(is_numeric($prim)){ | |
return new __N__($prim); | |
} | |
if(is_null($prim)){ | |
return new __Null__($prim); | |
} | |
return new Object($prim); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require_once "phjs.php"; | |
require_once "phjs.ex.php"; | |
require_once "phjs.async.php"; | |
require_once "EvE.php"; | |
require_once "Promise.php"; | |
function bgExec($fn_name, $data = null){ | |
$dir = sys_get_temp_dir(); | |
$io_path = tempnam($dir, "phjs"); | |
file_put_contents($io_path, json_encode($data)); | |
$command = "php7 phjs.bg.php ${fn_name} ${io_path}"; | |
if(PHP_OS === "WINNT"){ | |
pclose(popen("start /B ${command}", "w")); | |
}else if(PHP_OS === "Linux"){ | |
shell_exec($command . " &"); | |
}else{ | |
throw new Exception("Error: [Unknown OS] cannot start backgroud tasks."); | |
} | |
return $io_path; | |
} | |
function asyncSet($io_path, $cb){ | |
global $main_queue; | |
$main_queue[] = function() use ($io_path, $cb) { | |
$result_path = $io_path . ".return"; | |
if(!is_readable($result_path)){ | |
return false; | |
} | |
$fp = fopen($result_path, "r"); | |
if(!flock($fp, LOCK_SH|LOCK_NB, $wouldblock)){ | |
if($wouldblock){ | |
return false; | |
} | |
}else{ | |
flock($fp, LOCK_UN); | |
fclose($fp); | |
} | |
$result = json_decode(file_get_contents($result_path), true); | |
$cb($result); | |
unlink($io_path); | |
unlink($result_path); | |
return true; | |
}; | |
} | |
function async($key, $bg_opt, $cb){ | |
$io_path = bgExec($key, $bg_opt); | |
asyncSet($io_path, $cb); | |
} | |
function postpone($cb){ | |
global $main_queue; | |
$main_queue[] = function(){ | |
$cb(); | |
return true; | |
}; | |
} | |
if(empty($argv[1]) || !is_readable($argv[1])){ | |
$filename = $argv[1] ?? ""; | |
echo "Error! Invalid argument: Cannot open `${filename}'.", PHP_EOL; | |
echo "Usage: `php this-script program.php'", PHP_EOL; | |
exit; | |
} | |
$main_queue = [function() use ($argv) { | |
require $argv[1]; | |
return true; | |
}]; | |
// main | |
while(count($main_queue)){ | |
foreach($main_queue as $idx => $fn){ | |
if($fn()) unset($main_queue[$idx]); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require_once "phjs.php"; | |
require_once "phjs.ex.php"; | |
require_once "EvE.php"; | |
function asyncExec($fn){ | |
global $main_queue; | |
array_push($main_queue, $fn); | |
} | |
function setTimeout($fn, $time, ...$args){ | |
$exec_time = microtime(true) + $time / 1000; | |
$recur = function() use($fn, $args, $exec_time, &$recur){ | |
$exec_time < microtime(true) ? | |
$fn(...$args) : | |
asyncExec($recur); | |
}; | |
asyncExec($recur); | |
} | |
$main_queue = []; | |
if(empty($argv[1]) || !is_readable($argv[1])){ | |
$filename = $argv[1] ?? ""; | |
echo "Error! Invalid argument: Cannot open `${filename}'.", PHP_EOL; | |
echo "Usage: `php this-script program.php'", PHP_EOL; | |
exit; | |
} | |
// set main script to queue | |
array_push($main_queue, function() use ($argv) { | |
require $argv[1]; | |
}); | |
// main loop | |
while(count($main_queue)){ | |
$fn = array_shift($main_queue); | |
$fn(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$x = 1; | |
switch($x){ | |
case 1: | |
$p = new Promise(function($a,$b){setTimeout($a, 1000, 10);}); | |
$p->then(function($e){var_dump($e);}); | |
$p->then(function($e){var_dump($e+1);}); | |
$p->then(function($e){var_dump($e+2);}); | |
// 10 | |
// 11 | |
// 12 | |
break; | |
case 2: | |
$p = new Promise(function($a,$b){setTimeout($a, 1000, 16);}); | |
$p->then(function($e){ | |
return $e / 4; | |
})->then(function($e){ | |
return $e + 2; | |
})->then(function($e){ | |
var_dump($e * $e); | |
}); | |
// 36 | |
break; | |
case 3: | |
$p = new Promise(function($a,$b){setTimeout($b, 1000, 16);}); | |
$p->then(function($e){var_dump($e);})->catch(function($e){var_dump(-$e);}); | |
// -16 | |
break; | |
case 4: | |
(new Promise(function($a,$b){setTimeout($a, 1000, 1);})) | |
->then(function($e){return new Promise(function($a,$b) use($e) {setTimeout($a, 1000, $e+1);});}) | |
->then(function($e){var_dump($e);}); | |
// 2 | |
break; | |
case 5: | |
(new Promise(function($a,$b){$a(null);})) | |
->then(function($e){return Promise::reject();}) | |
->catch(function($e){var_dump(111);}); | |
// 111 | |
break; | |
case 6: | |
(new Promise(function($a,$b){$a(1);})) | |
->then(function($e){throw new Exception("errrrrror");}) | |
->catch(function($e){var_dump($e);}); | |
// Error | |
break; | |
case 7: | |
(new Promise(function($a,$b){throw new Exception("errrror");})) | |
->then(function($e){return 1;}) | |
->catch(function($e){var_dump($e);}); | |
// Error | |
break; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Promise { | |
const STATUS_PENDING = 0; | |
const STATUS_RESOLVED = 1; | |
const STATUS_REJECTED = 2; | |
private $status = self::STATUS_PENDING; | |
private $value = null; | |
private $nexts = []; | |
function __construct($fn){ | |
$pcbmaker = function($status){ | |
return function($value = null) use($status) { | |
if($this->status === self::STATUS_PENDING){ | |
$this->status = $status; | |
$this->value = $value; | |
$this->callNexts(); | |
} | |
}; | |
}; | |
$resolve = $pcbmaker(self::STATUS_RESOLVED); | |
$reject = $pcbmaker(self::STATUS_REJECTED); | |
try{ | |
$fn($resolve, $reject); | |
}catch(Exception $err){ | |
$reject($err); | |
} | |
} | |
private function callNexts(){ | |
while(count($this->nexts)) array_shift($this->nexts)(); | |
} | |
function then($fn){ | |
return $this->setNext($fn, self::STATUS_RESOLVED); | |
} | |
function catch($fn){ | |
return $this->setNext($fn, self::STATUS_REJECTED); | |
} | |
private function setNext($fn, $status){ | |
return new self(function($resolve,$reject) use($fn, $status) { | |
$action = function() use($fn, $status, $resolve, $reject) { | |
if($this->status === $status){ | |
try{ | |
$result = $fn($this->value); | |
}catch(Exception $err){ | |
$reject($err); | |
return; | |
} | |
if($result instanceof self){ | |
$result->then(function($value) use($resolve) {$resolve($value);}); | |
$result->catch(function($err) use($reject) {$reject($err);}); | |
}else{ | |
$resolve($result); | |
} | |
}else{ | |
$this->status === self::STATUS_RESOLVED ? $resolve($this->value) : $reject($this->value); | |
} | |
}; | |
if($this->status === self::STATUS_PENDING){ | |
$this->nexts[] = $action; | |
}else{ | |
$action(); | |
} | |
}); | |
} | |
static function resolve($value = null){ | |
return new self(function ($a, $b) use($value) {$a($value);}); | |
} | |
static function reject($value = null){ | |
return new self(function ($a, $b) use($value) {$b($value);}); | |
} | |
static function all($arr){ | |
return new self(function ($a, $b) use($arr) { | |
$rem = count($arr); | |
$result = []; | |
foreach($arr as $idx => $promise){ | |
if($promise instanceof self){ | |
$promise->then(function($value) use(&$result, &$rem, $a) { | |
$rem--; | |
$result[$idx] = $value; | |
if($rem === 0){ | |
$a($result); | |
} | |
}); | |
$promise->catch(function($err) use($b) { | |
$b($err); | |
}); | |
}else{ | |
$result[$idx] = $promise; | |
} | |
} | |
}); | |
} | |
static function race($arr){ | |
return new self(function ($a, $b) use($arr) { | |
foreach($arr as $promise){ | |
if($promise instanceof self){ | |
$promise->then(function($value) use($a) { | |
$a($value); | |
}); | |
$promise->catch(function($err) use($b) { | |
$b($err); | |
}); | |
}else{ | |
$a($promise); | |
} | |
} | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
EvE.php | |
イベントエミッター | |
独立してる | |
lib.php | |
phjs に依存しない系関数など | |
Promise.php | |
プロミス | |
独立してるけど 非同期部分がないと存在価値が微妙 | |
phjs.php | |
JavaScript 風にメソッドチェーンとプロトタイプチェーンできる仕組み | |
phjs.ex.php | |
phjs.php のメソッド拡張 | |
phjs.old.php | |
phjs.php の古い版(primの持ち方とか) | |
phjs.start.php | |
開始用のファイル | |
メインループ・非同期機能 | |
phjs.start.mp.php | |
マルチプロセス版の開始ファイル | |
メインループ・非同期機能 | |
phjs.async.php | |
マルチプロセス版の非同期関数置き場 | |
phjs.bg.php | |
マルチプロセス版のバックグラウンド側の処理部分 | |
sample.php | |
使い方サンプル | |
ls-sample.php | |
ローカルストレージのサンプル | |
promise-sample.php | |
プロミスのサンプル | |
usage.php | |
使い方(起動方法) | |
phjs.start.mp.php | |
require | |
→ phjs.php | |
→ phjs.ex.php | |
→ phjs.async.php | |
→ EvE.php | |
→ Promise.php | |
shell exec | |
→ phjs.bg.php | |
phjs.start.php | |
require | |
→ phjs.php | |
→ phjs.ex.php | |
→ EvE.php | |
sample.php | |
どっちでも | |
→ phjs.start.mp.php | |
→ phjs.start.php |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// EventEmitter | |
// register listeners | |
EvE::$eve->on("in-settimeout", function($val){ | |
echo "EvE: ", $val, PHP_EOL; | |
}); | |
// setTimeout | |
// these 'echo' display at last. | |
setTimeout(function($a){ | |
echo $a, PHP_EOL; | |
EvE::$eve->emit("in-settimeout", $a); | |
}, 1000, "SETTIMTOUT 1000 msec"); | |
setTimeout(function($a){ | |
echo $a, PHP_EOL; | |
EvE::$eve->emit("in-settimeout", $a); | |
}, 200, "SETTIMEOUT 200 msec"); | |
echo "timeout setting done."; | |
// js like method | |
$a = _([1,2]); | |
var_dump($a->join("U")->dump()); | |
$s = _("acd"); | |
var_dump( $s() ); | |
$a = _(); | |
var_dump( $a->isTrue()() ); | |
$f = _(function($a, $b){return $a() * $b();}); | |
$f->call(null, 12, 12)->dump(); | |
$f->apply(null, [20,30])->dump(); | |
echo "message of EventEmitter and setTimeout are printed below.", PHP_EOL; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# single | |
php phjs.start.php sample.php | |
# multi | |
php phjs.start.mp.php sample.php |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment