Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Perlito5 - js - AUTOLOAD finished; add tests; workaround for broken b…
…ootstrap in 589722e
  • Loading branch information
fglock committed Nov 22, 2012
1 parent 589722e commit b371c5d
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 19 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Expand Up @@ -16,6 +16,7 @@ dev 2012-04-12

- javascript backend:

-- AUTOLOAD
-- tie() - TIEARRAY, STORE, FETCH
-- string increment
-- negative index in array
Expand Down
6 changes: 3 additions & 3 deletions README-perlito5-js
Expand Up @@ -27,6 +27,8 @@

- Tie array.

- AUTOLOAD.



* Perlito5-in-Javascript differences from "perl"
Expand All @@ -46,8 +48,6 @@

- Overload is not implemented yet.

- AUTOLOAD is not implemented yet for function calls; but AUTOLOAD should work for method calls

- XS is not supported.

- Variable aliasing is not implemented yet;
Expand Down Expand Up @@ -197,7 +197,7 @@ do block
- ...

AUTOLOAD
- TODO
- ...

my
- ...
Expand Down
8 changes: 5 additions & 3 deletions TODO-perlito5
Expand Up @@ -278,9 +278,11 @@ TODO list for Perlito5
-- BEGIN/END that are defined inside blocks/closures need to run inside some pseudo-environment
even if the closure was never created or used in the first place

