Commit 5a7f95bb authored by Robert Lemmen's avatar Robert Lemmen

New upstream version 2018.06+dfsg

parent 9a3df982
......@@ -21,19 +21,9 @@ Makefile
*~
/nqp
/*.html
nqp.c
nqp_group.c
nqp_group.h
src/gen/*.nqp
src/gen/*.pm
src/gen/*.setting
src/stage1
src/stage2
tools/build/install-jvm-runner.pl
config.status
config.default
3rdparty/dyncall/ConfigVars
3rdparty/dyncall/*/*.a
node_modules
nqp-runtime.jar
*.class
......@@ -49,7 +39,7 @@ nqp-runtime.jar
/nqp-js.bat
/nqp-js-cross.bat
/jvmconfig.properties
*.moarvm
/*.moarvm
MoarVM
MANIFEST
/bin
......
......@@ -476,6 +476,7 @@ t/moar/10-eqatim.t
t/moar/11-decode.t
t/moar/50-jit-register-alloc.t
t/moar/51-jit-div_i.t
t/moar/52-pluggable-spesh.t
t/nativecall/01-basic.t
t/nqp/001-literals.t
t/nqp/002-if.t
......
......@@ -296,6 +296,7 @@
* [debugnoop `jvm`](#debugnoop-jvm)
* [exit](#exit)
* [getenvhash](#getenvhash)
* [getsignals](#getsignals)
* [backendconfig](#backendconfig)
* [getpid](#getpid)
* [getppid `moar`](#getppid)
......@@ -836,6 +837,9 @@ You can also use `nqp::iterator()` to iterate over a hash's key-value pairs.
## atkey
* `atkey(%hash, str $key --> Mu)`
* `atkey_i(%hash, str $key --> int)`
* `atkey_u(%hash, str $key --> uint)`
* Note, there's no bindkey_u yet since at the moment since atkey_u is only used
for getting values from the lexpad
* `atkey_n(%hash, str $key --> num)`
* `atkey_s(%hash, str $key --> str)`
......@@ -2460,47 +2464,6 @@ constants below can be used in nqp as (e.g.) `nqp::const::CCLASS_ANY`.
* TYPE_CHECK_CACHE_THEN_METHOD
* TYPE_CHECK_NEEDS_ACCEPTS
The JVM only supports SIG_INT and SIG_KILL.
On the MoarVM all of those signal constants below are defined.
* SIG_HUP
* SIG_INT
* SIG_QUIT
* SIG_ILL
* SIG_TRAP
* SIG_ABRT
* SIG_EMT
* SIG_FPE
* SIG_KILL
* SIG_BUS
* SIG_SEGV
* SIG_SYS
* SIG_PIPE
* SIG_ALRM
* SIG_TERM
* SIG_URG
* SIG_STOP
* SIG_TSTP
* SIG_CONT
* SIG_CHLD
* SIG_TTIN
* SIG_TTOU
* SIG_IO
* SIG_XCPU
* SIG_XFSZ
* SIG_VTALRM
* SIG_PROF
* SIG_WINCH
* SIG_INFO
* SIG_USR1
* SIG_USR2
* SIG_THR
* SIG_STKFLT
* SIG_PWR
* SIG_BREAK
## debugnoop `jvm`
* `debugnoop(Mu $a)`
......@@ -2518,6 +2481,56 @@ Exit nqp, using the given status as the compiler's exit value.
Returns a hash containing the environment variables.
Changing the hash doesn't affect the environment variables
## getsignals
* `getsignals(--> Mu)`
Returns a list containing signal names interleaved with the associated signum
integer on the host platform (MacOSX, Linux, BSD, etc).
If the current backend does not support the registering of a signal handler for
a given signal, the hash value will be a negative integer. For instance, the JVM
only supports signal handlers for SIGINT and SIGKILL, so all the values will be
negative except 2 (SIGINT) and 9 (SIGKILL). If a signal is not available on the
host system, the hash value will be set to 0.
The complete list of signal entries is as follows:
* SIGHUP
* SIGINT
* SIGQUIT
* SIGILL
* SIGTRAP
* SIGABRT
* SIGEMT
* SIGFPE
* SIGKILL
* SIGBUS
* SIGSEGV
* SIGSYS
* SIGPIPE
* SIGALRM
* SIGTERM
* SIGURG
* SIGSTOP
* SIGTSTP
* SIGCONT
* SIGCHLD
* SIGTTIN
* SIGTTOU
* SIGIO
* SIGXCPU
* SIGXFSZ
* SIGVTALRM
* SIGPROF
* SIGWINCH
* SIGINFO
* SIGUSR1
* SIGUSR2
* SIGTHR
* SIGSTKFLT
* SIGPWR
* SIGBREAK
## backendconfig
* `backendconfig(--> Mu)`
......
......@@ -14,5 +14,4 @@ Any word (other than 'cut') is accepted as an identifier. The entry may be used
...any text
=end ...optional identifier...
If the ```=begin``` has an identifier, the ```=end``` should have the same identifier (not
yet enforced).
If the ```=begin``` has an identifier, the ```=end``` must have the same identifier.
......@@ -56,18 +56,55 @@ class HLL::Actions {
my str $key := ~$_;
unless $block.symbol($key) {
my $lextype := nqp::lexprimspec($pad, $key);
# obj
if $lextype == 0 {
$block.symbol($key, :scope<lexical>, :lazy_value_from($pad));
}
# int
elsif $lextype == 1 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_i($pad, $key)), :type(int));
}
# num
elsif $lextype == 2 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_n($pad, $key)), :type(num));
}
# str
elsif $lextype == 3 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_s($pad, $key)), :type(str));
}
# int8
elsif $lextype == 4 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_i($pad, $key)), :type(int8));
}
# int16
elsif $lextype == 5 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_i($pad, $key)), :type(int16));
}
# int32
elsif $lextype == 6 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_i($pad, $key)), :type(int32));
}
#?if moar
# uint8
elsif $lextype == 7 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_u($pad, $key)), :type(uint8));
}
# uint16
elsif $lextype == 8 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_u($pad, $key)), :type(uint16));
}
# uint32
elsif $lextype == 9 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_u($pad, $key)), :type(uint32));
}
# uint64
elsif $lextype == 10 {
$block.symbol($key, :scope<lexical>, :value(nqp::atkey_u($pad, $key)), :type(uint64));
}
#?endif
else {
die("Unhandled lexical type")
}
}
}
}
......@@ -132,7 +169,7 @@ class HLL::Actions {
$ast := QAST::SVal.new( :value(~@words[0]) );
}
}
else {
else {
$/.panic("Can't form :w list from non-constant strings (yet)");
}
}
......
......@@ -412,7 +412,9 @@ class HLL::Compiler does HLL::Backend::Default {
nqp::exit(1) if $err;
try {
nqp::push(@codes, $in-handle.slurp());
$in-handle.close;
unless $filename eq '-' {
$in-handle.close;
}
CATCH {
note("Error while reading from file: $_");
$err := 1;
......
......@@ -1626,12 +1626,9 @@ class NQP::Actions is HLL::Actions {
method postfix:sym<.>($/) { make $<dotty>.ast; }
method term:sym<return>($/) {
# This can go away in favor of nqp::const::CONTROL_RETURN after rebootstrap
# of Moar and JVM backends.
my $CONTROL_RETURN := 32;
make QAST::Op.new(
:op('throwpayloadlex'),
QAST::IVal.new( :value($CONTROL_RETURN) ),
QAST::IVal.new( :value(nqp::const::CONTROL_RETURN) ),
$<EXPR> ?? $<EXPR>.ast !! QAST::WVal.new( :value($*W.find_sym(['NQPMu'])))
);
}
......@@ -1677,6 +1674,10 @@ class NQP::Actions is HLL::Actions {
make QAST::Op.new( :op<callmethod>, :name<ACCEPTS>, :node($/) );
}
method infix:sym<!~~>($/) {
make QAST::Op.new( :op<callmethod>, :name<NOT-ACCEPTS>, :node($/) );
}
# Takes a multi-part name that we know is in a package and generates
# QAST to look it up using NQP package semantics.
sub lexical_package_lookup(@name, $/) {
......
......@@ -238,46 +238,46 @@ grammar NQP::Grammar is HLL::Grammar {
proto rule statement_control { <...> }
rule statement_control:sym<use> {
<sym>\s <name>
<sym> <name>
}
rule statement_control:sym<if> {
<sym>\s
<sym>
<xblock>
[ 'elsif'\s <xblock> ]*
[ 'else'\s <else=.pblock> ]?
[ 'elsif' <xblock> ]*
[ 'else' <else=.pblock> ]?
}
rule statement_control:sym<unless> {
<sym>\s
<sym>
<xblock>
[ <!before 'else'> || <.panic: 'unless does not take "else", please rewrite using "if"'> ]
}
rule statement_control:sym<while> {
:my $*CONTROL_USED := 0;
$<sym>=[while|until]\s
$<sym>=[while|until]
<xblock>
}
rule statement_control:sym<repeat> {
:my $*CONTROL_USED := 0;
<sym>\s
<sym>
[
| $<wu>=[while|until]\s <xblock>
| <pblock> $<wu>=[while|until]\s <EXPR>
| $<wu>=[while|until] <xblock>
| <pblock> $<wu>=[while|until] <EXPR>
]
}
rule statement_control:sym<for> {
:my $*CONTROL_USED := 0;
<sym>\s
<sym>
<xblock>
}
rule statement_control:sym<CATCH> { <sym>\s <block> }
rule statement_control:sym<CATCH> { <sym> <block> }
rule statement_control:sym<CONTROL> { <sym>\s <block> }
rule statement_control:sym<CONTROL> { <sym> <block> }
proto token statement_prefix { <...> }
token statement_prefix:sym<BEGIN> { <sym> <blorst> }
......@@ -821,6 +821,7 @@ grammar NQP::Grammar is HLL::Grammar {
token infix:sym«gt» { <sym> <O(|%relational, :op<isgt_s>)> }
token infix:sym«=:=» { <sym> <O(|%relational, :op<eqaddr>)> }
token infix:sym<~~> { <sym> <O(|%relational, :reducecheck<smartmatch>)> }
token infix:sym<!~~> { <sym> <O(|%relational, :reducecheck<smartmatch>)> }
token infix:sym<&&> { <sym> <O(|%tight_and, :op<if>)> }
......@@ -843,8 +844,8 @@ grammar NQP::Grammar is HLL::Grammar {
token infix:sym<,> { <sym> <O(|%comma, :op<list>)> }
token prefix:sym<make> { <sym> \s <O(|%list_prefix)> }
token term:sym<return> { <sym> [\s <EXPR>]? { $*RETURN_USED := 1 } }
token prefix:sym<make> { <sym> \s+ <O(|%list_prefix)> }
token term:sym<return> { <sym> [\s+ <EXPR>]? { $*RETURN_USED := 1 } }
method smartmatch($/) {
# swap rhs into invocant position
......
......@@ -25,7 +25,11 @@ role QAST::Children {
else {
nqp::push(@onto, nqp::x(' ', $indent));
nqp::push(@onto, '- ');
nqp::push(@onto, nqp::istype($_, NQPMu) ?? '(NQPMu)' !! ~$_);
nqp::istype($_, NQPMu)
?? nqp::push(@onto, '(NQPMu)')
!! $_.HOW.name($_) eq 'Sub' || $_.HOW.name($_) eq 'Regex'
?? nqp::push(@onto, $_.name)
!! nqp::push(@onto, ~$_ );
nqp::push(@onto, "\n");
}
}
......
......@@ -1368,6 +1368,9 @@ class NQPRegexMethod {
multi method ACCEPTS(NQPRegexMethod:D $self: $target) {
NQPMatch.parse($target, :rule(self))
}
multi method NOT-ACCEPTS(NQPRegexMethod:D $self: $target) {
nqp::isfalse(NQPMatch.parse($target, :rule(self)))
}
method name() {
nqp::getcodename($!code)
}
......@@ -1381,5 +1384,8 @@ class NQPRegex is NQPRegexMethod {
multi method ACCEPTS(NQPRegex:D $self: $target) {
NQPMatch.parse($target, :rule(self), :c(0))
}
multi method NOT-ACCEPTS(NQPRegex:D $self: $target) {
nqp::isfalse(NQPMatch.parse($target, :rule(self), :c(0)))
}
}
nqp::setinvokespec(NQPRegex, NQPRegexMethod, '$!code', nqp::null);
......@@ -22,50 +22,37 @@ class QRegex::Optimizer {
method all_subtypes($node, $type) {
my int $res := 0;
for $node {
if $node.rxtype eq $type {
$res++
} else {
return -1;
}
return -1 if $node.rxtype ne $type;
$res++;
}
return $res;
}
method first_non_concat_child($node) {
while nqp::elems(@($node)) >= 1 {
if nqp::istype($node, QAST::Regex) {
if $node.rxtype eq 'concat' {
if $node[0].rxtype eq 'qastnode' && $node[0].subtype eq 'declarative' {
# the debugger puts these all over our code; we should pretend we never saw them.
$node := $node[1];
} else {
$node := $node[0];
}
} else {
last;
}
} else {
last;
}
last unless nqp::istype($node, QAST::Regex);
last unless $node.rxtype eq 'concat';
$node := ($node[0].rxtype eq 'qastnode' && $node[0].subtype eq 'declarative')
?? $node[1] !! $node[0];
}
$node;
}
method dont_scan($node) {
while nqp::elems(@($node)) >= 1 {
if nqp::istype($node, QAST::Regex) {
if nqp::istype($node[0], QAST::Regex) && $node[0].rxtype eq 'scan' {
$node.shift;
last;
}
if $node.rxtype eq 'concat' {
$node := $node[0];
} else {
last;
}
last unless nqp::istype($node, QAST::Regex);
if nqp::istype($node[0], QAST::Regex) && $node[0].rxtype eq 'scan' {
$node.shift;
last;
}
if $node.rxtype eq 'concat' {
$node := $node[0];
} else {
last;
}
}
}
......@@ -152,45 +139,47 @@ class QRegex::Optimizer {
}
method visit_children($node) {
if nqp::isstr($node) {
return;
}
my int $i := 0;
unless nqp::isstr($node) {
my int $n := nqp::elems(@($node));
while $i < $n {
my $visit := $node[$i];
if nqp::istype($visit, QAST::Regex) {
my $type := $visit.rxtype;
if $type eq 'concat' {
$node[$i] := self.visit_concat($visit);
} elsif $type eq 'literal' {
} elsif $type eq 'quant' {
self.visit_children($visit);
} elsif $type eq 'subrule' {
$node[$i] := $!main_opt($node[$i]) if $!main_opt;
$node[$i] := self.simplify_assertion($visit);
} elsif $type eq 'qastnode' {
$node[$i] := $!main_opt($node[$i]) if $!main_opt;
} elsif $type eq 'anchor' {
} elsif $type eq 'enumcharlist' {
} elsif $type eq 'cclass' {
} elsif $type eq 'scan' {
} elsif $type eq 'charrange' {
} elsif $type eq 'dynquant' {
$node[$i] := $!main_opt($node[$i]) if $!main_opt;
} elsif $type eq 'pass' || $type eq 'fail' {
} else {
# alt, altseq, conjseq, conj, quant
self.visit_children($visit);
}
} elsif nqp::istype($visit, QAST::Block) {
@!outer.push($visit);
my int $n := nqp::elems(@($node));
while $i < $n {
my $visit := $node[$i];
if nqp::istype($visit, QAST::Regex) {
my $type := $visit.rxtype;
if $type eq 'concat' {
$node[$i] := self.visit_concat($visit);
} elsif $type eq 'literal' {
} elsif $type eq 'quant' {
self.visit_children($visit);
@!outer.pop();
}
else {
} elsif $type eq 'subrule' {
$node[$i] := $!main_opt($node[$i]) if $!main_opt;
$node[$i] := self.simplify_assertion($visit);
} elsif $type eq 'qastnode' {
$node[$i] := $!main_opt($node[$i]) if $!main_opt;
} elsif $type eq 'anchor' {
} elsif $type eq 'enumcharlist' {
} elsif $type eq 'cclass' {
} elsif $type eq 'scan' {
} elsif $type eq 'charrange' {
} elsif $type eq 'dynquant' {
$node[$i] := $!main_opt($node[$i]) if $!main_opt;
} elsif $type eq 'pass' || $type eq 'fail' {
} else {
# alt, altseq, conjseq, conj, quant
self.visit_children($visit);
}
$i := $i + 1;
} elsif nqp::istype($visit, QAST::Block) {
@!outer.push($visit);
self.visit_children($visit);
@!outer.pop();
}
else {
self.visit_children($visit);
}
$i := $i + 1;
}
}
}
......@@ -88,6 +88,11 @@ my class NQPMu {
nqp::istype($topic, self.WHAT)
}
proto method NOT-ACCEPTS($topic) { * }
multi method NOT-ACCEPTS(NQPMu:U $self: $topic) {
nqp::isfalse(nqp::istype($topic, self.WHAT))
}
method isa($type) {
self.HOW.isa(self, $type)
}
......@@ -114,7 +119,11 @@ nqp::sethllconfig('nqp', nqp::hash(
'list', NQPArray,
'slurpy_array', NQPArray,
'array_iter', NQPArrayIter,
'hash_iter', NQPHashIter
'hash_iter', NQPHashIter,
'foreign_transform_hash', -> $hash {
# BOOTHashes don't actually need transformation
nqp::ishash($hash) ?? $hash !! $hash.FLATTENABLE_HASH
},
));
my class NQPLabel { }
......@@ -19,10 +19,6 @@ knowhow NQPClassHOW {
has @!roles;
has $!default_parent;
# Vtable and mapping of method names to slots.
has @!vtable;
has %!method-vtable-slots;
# Have we been composed?
has $!composed;
......@@ -71,8 +67,6 @@ knowhow NQPClassHOW {
@!multi_methods_to_incorporate := nqp::list();
@!parents := nqp::list();
@!roles := nqp::list();
@!vtable := nqp::list();
%!method-vtable-slots := nqp::hash();
@!mro := nqp::list();
@!done := nqp::list();
@!BUILDALLPLAN := nqp::list();
......
......@@ -2078,10 +2078,6 @@ my %const_map := nqp::hash(
'PIPE_CAPTURE_ERR', 256,
'PIPE_MERGED_OUT_ERR', 512,
# could probably support a few more...
'SIG_INT', 2,
'SIG_KILL', 9,
'TYPE_CHECK_CACHE_DEFINITIVE', 0,
'TYPE_CHECK_CACHE_THEN_METHOD', 1,
'TYPE_CHECK_NEEDS_ACCEPTS', 2,
......@@ -2662,6 +2658,12 @@ QAST::OperationsJAST.map_classlib_core_op('setdebugtypename', $TYPE_OPS, 'setdeb
# defined - overridden by HLL, but by default same as .DEFINITE.
QAST::OperationsJAST.map_classlib_core_op('defined', $TYPE_OPS, 'isconcrete', [$RT_OBJ], $RT_INT, :tc);
# object ops that don't do the usual decontainerization
QAST::OperationsJAST.map_classlib_core_op('what_nd', $TYPE_OPS, 'what_nd', [$RT_OBJ], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('how_nd', $TYPE_OPS, 'how_nd', [$RT_OBJ], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('clone_nd', $TYPE_OPS, 'clone_nd', [$RT_OBJ], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('isconcrete_nd', $TYPE_OPS, 'isconcrete_nd', [$RT_OBJ], $RT_INT, :tc);
# container related
QAST::OperationsJAST.map_classlib_core_op('setcontspec', $TYPE_OPS, 'setcontspec', [$RT_OBJ, $RT_STR, $RT_OBJ], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('iscont', $TYPE_OPS, 'iscont', [$RT_OBJ], $RT_INT);
......@@ -2813,6 +2815,7 @@ QAST::OperationsJAST.map_classlib_core_op('nfarunalt', $TYPE_OPS, 'nfarunalt', [
# process related opcodes
QAST::OperationsJAST.map_classlib_core_op('exit', $TYPE_OPS, 'exit', [$RT_INT], $RT_INT, :tc);
QAST::OperationsJAST.map_classlib_core_op('getsignals', $TYPE_IO_OPS, 'getsignals', [], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('sleep', $TYPE_OPS, 'sleep', [$RT_NUM], $RT_NUM);
QAST::OperationsJAST.map_classlib_core_op('getenvhash', $TYPE_OPS, 'getenvhash', [], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('getpid', $TYPE_OPS, 'getpid', [], $RT_INT, :tc);
......@@ -2857,6 +2860,8 @@ QAST::OperationsJAST.map_classlib_core_op('killprocasync', $TYPE_IO_OPS, 'killpr
QAST::OperationsJAST.map_classlib_core_op('cas', $TYPE_OPS, 'cas', [$RT_OBJ, $RT_OBJ, $RT_OBJ], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('atomicload', $TYPE_OPS, 'atomicload', [$RT_OBJ], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('atomicstore', $TYPE_OPS, 'atomicstore', [$RT_OBJ, $RT_OBJ], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('casattr', $TYPE_OPS, 'casattr', [$RT_OBJ, $RT_OBJ, $RT_STR, $RT_OBJ, $RT_OBJ], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('atomicbindattr', $TYPE_OPS, 'atomicbindattr', [$RT_OBJ, $RT_OBJ, $RT_STR, $RT_OBJ], $RT_OBJ, :tc);
# JVM-specific ops for compilation unit handling
QAST::OperationsJAST.map_classlib_core_op('compilejast', $TYPE_OPS, 'compilejast', [$RT_OBJ, $RT_OBJ], $RT_OBJ, :tc);
......
......@@ -31,6 +31,7 @@ public class AsyncProcessHandle implements IIOClosable {
private SixModelObject bufType;
private int outSeq = 0;
private int errSeq = 0;
private boolean procStarted = false;
public AsyncProcessHandle(ThreadContext tc, SixModelObject queue, SixModelObject argsObj,
String cwd, SixModelObject envObj, SixModelObject configObj) {
......@@ -52,6 +53,7 @@ public class AsyncProcessHandle implements IIOClosable {
public void run() {
try {
AsyncProcessHandle.this.proc = pb.start();
procStarted = true;
int pid = (int)getPID(AsyncProcessHandle.this.proc);
......@@ -77,7 +79,7 @@ public class AsyncProcessHandle implements IIOClosable {
send(done, boxInt(outcome << 8));
}
catch (Throwable t) {
SixModelObject message = boxError(t.getMessage());
SixModelObject message = boxError(t.toString());
SixModelObject error = config.get("error");
if (error != null)
......@@ -197,7 +199,7 @@ public class AsyncProcessHandle implements IIOClosable {
}
catch (Throwable t) {
send(callback, boxInt(-1), AsyncProcessHandle.this.hllConfig.strBoxType,
boxError(t.getMessage()));
boxError(t.toString()));
}
}
}).start();
......@@ -219,13 +221,18 @@ public class AsyncProcessHandle implements IIOClosable {
return Ops.box_i(value, this.hllConfig.intBoxType, this.tc);
}
public void writeBytes(ThreadContext tc, AsyncTaskInstance task, SixModelObject toWrite) {
public synchronized void writeBytes(ThreadContext tc, AsyncTaskInstance task, SixModelObject toWrite) {
ByteBuffer buffer = Buffers.unstashBytes(toWrite, tc);
OutputStream stream = this.proc.getOutputStream();
SixModelObject Array = this.hllConfig.listType;
SixModelObject result = Array.st.REPR.allocate(tc, Array.st);
result.push_boxed(tc, task.schedulee);
try {
/* wait up to one second for proc */
for (int counter = 0; !procStarted && counter < 100; counter++)
wait(10);
/* TODO: is it better to check if proc is null and
* throw an Exception with a fitting message? */
OutputStream stream = this.proc.getOutputStream();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
stream.write(bytes);
......@@ -234,7 +241,7 @@ public class AsyncProcessHandle implements IIOClosable {
}
catch (Throwable t) {
result.push_boxed(tc, this.hllConfig.strBoxType);
result.push_boxed(tc, boxError(t.getMessage()));
result.push_boxed(tc, boxError(t.toString()));
}
((ConcBlockingQueueInstance)task.queue).push_boxed(tc, result);
}
......
......@@ -50,11 +50,36 @@ public class AsyncServerSocketHandle implements IIOBindable, IIOCancelable {
final SixModelObject IOType = hllConfig.ioType;
final SixModelObject Array = hllConfig.listType;
final SixModelObject Null = hllConfig.nullValue;
final SixModelObject Int = hllConfig.intBoxType;
final SixModelObject Str = hllConfig.strBoxType;
@Override
public void completed(AsynchronousSocketChannel channel, AsyncTaskInstance task) {
listenChan.accept(task, this);
InetSocketAddress localAddress;
InetSocketAddress remoteAddress;
try {
localAddress = (InetSocketAddress) channel.getLocalAddress();
} catch (IOException e) {
throw ExceptionHandling.dieInternal(tc, e);
}
String socketHost = localAddress.getAddress().getHostAddress();
if (socketHost.equals("0:0:0:0:0:0:0:1"))
socketHost = "::1";
int socketPort = localAddress.getPort();
try {
remoteAddress = (InetSocketAddress) channel.getRemoteAddress();
} catch (IOException e) {
throw ExceptionHandling.dieInternal(tc, e);
}
String peerHost = remoteAddress.getAddress().getHostAddress();
if (peerHost.equals("0:0:0:0:0:0:0:1"))
peerHost = "::1";
int peerPort = localAddress.getPort();
ThreadContext curTC = tc.gc.getCurrentThreadContext();
AsyncSocketHandle handle = new AsyncSocketHandle(curTC, channel);
......@@ -66,6 +91,10 @@ public class AsyncServerSocketHandle implements IIOBindable, IIOCancelable {
result.push_boxed(curTC, task.schedulee);
result.push_boxed(curTC, ioHandle);
result.push_boxed(curTC, Null);
result.push_boxed(curTC, Ops.box_s(socketHost, Str, curTC));
result.push_boxed(curTC, Ops.box_i(socketPort, Int, curTC));
result.push_boxed(curTC, Ops.box_s(peerHost, Str, curTC));
result.push_boxed(curTC, Ops.box_i(peerPort, Int, curTC));
((ConcBlockingQueueInstance) task.queue).push_boxed(curTC, result);
}
......@@ -76,7 +105,7 @@ public class AsyncServerSocketHandle implements IIOBindable, IIOCancelable {
SixModelObject result = Array.st.REPR.allocate(curTC, Array.st);
result.push_boxed(curTC, task.schedulee);
result.push_boxed(curTC, IOType);
result.push_boxed(curTC, Ops.box_s(exc.getMessage(), Str, curTC));
result.push_boxed(curTC, Ops.box_s(exc.toString(), Str, curTC));
}
};
......
......@@ -7,6 +7,7 @@ import java.nio.CharBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.channels.ClosedChannelException;
import org.perl6.nqp.runtime.Buffers;
import org.perl6.nqp.runtime.ExceptionHandling;
......@@ -18,7 +19,7 @@ import org.perl6.nqp.sixmodel.reprs.AsyncTaskInstance;
import org.perl6.nqp.sixmodel.reprs.ConcBlock