-- AUTOLOAD
AUTOLOAD is implemented for method lookups, but not for normal subroutines
see: p5call_sub()
-- bug - method call context is disabled, because it breaks bootstrap.
in Runtime.pm:
function p5call(invocant, method, list, p5want) {
list.unshift(invocant);
p5want = 0; // TODO BUG - workaround for broken bootstrap


* Nice to Have
Expand Down
22 changes: 18 additions & 4 deletions html/perlito5.js
Expand Up @@ -133,6 +133,8 @@ function p5method_lookup(method, class_name, seen) {
function p5call(invocant, method, list, p5want) {
list.unshift(invocant);

p5want = 0; // TODO BUG - workaround for broken bootstrap

if (typeof invocant === "string") {
invocant = p5make_package(invocant);
}
Expand Down Expand Up @@ -175,10 +177,11 @@ function p5call(invocant, method, list, p5want) {

function p5call_sub(namespace, name, list, p5want) {
if(p5pkg[namespace].hasOwnProperty(name)) {
// TODO
return p5pkg[namespace][name](list, p5want)
}
if(p5pkg[namespace].hasOwnProperty("AUTOLOAD")) {
// TODO
p5pkg[namespace]["v_AUTOLOAD"] = namespace + "::" + name;
return p5pkg[namespace]["AUTOLOAD"](list, p5want)
}
p5pkg.CORE.die(["Undefined subroutine &" + namespace + "::" + name]);
}
Expand Down Expand Up @@ -4253,6 +4256,7 @@ var p5100 = p5pkg['main'];
(v_code = ((p5str(p5pkg["Perlito5::Javascript2"].pkg([], 0)) + '.' + p5str(v_code))));
};
var v_sig;
var v_may_need_autoload;
p5for_lex(function () {
var v_name;
(v_name = ((v_self || (v_self = new p5HashRef({})))._hash_.p5hget('code')));
Expand All @@ -4275,6 +4279,7 @@ var p5100 = p5pkg['main'];
};
throw(p5pkg["Perlito5::Javascript2"].escape_string([(p5str(( p5bool((v_self || (v_self = new p5HashRef({})))._hash_.p5hget('namespace')) ? (p5str((v_self || (v_self = new p5HashRef({})))._hash_.p5hget('namespace')) + '::') : '')) + p5str(v_name))], p5want));
};
(v_may_need_autoload = (1));
};
};
}, [0], false, "");
Expand Down Expand Up @@ -4374,6 +4379,15 @@ var p5100 = p5pkg['main'];
}, p5list_to_a((v_arg_list || (v_arg_list = new p5ArrayRef([])))._array_), false, "");
var v_arg_code;
(v_arg_code = (( (p5str((v_self || (v_self = new p5HashRef({})))._hash_.p5hget('code')) == 'scalar') ? ('[' + p5pkg["Perlito5::AST::Apply"].join([', ', p5list_to_a(List_args)], 0) + ']') : p5pkg["Perlito5::Javascript2"].to_list([v_arg_list], 0))));
if ( p5bool(v_may_need_autoload) ) {
(function () {
var v_name;
(v_name = ((v_self || (v_self = new p5HashRef({})))._hash_.p5hget('code')));
var v_namespace;
(v_namespace = (p5or((v_self || (v_self = new p5HashRef({})))._hash_.p5hget('namespace'), function () { return p5pkg["Perlito5"]["v_PKG_NAME"] })));
throw(p5context([('p5call_sub(' + '"' + p5str(v_namespace) + '", ' + '"' + p5str(v_name) + '", ' + p5str(v_arg_code) + ', ' + p5str(( (p5str(v_wantarray) == 'list') ? '1' : ( (p5str(v_wantarray) == 'scalar') ? '0' : ( (p5str(v_wantarray) == 'void') ? 'null' : 'p5want')))) + ')')], p5want));
})();
};
return (p5context([(p5str(v_code) + '(' + p5str(v_arg_code) + ', ' + p5str(( (p5str(v_wantarray) == 'list') ? '1' : ( (p5str(v_wantarray) == 'scalar') ? '0' : ( (p5str(v_wantarray) == 'void') ? 'null' : 'p5want')))) + ')')], p5want));
}
catch(err) {
Expand Down Expand Up @@ -10332,7 +10346,7 @@ return r;
var v_realfilename;
(v_realfilename = (p5pkg["main"]["Hash_INC"].p5hget(p5str(v_filename))));
var v_source;
(v_source = (p5pkg["Perlito5::IO"].slurp([v_realfilename], 0)));
(v_source = (p5call_sub("Perlito5::IO", "slurp", [v_realfilename], 0)));
var v_m;
(v_m = (p5call(p5pkg["Perlito5::Grammar"], "exp_stmts", [v_source, 0], 0)));
if ( (p5num((v_m || (v_m = new p5HashRef({})))._hash_.p5hget('to')) != p5pkg["Perlito5::Grammar::Use"].length([v_source], 0)) ) {
Expand Down Expand Up @@ -10390,7 +10404,7 @@ return r;
var r;
p5pkg["main"]["v_@"] = "";
try {
r = eval(perl5_to_js(p5str(p5pkg["Perlito5::IO"].slurp(p5list_to_a(p5pkg["main"]["Hash_INC"].p5hget(p5str(v_filename))), 0)), "Perlito5::Grammar::Use", (new p5ArrayRef(p5list_to_a((new p5HashRef(p5a_to_h(p5list_to_a('$filename', (new p5HashRef({'decl' : 'my'})), '$is_bareword', (new p5HashRef({'decl' : 'my'})), '$result', (new p5HashRef({'decl' : 'my'})))))), (new p5HashRef(p5a_to_h(p5list_to_a('$AUTOLOAD', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5::Grammar::Use'})), '$_', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5::Grammar::Use'})), '$a', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5::Grammar::Use'})), '$b', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5::Grammar::Use'})), '%Perlito_internal_module', (new p5HashRef({'decl' : 'my'})))))), (new p5HashRef(p5a_to_h(p5list_to_a('$AUTOLOAD', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5'})), '$_', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5'})), '$a', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5'})), '$b', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5'})))))), (new p5HashRef(p5a_to_h(p5list_to_a('$@', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$AUTOLOAD', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$^O', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$_', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$a', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$b', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$|', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '%ENV', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '%INC', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '@#', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '@ARGV', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '@INC', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '@_', (new p5HashRef({'decl' : 'my'}))))))))), ""))
r = eval(perl5_to_js(p5str(p5call_sub("Perlito5::IO", "slurp", p5list_to_a(p5pkg["main"]["Hash_INC"].p5hget(p5str(v_filename))), 0)), "Perlito5::Grammar::Use", (new p5ArrayRef(p5list_to_a((new p5HashRef(p5a_to_h(p5list_to_a('$filename', (new p5HashRef({'decl' : 'my'})), '$is_bareword', (new p5HashRef({'decl' : 'my'})), '$result', (new p5HashRef({'decl' : 'my'})))))), (new p5HashRef(p5a_to_h(p5list_to_a('$AUTOLOAD', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5::Grammar::Use'})), '$_', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5::Grammar::Use'})), '$a', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5::Grammar::Use'})), '$b', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5::Grammar::Use'})), '%Perlito_internal_module', (new p5HashRef({'decl' : 'my'})))))), (new p5HashRef(p5a_to_h(p5list_to_a('$AUTOLOAD', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5'})), '$_', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5'})), '$a', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5'})), '$b', (new p5HashRef({'decl' : 'our', 'namespace' : 'Perlito5'})))))), (new p5HashRef(p5a_to_h(p5list_to_a('$@', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$AUTOLOAD', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$^O', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$_', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$a', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$b', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '$|', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '%ENV', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '%INC', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '@#', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '@ARGV', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '@INC', (new p5HashRef({'decl' : 'our', 'namespace' : 'main'})), '@_', (new p5HashRef({'decl' : 'my'}))))))))), ""))
}
catch(err) {
if ( err instanceof p5_error || err instanceof Error ) {
Expand Down
22 changes: 18 additions & 4 deletions perlito5.pl

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions src5/lib/Perlito5/Javascript2/Emitter.pm
Expand Up @@ -2066,6 +2066,7 @@ package Perlito5::AST::Apply;
}

my $sig;
my $may_need_autoload;
{
my $name = $self->{code};
my $namespace = $self->{namespace} || $Perlito5::PKG_NAME;
Expand All @@ -2086,10 +2087,12 @@ package Perlito5::AST::Apply;
if ( $Perlito5::STRICT ) {
die 'Bareword "' . $name . '" not allowed while "strict subs" in use';
}
# bareword doesn't call AUTOLOAD
return Perlito5::Javascript2::escape_string(
($self->{namespace} ? $self->{namespace} . '::' : "") . $name
);
}
$may_need_autoload = 1;
}
}

Expand Down Expand Up @@ -2179,6 +2182,24 @@ package Perlito5::AST::Apply;
? '[' . join(', ', @args) . ']'
: Perlito5::Javascript2::to_list($arg_list);


if ( $may_need_autoload ) {
# p5call_sub(namespace, name, list, p5want)
my $name = $self->{code};
my $namespace = $self->{namespace} || $Perlito5::PKG_NAME;
return 'p5call_sub('
. '"' . $namespace . '", '
. '"' . $name . '", '
. $arg_code . ', '
. ($wantarray eq 'list' ? '1'
:$wantarray eq 'scalar' ? '0'
:$wantarray eq 'void' ? 'null'
: 'p5want'
)
. ')';

}

$code . '('
. $arg_code . ', '
. ($wantarray eq 'list' ? '1'
Expand Down
7 changes: 5 additions & 2 deletions src5/lib/Perlito5/Javascript2/Runtime.pm
Expand Up @@ -139,6 +139,8 @@ function p5method_lookup(method, class_name, seen) {
function p5call(invocant, method, list, p5want) {
list.unshift(invocant);
p5want = 0; // TODO BUG - workaround for broken bootstrap
if (typeof invocant === "string") {
invocant = p5make_package(invocant);
}
Expand Down Expand Up @@ -181,10 +183,11 @@ function p5call(invocant, method, list, p5want) {
function p5call_sub(namespace, name, list, p5want) {
if(p5pkg[namespace].hasOwnProperty(name)) {
// TODO
return p5pkg[namespace][name](list, p5want)
}
if(p5pkg[namespace].hasOwnProperty("AUTOLOAD")) {
// TODO
p5pkg[namespace]["v_AUTOLOAD"] = namespace + "::" + name;
return p5pkg[namespace]["AUTOLOAD"](list, p5want)
}
p5pkg.CORE.die(["Undefined subroutine &" + namespace + "::" + name]);
}
Expand Down
19 changes: 19 additions & 0 deletions src5/lib/Perlito5/Javascript3/Emitter.pm
Expand Up @@ -1953,6 +1953,7 @@ package Perlito5::AST::Apply;
}

my $sig;
my $may_need_autoload;
{
my $name = $self->{code};
my $namespace = $self->{namespace} || $Perlito5::PKG_NAME;
Expand All @@ -1977,6 +1978,7 @@ package Perlito5::AST::Apply;
($self->{namespace} ? $self->{namespace} . '::' : "") . $name
);
}
$may_need_autoload = 1;
}
}

Expand Down Expand Up @@ -2071,6 +2073,23 @@ package Perlito5::AST::Apply;
. join(', ', map( $_->emit_javascript3($level, "list", "lvalue"), @$arg_list) )
. ')';

if ( $may_need_autoload ) {
# p5call_sub(namespace, name, list, p5want)
my $name = $self->{code};
my $namespace = $self->{namespace} || $Perlito5::PKG_NAME;
return 'p5call_sub('
. '"' . $namespace . '", '
. '"' . $name . '", '
. $arg_code . ', '
. ($wantarray eq 'list' ? '1'
:$wantarray eq 'scalar' ? '0'
:$wantarray eq 'void' ? 'null'
: 'p5want'
)
. ')';

}

$code . '('
. $arg_code . ', '
. ($wantarray eq 'list' ? '1'
Expand Down
7 changes: 5 additions & 2 deletions src5/lib/Perlito5/Javascript3/Runtime.pm
Expand Up @@ -147,6 +147,8 @@ function p5method_lookup(method, class_name, seen) {
function p5call(invocant, method, list, p5want) {
list.unshift(invocant);
p5want = 0; // TODO BUG - workaround for broken bootstrap
if (invocant instanceof p5Scalar) {
// TODO - move p5call() to p5Scalar method
invocant = invocant.FETCH();
Expand Down Expand Up @@ -197,10 +199,11 @@ function p5call(invocant, method, list, p5want) {
function p5call_sub(namespace, name, list, p5want) {
if(p5pkg[namespace].hasOwnProperty(name)) {
// TODO
return p5pkg[namespace][name](list, p5want)
}
if(p5pkg[namespace].hasOwnProperty("AUTOLOAD")) {
// TODO
p5pkg[namespace]["v_AUTOLOAD"] = namespace + "::" + name;
return p5pkg[namespace]["AUTOLOAD"](list, p5want)
}
p5pkg.CORE.die(["Undefined subroutine &" + namespace + "::" + name]);
}
Expand Down
8 changes: 7 additions & 1 deletion t5/01-perlito/31-autoload.t
@@ -1,7 +1,7 @@
use feature 'say';
use strict;

say "1..4";
say "1..5";

{

Expand Down Expand Up @@ -39,5 +39,11 @@ say "1..4";
print "not " if $x[0] != 6 || $x[1] != 7;
say "ok 4";

{
no strict;
my $v = XYZ;
print "not " if $v == 456;
say "ok 5 # bareword doesn't call AUTOLOAD";
}
}

0 comments on commit b371c5d

Please sign in to comment.