Skip to content
This repository
Browse code

Perlito5 - add "Javascript3" backend (containers are objects)

  • Loading branch information...
commit bd673d3000ea80bddf98d50592f98d178b795517 1 parent f9a20c8
Flavio S. Glock authored September 23, 2012
718  html/perlito5.js
335 additions, 383 deletions not shown
1,160  perlito5.pl
603 additions, 557 deletions not shown
68  src5/lib/Perlito5/Javascript/CORE.pm → src5/lib/Perlito5/Javascript3/CORE.pm
... ...
@@ -1,15 +1,15 @@
1 1
 use v5;
2 2
 
3  
-package Perlito5::Javascript::CORE;
  3
+package Perlito5::Javascript3::CORE;
4 4
 
5  
-sub emit_javascript {
  5
+sub emit_javascript3 {
6 6
 
7 7
     return <<'EOT'
8 8
 //
9 9
 //
10  
-// lib/Perlito5/Javascript/CORE.js
  10
+// lib/Perlito5/Javascript3/CORE.js
11 11
 //
12  
-// CORE functions for "Perlito" Perl5-in-Javascript
  12
+// CORE functions for "Perlito" Perl5-in-Javascript3
13 13
 //
14 14
 // AUTHORS
15 15
 //
@@ -72,6 +72,12 @@ CORE.warn = function(List__) {
72 72
 CORE.bless = function(List__) {
73 73
     var o        = List__[0];
74 74
     var pkg_name = List__[1];
  75
+    if (o instanceof p5Scalar) {
  76
+        o = o._v_;
  77
+    }
  78
+    if (pkg_name instanceof p5Scalar) {
  79
+        pkg_name = pkg_name._v_;
  80
+    }
75 81
     if (typeof pkg_name === "object") {
76 82
         // bless {}, Class
77 83
         o._class_ = pkg_name;
@@ -164,12 +170,16 @@ CORE.substr = function(List__) {
164 170
     return p5str(expr).substr(offset, length);
165 171
 };
166 172
 
  173
+CORE.defined = function(List__) {
  174
+    return (List__[0] instanceof p5Scalar) ? ( List__[0]._v_ != null ) : ( List__[0] != null )
  175
+};
  176
+
167 177
 CORE.values = function(List__, p5want) {
168  
-    var o = List__[0];
  178
+    var o = List__[0]._hash_;
169 179
     delete o["_each_"];
170 180
     if (p5want) {
171 181
         if (o == null) {
172  
-            return [];
  182
+            return new p5Array([]);
173 183
         };
174 184
         if (typeof o.values === "function") {
175 185
             return o.values();
@@ -178,17 +188,17 @@ CORE.values = function(List__, p5want) {
178 188
         for (var i in o) {
179 189
             out.push(o[i]);
180 190
         }
181  
-        return out;
  191
+        return new p5Array(out);
182 192
     }
183 193
     return CORE.keys(List__, p5want);
184 194
 };
185 195
 
186 196
 CORE.keys = function(List__, p5want) {
187  
-    var o = List__[0];
  197
+    var o = List__[0]._hash_;
188 198
     delete o["_each_"];
189 199
     if (p5want) {
190 200
         if (o == null) {
191  
-            return [];
  201
+            return new p5Array([]);
192 202
         }
193 203
         if (typeof o.keys === "function") {
194 204
             return o.keys();
@@ -197,7 +207,7 @@ CORE.keys = function(List__, p5want) {
197 207
         for (var i in o) {
198 208
             out.push(i);
199 209
         }
200  
-        return out;
  210
+        return new p5Array(out);
201 211
     }
202 212
     else {
203 213
         if (o == null) {
@@ -248,7 +258,7 @@ CORE.reverse = function(List__) {
248 258
 };
249 259
 
250 260
 CORE.splice = function(List__, p5want) {
251  
-    var array  = List__.shift();
  261
+    var array  = List__.shift()._array_;
252 262
     // CORE.say([ array ]);
253 263
     var offset = p5num(List__.shift());
254 264
     var limit  = List__.length ? p5num(List__.shift()) : (array.length + 1);
@@ -269,49 +279,47 @@ CORE.splice = function(List__, p5want) {
269 279
 
270 280
 CORE.pop = function(List__) {
271 281
     var o = List__[0];
272  
-    if (o.length == null) {
  282
+    if (o._array_.length == null) {
273 283
         return null;
274 284
     }
275  
-    return o.pop();
  285
+    return o._array_.pop();
276 286
 };
277 287
 
278 288
 CORE.shift = function(List__) {
279 289
     var o = List__[0];
280  
-    if (o.length == null) {
  290
+    if (o._array_.length == null) {
281 291
         return null;
282 292
     }
283  
-    return o.shift();
  293
+    return o._array_.shift();
284 294
 };
285 295
 
286 296
 CORE.push = function(List__) {
287 297
     var o = List__[0];
288 298
     var v = List__[1];
289  
-    for(var i = 0; i < v.length; i++) {
290  
-        o.push(v[i]);
  299
+    for(var i = 0; i < v._array_.length; i++) {
  300
+        o._array_.push(v._array_[i]);
291 301
     }
292  
-    return o.length;
  302
+    return o._array_.length;
293 303
 };
294 304
 
295 305
 CORE.unshift = function(List__) {
296 306
     var o = List__[0];
297 307
     var v = List__[1];
298  
-    for(var i = v.length-1; i >= 0; i--) {
299  
-        o.unshift(v[i]);
  308
+    for(var i = v._array_.length-1; i >= 0; i--) {
  309
+        o._array_.unshift(v._array_[i]);
300 310
     }
301  
-    return o.length;
  311
+    return o._array_.length;
302 312
 };
303 313
 
304 314
 CORE.join = function(List__) {
305 315
     var s = List__[0];
306 316
     var o = List__[1];
307  
-    return o.join(s);
  317
+    return o._array_.join(s);
308 318
 };
309 319
 
310 320
 CORE.index = function(List__) {
311  
-    var o = List__[0];
312  
-    var s = List__[1];
313 321
     try {
314  
-        return o.indexOf(s, p5num(List__[2]));
  322
+        return p5str(List__[0]).indexOf(p5str(List__[1]), p5num(List__[2]));
315 323
     }
316 324
     catch(err) {
317 325
         return -1;
@@ -339,10 +347,7 @@ CORE.rindex = function(List__) {
339 347
 };
340 348
 
341 349
 CORE.length = function(List__) {
342  
-    var o = List__[0];
343  
-    if (typeof o.string === "function") {
344  
-        return o.string().length;
345  
-    }
  350
+    var o = p5str(List__[0]);
346 351
     return o.length;
347 352
 };
348 353
 
@@ -351,6 +356,9 @@ CORE.unpack  = function(List__) { CORE.warn([ "CORE::unpack not implemented" ])
351 356
 
352 357
 CORE.ref = function(List__) {
353 358
     var o = List__[0];
  359
+    if (o instanceof p5Scalar) {
  360
+        o = o._v_;
  361
+    }
354 362
     if (o == null) {
355 363
         return "";
356 364
     }
@@ -395,7 +403,7 @@ CORE.prototype = function(List__, data) {
395 403
 };
396 404
 
397 405
 EOT
398  
-} # end of emit_javascript()
  406
+} # end of emit_javascript3()
399 407
 
400 408
 1;
401 409
 
826  src5/lib/Perlito5/Javascript/Emitter.pm → src5/lib/Perlito5/Javascript3/Emitter.pm
@@ -3,7 +3,7 @@ use v5;
3 3
 use Perlito5::AST;
4 4
 use Perlito5::Dumper;
5 5
 
6  
-package Perlito5::Javascript;
  6
+package Perlito5::Javascript3;
7 7
 {
8 8
     my $label_count = 100;
9 9
     my %label;
@@ -174,10 +174,10 @@ package Perlito5::Javascript;
174 174
                 || ($cond->isa( 'Perlito5::AST::Apply' )  && exists $op_to_str{ $cond->code } )
175 175
                 )
176 176
             {
177  
-                return $cond->emit_javascript($level, $wantarray);
  177
+                return $cond->emit_javascript3($level, $wantarray);
178 178
             }
179 179
             else {
180  
-                return 'p5str(' . $cond->emit_javascript($level, $wantarray) . ')';
  180
+                return 'p5str(' . $cond->emit_javascript3($level, $wantarray) . ')';
181 181
             }
182 182
     }
183 183
     sub to_num {
@@ -189,10 +189,10 @@ package Perlito5::Javascript;
189 189
                 || ($cond->isa( 'Perlito5::AST::Apply' )  && exists $op_to_num{ $cond->code } )
190 190
                 )
191 191
             {
192  
-                return $cond->emit_javascript($level, $wantarray);
  192
+                return $cond->emit_javascript3($level, $wantarray);
193 193
             }
194 194
             else {
195  
-                return 'p5num(' . $cond->emit_javascript($level, $wantarray) . ')';
  195
+                return 'p5num(' . $cond->emit_javascript3($level, $wantarray) . ')';
196 196
             }
197 197
     }
198 198
     sub to_bool {
@@ -232,10 +232,10 @@ package Perlito5::Javascript;
232 232
                 || ($cond->isa( 'Perlito5::AST::Apply' ) && exists $op_to_bool{ $cond->code })
233 233
                 )
234 234
             {
235  
-                return $cond->emit_javascript($level, $wantarray);
  235
+                return $cond->emit_javascript3($level, $wantarray);
236 236
             }
237 237
             else {
238  
-                return 'p5bool(' . $cond->emit_javascript($level, $wantarray) . ')';
  238
+                return 'p5bool(' . $cond->emit_javascript3($level, $wantarray) . ')';
239 239
             }
240 240
     }
241 241
 
@@ -277,18 +277,18 @@ package Perlito5::Javascript;
277 277
                 while (@in) {
278 278
                     my $k = shift @in;
279 279
                     my $v = shift @in;
280  
-                    $k = $k->emit_javascript($level, 0);
  280
+                    $k = $k->emit_javascript3($level, 0);
281 281
 
282 282
                     $printable = 0
283 283
                         if $k =~ /[ \[]/;
284 284
 
285 285
                     $v = $v
286  
-                         ? $v->emit_javascript($level, 0)
  286
+                         ? $v->emit_javascript3($level, 0)
287 287
                          : 'null';
288 288
                     push @out, "$k : $v";
289 289
                 }
290 290
 
291  
-                return '{' . join(', ', @out) . '}'
  291
+                return 'new p5Hash({' . join(', ', @out) . '})'
292 292
                     if $printable;
293 293
 
294 294
             }
@@ -297,11 +297,11 @@ package Perlito5::Javascript;
297 297
 
298 298
         $interpolate
299 299
         ? ( 'p5list_to_a('
300  
-          .   join(', ', map( $_->emit_javascript($level, $wantarray), @$items ))
  300
+          .   join(', ', map( $_->emit_javascript3($level, $wantarray), @$items ))
301 301
           . ')'
302 302
           )
303 303
         : ( '['
304  
-          .   join(', ', map( $_->emit_javascript($level, $wantarray), @$items ))
  304
+          .   join(', ', map( $_->emit_javascript3($level, $wantarray), @$items ))
305 305
           . ']'
306 306
           )
307 307
     }
@@ -340,7 +340,7 @@ package Perlito5::Javascript;
340 340
 
341 341
         @$items
342 342
         ?   '('
343  
-          .   join(', ', map( $_->emit_javascript($level, $wantarray), @$items ))
  343
+          .   join(', ', map( $_->emit_javascript3($level, $wantarray), @$items ))
344 344
           . ')'
345 345
         : 'null'
346 346
     }
@@ -375,45 +375,69 @@ package Perlito5::Javascript;
375 375
         my $level = $_[1];
376 376
         my $wantarray = 'runtime';
377 377
 
378  
-        return $items->[0]->emit_javascript($level, $wantarray)
  378
+        return $items->[0]->emit_javascript3($level, $wantarray)
379 379
             if @$items == 1 && is_scalar($items->[0]);
380 380
 
381 381
         'p5context(' 
382 382
             . '['
383  
-            .   join(', ', map( $_->emit_javascript($level, $wantarray), @$items ))
  383
+            .   join(', ', map( $_->emit_javascript3($level, $wantarray), @$items ))
384 384
             . ']'
385 385
             . ', p5want)'
386 386
     }
387 387
 
388  
-    sub emit_javascript_autovivify {
  388
+    sub autoquote {
  389
+        my $index = shift;
  390
+        my $level = shift;
  391
+    
  392
+        # ok   ' sub x () { 123 } $v{x()} = 12; use Data::Dumper; print Dumper \%v '       # '123'     => 12
  393
+        # ok   ' sub x () { 123 } $v{x} = 12; use Data::Dumper; print Dumper \%v '         # 'x'       => 12
  394
+        # TODO ' sub x () { 123 } $v{main::x} = 12; use Data::Dumper; print Dumper \%v '   # '123'     => 12
  395
+        # ok   ' $v{main::x} = 12; use Data::Dumper; print Dumper \%v '                    # 'main::x' => 12
  396
+    
  397
+        if ($index->isa('Perlito5::AST::Apply')
  398
+           && $index->{bareword}
  399
+           )
  400
+        {
  401
+            $index = Perlito5::AST::Val::Buf->new( 
  402
+                buf => ($index->{namespace} ? $index->{namespace} . '::' : "") . $index->{code} 
  403
+            );
  404
+        }
  405
+    
  406
+        return to_str($index, $level);
  407
+    }
  408
+
  409
+    sub emit_javascript3_autovivify {
389 410
         my $obj = shift;
390 411
         my $level = shift;
391 412
         my $type = shift;  # 'array'/'hash'
  413
+        my $wantarray = 'scalar';
392 414
 
393  
-          '(' .  $obj->emit_javascript($level)
394  
-        .   ' || (' . $obj->emit_javascript($level) . ' = ' 
395  
-                    . ( $type eq 'array' ? 'new p5ArrayRef([])' 
396  
-                      : $type eq 'hash'  ? 'new p5HashRef({})'
397  
-                      :                    'new p5ScalarRef(null)'
398  
-                      )
399  
-              . ')'
400  
-        . ')'
  415
+        return $obj->emit_javascript3($level, $wantarray, $type);
  416
+
  417
+        #   '(' .  $obj->emit_javascript3($level)
  418
+        # .   ' || (' . $obj->emit_javascript3($level) . ' = ' 
  419
+        #             . ( $type eq 'array' ? 'new p5ArrayRef(new p5Array([]))' 
  420
+        #               : $type eq 'hash'  ? 'new p5HashRef(new p5Hash({}))'
  421
+        #               :                    'new p5ScalarRef(null)'
  422
+        #               )
  423
+        #       . ')'
  424
+        # . ')'
401 425
     }
402 426
 
403  
-    sub emit_function_javascript {
  427
+    sub emit_function_javascript3 {
404 428
         my $level = shift;
405 429
         my $wantarray = shift;
406 430
         my $argument = shift;
407 431
 
408 432
         if ( $argument->isa( 'Perlito5::AST::Apply' ) && $argument->code eq 'return' ) {
409  
-            return 'function () { ' . $argument->emit_javascript($level, $wantarray) . ' }';
  433
+            return 'function () { ' . $argument->emit_javascript3($level, $wantarray) . ' }';
410 434
         }
411  
-        return 'function () { return ' . $argument->emit_javascript($level, $wantarray) . ' }';
  435
+        return 'function () { return ' . $argument->emit_javascript3($level, $wantarray) . ' }';
412 436
     }
413 437
 
414 438
 }
415 439
 
416  
-package Perlito5::Javascript::LexicalBlock;
  440
+package Perlito5::Javascript3::LexicalBlock;
417 441
 {
418 442
     sub new { my $class = shift; bless {@_}, $class }
419 443
     sub block { $_[0]->{block} }
@@ -447,7 +471,7 @@ package Perlito5::Javascript::LexicalBlock;
447 471
     }
448 472
 
449 473
 
450  
-    sub emit_javascript {
  474
+    sub emit_javascript3 {
451 475
         my $self = shift;
452 476
         my $level = shift;
453 477
         my $wantarray = shift;
@@ -459,7 +483,7 @@ package Perlito5::Javascript::LexicalBlock;
459 483
             }
460 484
         }
461 485
         if (!@block) {
462  
-            return Perlito5::Javascript::tab($level) . 'null;';
  486
+            return Perlito5::Javascript3::tab($level) . 'null;';
463 487
         }
464 488
         my $out = '';
465 489
         my @str;
@@ -472,17 +496,17 @@ package Perlito5::Javascript::LexicalBlock;
472 496
         $Perlito5::THROW = 0
473 497
             if $self->{top_level};
474 498
 
475  
-        $out .= Perlito5::Javascript::tab($level) . "var local_idx = p5LOCAL.length;\n"
  499
+        $out .= Perlito5::Javascript3::tab($level) . "var local_idx = p5LOCAL.length;\n"
476 500
             if $has_local;
477 501
         if ($self->{top_level}) {
478 502
             $level++;
479 503
         }
480 504
         if ( $create_context ) {
481  
-            $out .= Perlito5::Javascript::tab($level) . "(function () {\n";
  505
+            $out .= Perlito5::Javascript3::tab($level) . "(function () {\n";
482 506
             $level++;
483 507
         }
484 508
 
485  
-        my $tab = Perlito5::Javascript::tab($level);
  509
+        my $tab = Perlito5::Javascript3::tab($level);
486 510
         my $last_statement;
487 511
         if ($self->{needs_return}) {
488 512
             $last_statement = pop @block;
@@ -497,35 +521,35 @@ package Perlito5::Javascript::LexicalBlock;
497 521
             }
498 522
 
499 523
             if ($decl->isa( 'Perlito5::AST::Decl' )) {
500  
-                push @str, $decl->emit_javascript_init;
  524
+                push @str, $decl->emit_javascript3_init;
501 525
             }
502 526
             # TODO - local, our
503 527
             if ($decl->isa( 'Perlito5::AST::Apply' ) && $decl->code eq 'my' ) {
504 528
                 for (@{$decl->{arguments}}) {
505 529
                     if ($_->isa( 'Perlito5::AST::Var' )) {
506 530
                         my $d = Perlito5::AST::Decl->new( decl => $decl->code, var => $_ );
507  
-                        push @str, $d->emit_javascript_init;
  531
+                        push @str, $d->emit_javascript3_init;
508 532
                     }
509 533
                 }
510 534
             }
511 535
             if ($decl->isa( 'Perlito5::AST::Apply' ) && $decl->code eq 'infix:<=>') {
512 536
                 my $arg = $decl->{arguments}[0];
513 537
                 if ($arg->isa( 'Perlito5::AST::Decl' )) {
514  
-                    push @str, $arg->emit_javascript_init;
  538
+                    push @str, $arg->emit_javascript3_init;
515 539
                 }
516 540
                 # TODO - local, our
517 541
                 if ($arg->isa( 'Perlito5::AST::Apply' ) && $arg->code eq 'my' ) {
518 542
                     for (@{$arg->{arguments}}) {
519 543
                         if ($_->isa( 'Perlito5::AST::Var' )) {
520 544
                             my $d = Perlito5::AST::Decl->new( decl => $arg->code, var => $_ );
521  
-                            push @str, $d->emit_javascript_init;
  545
+                            push @str, $d->emit_javascript3_init;
522 546
                         }
523 547
                     }
524 548
                 }
525 549
             }
526 550
 
527 551
             if (!( $decl->isa( 'Perlito5::AST::Decl' ) && $decl->decl eq 'my' )) {
528  
-                push @str, $decl->emit_javascript($level, 'void') . ';';
  552
+                push @str, $decl->emit_javascript3($level, 'void') . ';';
529 553
             }
530 554
         }
531 555
 
@@ -534,11 +558,11 @@ package Perlito5::Javascript::LexicalBlock;
534 558
         if ($self->{needs_return} && $last_statement) {
535 559
 
536 560
             if ($last_statement->isa( 'Perlito5::AST::Decl' )) {
537  
-                push @str, $last_statement->emit_javascript_init;
  561
+                push @str, $last_statement->emit_javascript3_init;
538 562
             }
539 563
             if ($last_statement->isa( 'Perlito5::AST::Apply' ) && $last_statement->code eq 'infix:<=>') {
540 564
                 if ($last_statement->{arguments}[0]->isa( 'Perlito5::AST::Decl' )) {
541  
-                    push @str, $last_statement->{arguments}[0]->emit_javascript_init;
  565
+                    push @str, $last_statement->{arguments}[0]->emit_javascript3_init;
542 566
                 }
543 567
             }
544 568
             if  (  $last_statement->isa( 'Perlito5::AST::Apply' ) 
@@ -554,25 +578,25 @@ package Perlito5::Javascript::LexicalBlock;
554 578
                 my $cond      = $last_statement->cond;
555 579
                 my $body      = $last_statement->body;
556 580
                 my $otherwise = $last_statement->otherwise;
557  
-                $body         = Perlito5::Javascript::LexicalBlock->new( block => $body->stmts, needs_return => 1 );
  581
+                $body         = Perlito5::Javascript3::LexicalBlock->new( block => $body->stmts, needs_return => 1 );
558 582
                 push @str,
559  
-                        'if ( ' . Perlito5::Javascript::to_bool( $cond, $level+1 ) . ' ) {' . "\n"
560  
-                        .   $body->emit_javascript($level+1) . "\n"
561  
-                        . Perlito5::Javascript::tab($level) . '}';
  583
+                        'if ( ' . Perlito5::Javascript3::to_bool( $cond, $level+1 ) . ' ) {' . "\n"
  584
+                        .   $body->emit_javascript3($level+1) . "\n"
  585
+                        . Perlito5::Javascript3::tab($level) . '}';
562 586
                 if ($otherwise) {
563  
-                    $otherwise = Perlito5::Javascript::LexicalBlock->new( block => $otherwise->stmts, needs_return => 1 );
  587
+                    $otherwise = Perlito5::Javascript3::LexicalBlock->new( block => $otherwise->stmts, needs_return => 1 );
564 588
                     push @str, "\n"
565  
-                        . Perlito5::Javascript::tab($level) . 'else {' . "\n"
566  
-                        .   $otherwise->emit_javascript($level+1) . "\n"
567  
-                        . Perlito5::Javascript::tab($level) . '}';
  589
+                        . Perlito5::Javascript3::tab($level) . 'else {' . "\n"
  590
+                        .   $otherwise->emit_javascript3($level+1) . "\n"
  591
+                        . Perlito5::Javascript3::tab($level) . '}';
568 592
                 }
569 593
             }
570 594
             elsif ( $last_statement->isa( 'Perlito5::AST::Lit::Block' ) ) {
571  
-                my $body = Perlito5::Javascript::LexicalBlock->new( block => $last_statement->{stmts}, needs_return => 1 );
  595
+                my $body = Perlito5::Javascript3::LexicalBlock->new( block => $last_statement->{stmts}, needs_return => 1 );
572 596
                 push @str,
573 597
                       'for (var i_ = 0; i_ < 1 ; i_++) {' . "\n"
574  
-                    .   $body->emit_javascript( $level + 1 ) . "\n"
575  
-                    . Perlito5::Javascript::tab($level) . '}'
  598
+                    .   $body->emit_javascript3( $level + 1 ) . "\n"
  599
+                    . Perlito5::Javascript3::tab($level) . '}'
576 600
             }
577 601
             elsif (  $last_statement->isa( 'Perlito5::AST::For' )
578 602
                   || $last_statement->isa( 'Perlito5::AST::While' )
@@ -580,14 +604,14 @@ package Perlito5::Javascript::LexicalBlock;
580 604
                   || $last_statement->isa( 'Perlito5::AST::Apply' ) && $last_statement->code eq 'return'
581 605
                   )
582 606
             {
583  
-                push @str, $last_statement->emit_javascript($level, 'runtime');
  607
+                push @str, $last_statement->emit_javascript3($level, 'runtime');
584 608
             }
585 609
             else {
586 610
                 if ( $has_local ) {
587  
-                    push @str, 'return p5cleanup_local(local_idx, (' . Perlito5::Javascript::to_runtime_context([$last_statement], $level) . '));';
  611
+                    push @str, 'return p5cleanup_local(local_idx, (' . Perlito5::Javascript3::to_runtime_context([$last_statement], $level) . '));';
588 612
                 }
589 613
                 else {
590  
-                    push @str, 'return (' . Perlito5::Javascript::to_runtime_context([$last_statement], $level) . ');';
  614
+                    push @str, 'return (' . Perlito5::Javascript3::to_runtime_context([$last_statement], $level) . ');';
591 615
                 }
592 616
             }
593 617
         }
@@ -604,22 +628,22 @@ package Perlito5::Javascript::LexicalBlock;
604 628
 
605 629
             $level--;
606 630
             $out .= 
607  
-                  Perlito5::Javascript::tab($level) . "try {\n"
  631
+                  Perlito5::Javascript3::tab($level) . "try {\n"
608 632
                 .   join("\n", map($tab . $_, @str)) . "\n"
609  
-                . Perlito5::Javascript::tab($level)   . '}' . "\n"
610  
-                . Perlito5::Javascript::tab($level)   . 'catch(err) {' . "\n"
611  
-                . Perlito5::Javascript::tab($level + 1)   . 'if ( err instanceof Error ) {' . "\n"
612  
-                . Perlito5::Javascript::tab($level + 2)       . 'throw(err);' . "\n"
613  
-                . Perlito5::Javascript::tab($level + 1)   . '}' . "\n"
614  
-                . Perlito5::Javascript::tab($level + 1)   . 'else {' . "\n"
615  
-                . Perlito5::Javascript::tab($level + 2)
  633
+                . Perlito5::Javascript3::tab($level)   . '}' . "\n"
  634
+                . Perlito5::Javascript3::tab($level)   . 'catch(err) {' . "\n"
  635
+                . Perlito5::Javascript3::tab($level + 1)   . 'if ( err instanceof Error ) {' . "\n"
  636
+                . Perlito5::Javascript3::tab($level + 2)       . 'throw(err);' . "\n"
  637
+                . Perlito5::Javascript3::tab($level + 1)   . '}' . "\n"
  638
+                . Perlito5::Javascript3::tab($level + 1)   . 'else {' . "\n"
  639
+                . Perlito5::Javascript3::tab($level + 2)
616 640
                     . ( $has_local
617 641
                       ? 'return p5cleanup_local(local_idx, err)'
618 642
                       : 'return(err)'
619 643
                       )
620 644
                     . ";\n"
621  
-                . Perlito5::Javascript::tab($level + 1)   . '}' . "\n"
622  
-                . Perlito5::Javascript::tab($level)   . '}';
  645
+                . Perlito5::Javascript3::tab($level + 1)   . '}' . "\n"
  646
+                . Perlito5::Javascript3::tab($level)   . '}';
623 647
         }
624 648
         else {
625 649
             $out .= join("\n", map($tab . $_, @str));
@@ -635,20 +659,20 @@ package Perlito5::Javascript::LexicalBlock;
635 659
 
636 660
 package Perlito5::AST::CompUnit;
637 661
 {
638  
-    sub emit_javascript {
  662
+    sub emit_javascript3 {
639 663
         my $self = $_[0];
640 664
         my $level = $_[1];
641 665
         my $str = "(function () {\n"
642  
-            .   Perlito5::Javascript::LexicalBlock->new( block => $self->{body}, needs_return => 0 )->emit_javascript( $level + 1 ) . "\n"
643  
-            . Perlito5::Javascript::tab($level) . "})()\n";
  666
+            .   Perlito5::Javascript3::LexicalBlock->new( block => $self->{body}, needs_return => 0 )->emit_javascript( $level + 1 ) . "\n"
  667
+            . Perlito5::Javascript3::tab($level) . "})()\n";
644 668
         return $str;
645 669
     }
646  
-    sub emit_javascript_program {
  670
+    sub emit_javascript3_program {
647 671
         my $comp_units = shift;
648 672
         $Perlito5::PKG_NAME = 'main';
649 673
         my $str = ''
650 674
                 .  "var p5want = null;\n"
651  
-                .  "var " . Perlito5::Javascript::pkg_new_var() . " = p5pkg['" . $Perlito5::PKG_NAME . "'];\n";
  675
+                .  "var " . Perlito5::Javascript3::pkg_new_var() . " = p5pkg['" . $Perlito5::PKG_NAME . "'];\n";
652 676
         $Perlito5::VAR = [
653 677
             { '@_'    => { decl => 'my' }, # XXX
654 678
               '$@'    => { decl => 'our', namespace => 'main' },
@@ -666,7 +690,7 @@ package Perlito5::AST::CompUnit;
666 690
             }
667 691
         ];
668 692
         for my $comp_unit ( @$comp_units ) {
669  
-            $str = $str . $comp_unit->emit_javascript() . "\n";
  693
+            $str = $str . $comp_unit->emit_javascript3() . "\n";
670 694
         }
671 695
         return $str;
672 696
     }
@@ -674,7 +698,7 @@ package Perlito5::AST::CompUnit;
674 698
 
675 699
 package Perlito5::AST::Val::Int;
676 700
 {
677  
-    sub emit_javascript {
  701
+    sub emit_javascript3 {
678 702
         my $self  = shift;
679 703
         my $level = shift;
680 704
         $self->{int};
@@ -683,7 +707,7 @@ package Perlito5::AST::Val::Int;
683 707
 
684 708
 package Perlito5::AST::Val::Num;
685 709
 {
686  
-    sub emit_javascript {
  710
+    sub emit_javascript3 {
687 711
         my $self  = shift;
688 712
         my $level = shift;
689 713
         $self->{num};
@@ -692,25 +716,25 @@ package Perlito5::AST::Val::Num;
692 716
 
693 717
 package Perlito5::AST::Val::Buf;
694 718
 {
695  
-    sub emit_javascript {
  719
+    sub emit_javascript3 {
696 720
         my $self  = shift;
697 721
         my $level = shift;
698  
-        Perlito5::Javascript::escape_string( $self->{buf} );
  722
+        Perlito5::Javascript3::escape_string( $self->{buf} );
699 723
     }
700 724
 }
701 725
 
702 726
 package Perlito5::AST::Lit::Block;
703 727
 {
704  
-    sub emit_javascript {
  728
+    sub emit_javascript3 {
705 729
         my $self = shift;
706 730
         my $level = shift;
707 731
 
708 732
         my $init = "";
709 733
         if ($self->{name} eq 'INIT') {
710  
-            my $tmp  = 'p5pkg.main._tmp' . Perlito5::Javascript::get_label();
  734
+            my $tmp  = 'p5pkg.main._tmp' . Perlito5::Javascript3::get_label();
711 735
 
712 736
             # INIT-blocks execute only once
713  
-            $init = Perlito5::Javascript::tab($level + 2) . "if ($tmp) { return }; $tmp = 1;\n";
  737
+            $init = Perlito5::Javascript3::tab($level + 2) . "if ($tmp) { return }; $tmp = 1;\n";
714 738
 
715 739
             # TODO - make this execute before anything else
716 740
 
@@ -719,14 +743,14 @@ package Perlito5::AST::Lit::Block;
719 743
         return 'p5for_lex('
720 744
                 . "function () {\n"
721 745
                 .   $init
722  
-                .   (Perlito5::Javascript::LexicalBlock->new( block => $self->{stmts}, needs_return => 0, top_level => 0 ))->emit_javascript($level + 2) . "\n"
723  
-                . Perlito5::Javascript::tab($level + 1) . '}, '
  746
+                .   (Perlito5::Javascript3::LexicalBlock->new( block => $self->{stmts}, needs_return => 0, top_level => 0 ))->emit_javascript($level + 2) . "\n"
  747
+                . Perlito5::Javascript3::tab($level + 1) . '}, '
724 748
                 .   '[0], '
725  
-                . $self->emit_javascript_continue($level) . ', '
  749
+                . $self->emit_javascript3_continue($level) . ', '
726 750
                 .   '"' . ($self->{label} || "") . '"'
727 751
                 . ')'
728 752
     }
729  
-    sub emit_javascript_continue {
  753
+    sub emit_javascript3_continue {
730 754
         my $self = shift;
731 755
         my $level = shift;
732 756
 
@@ -736,79 +760,145 @@ package Perlito5::AST::Lit::Block;
736 760
 
737 761
         return
738 762
               "function () {\n"
739  
-            .   (Perlito5::Javascript::LexicalBlock->new( block => $self->{continue}->stmts, needs_return => 0, top_level => 0 ))->emit_javascript($level + 2) . "\n"
740  
-            . Perlito5::Javascript::tab($level + 1) . '}'
  763
+            .   (Perlito5::Javascript3::LexicalBlock->new( block => $self->{continue}->stmts, needs_return => 0, top_level => 0 ))->emit_javascript($level + 2) . "\n"
  764
+            . Perlito5::Javascript3::tab($level + 1) . '}'
741 765
     }
742 766
 }
743 767
 
744 768
 package Perlito5::AST::Index;
745 769
 {
746  
-    sub emit_javascript {
747  
-        my $self = shift;
748  
-        my $level = shift;
  770
+    sub emit_javascript3 {
  771
+        my $self      = shift;
  772
+        my $level     = shift;
  773
+        my $wantarray = shift;
  774
+        my $type      = shift;  # autovivify to 'array'/'hash'
  775
+
  776
+        $type = $type ? '"' . $type . '"' : 'null';
749 777
 
750 778
         if (  $self->{obj}->isa('Perlito5::AST::Var')
751 779
            && $self->{obj}->sigil eq '$'
752 780
            )
753 781
         {
754 782
             my $v = Perlito5::AST::Var->new( sigil => '@', namespace => $self->{obj}->namespace, name => $self->{obj}->name );
755  
-            return $v->emit_javascript($level) . '[' 
756  
-                    . 'p5idx(' 
757  
-                        . $v->emit_javascript($level) . ','
758  
-                        . Perlito5::Javascript::to_num($self->{index_exp}, $level) 
759  
-                    . ')'
760  
-                . ']';
  783
+            return $v->emit_javascript3($level) 
  784
+                    . '.aget(' . Perlito5::Javascript3::to_num($self->{index_exp}, $level) . ', ' . $type . ')';
761 785
         }
762 786
         if (  $self->{obj}->isa('Perlito5::AST::Apply')
763 787
            && $self->{obj}->{code} eq 'prefix:<$>'
764 788
            )
765 789
         {
766 790
             # $$a[0] ==> $a->[0]
767  
-            return Perlito5::AST::Call->new(
768  
-                    method    => 'postcircumfix:<[ ]>',
769  
-                    invocant  => $self->{obj}{arguments}[0],
770  
-                    arguments => $self->{index_exp},
771  
-                )->emit_javascript($level);
  791
+            return Perlito5::Javascript3::emit_javascript_autovivify( $self->{obj}{arguments}[0], $level, 'array' )
  792
+                . '.aget(' 
  793
+                        . Perlito5::Javascript3::to_num($self->{index_exp}) . ', ' . $type
  794
+                . ')';
772 795
         }
773 796
 
774  
-          Perlito5::Javascript::emit_javascript_autovivify( $self->{obj}, $level, 'array' ) . '._array_[' 
775  
-                    . 'p5idx(' 
776  
-                        . Perlito5::Javascript::emit_javascript_autovivify( $self->{obj}, $level, 'array' ) . '._array_,'
777  
-                        . Perlito5::Javascript::to_num($self->{index_exp}, $level) 
778  
-                    . ')'
779  
-                . ']';
  797
+        return Perlito5::Javascript3::emit_javascript_autovivify( $self->{obj}, $level, 'array' )
  798
+                . '.aget(' . Perlito5::Javascript3::to_num($self->{index_exp}, $level) . ', ' . $type . ')';
  799
+    }
  800
+    sub emit_javascript3_set {
  801
+        my $self      = shift;
  802
+        my $arguments = shift;
  803
+        my $level     = shift;
  804
+
  805
+        if (  $self->{obj}->isa('Perlito5::AST::Var')
  806
+           && $self->{obj}->sigil eq '$'
  807
+           )
  808
+        {
  809
+            my $v = Perlito5::AST::Var->new( sigil => '@', namespace => $self->{obj}->namespace, name => $self->{obj}->name );
  810
+            return $v->emit_javascript3($level) 
  811
+                    . '.aset(' 
  812
+                        . Perlito5::Javascript3::to_num($self->{index_exp}, $level+1) . ', ' 
  813
+                        . Perlito5::Javascript3::to_scalar([$arguments], $level+1)
  814
+                    . ')';
  815
+        }
  816
+        if (  $self->{obj}->isa('Perlito5::AST::Apply')
  817
+           && $self->{obj}->{code} eq 'prefix:<$>'
  818
+           )
  819
+        {
  820
+            # $$a[0] ==> $a->[0]
  821
+            return Perlito5::Javascript3::emit_javascript_autovivify( $self->{obj}{arguments}[0], $level, 'array' )
  822
+                . '.aset(' 
  823
+                        . Perlito5::Javascript3::to_num($self->{index_exp}) . ', '
  824
+                        . Perlito5::Javascript3::to_scalar([$arguments], $level+1)
  825
+                . ')';
  826
+        }
  827
+
  828
+        return Perlito5::Javascript3::emit_javascript_autovivify( $self->{obj}, $level, 'array' )
  829
+                . '.aset(' 
  830
+                    . Perlito5::Javascript3::to_num($self->{index_exp}, $level+1) . ', ' 
  831
+                    . Perlito5::Javascript3::to_scalar([$arguments], $level+1)
  832
+                . ')';
780 833
     }
  834
+
781 835
 }
782 836
 
783 837
 package Perlito5::AST::Lookup;
784 838
 {
785  
-    sub emit_javascript {
786  
-        my $self = shift;
787  
-        my $level = shift;
788  
-        # my $var = $self->{obj}->emit_javascript;
789  
-        # return $var . '[' . $self->{index_exp}->emit_javascript() . ']'
  839
+    sub emit_javascript3 {
  840
+        my $self      = shift;
  841
+        my $level     = shift;
  842
+        my $wantarray = shift;
  843
+        my $type      = shift;  # autovivify to 'array'/'hash'
  844
+
  845
+        $type = $type ? '"' . $type . '"' : 'null';
  846
+
  847
+        # my $var = $self->{obj}->emit_javascript3;
  848
+        # return $var . '[' . $self->{index_exp}->emit_javascript3() . ']'
790 849
 
791 850
         if (  $self->{obj}->isa('Perlito5::AST::Var')
792 851
            && $self->{obj}->sigil eq '$'
793 852
            )
794 853
         {
795 854
             my $v = Perlito5::AST::Var->new( sigil => '%', namespace => $self->{obj}->namespace, name => $self->{obj}->name );
796  
-            return $v->emit_javascript($level) . '[' . $self->autoquote($self->{index_exp})->emit_javascript($level) . ']';
  855
+            return Perlito5::Javascript3::emit_javascript_autovivify( $v, $level, 'hash' ) 
  856
+                . '.hget(' . Perlito5::Javascript3::autoquote($self->{index_exp}, $level) . ', ' . $type . ')';
797 857
         }
798 858
         if (  $self->{obj}->isa('Perlito5::AST::Apply')
799 859
            && $self->{obj}->{code} eq 'prefix:<$>'
800 860
            )
801 861
         {
802 862
             # $$a{0} ==> $a->{0}
803  
-            return Perlito5::AST::Call->new(
804  
-                    method    => 'postcircumfix:<{ }>',
805  
-                    invocant  => $self->{obj}{arguments}[0],
806  
-                    arguments => $self->{index_exp},
807  
-                )->emit_javascript($level);
  863
+            return Perlito5::Javascript3::emit_javascript_autovivify( $self->{obj}{arguments}[0], $level, 'hash' )
  864
+                . '.hget(' . Perlito5::Javascript3::autoquote($self->{index_exp}, $level, 'list') . ', ' . $type . ')';
808 865
         }
809 866
 
810  
-          Perlito5::Javascript::emit_javascript_autovivify( $self->{obj}, $level, 'hash' )
811  
-        . '._hash_[' . $self->autoquote($self->{index_exp})->emit_javascript($level) . ']';
  867
+          Perlito5::Javascript3::emit_javascript_autovivify( $self->{obj}, $level, 'hash' )
  868
+        . '.hget(' . Perlito5::Javascript3::autoquote($self->{index_exp}, $level) . ', ' . $type . ')';
  869
+    }
  870
+    sub emit_javascript3_set {
  871
+        my $self      = shift;
  872
+        my $arguments = shift;
  873
+        my $level     = shift;
  874
+        # my $var = $self->{obj}->emit_javascript3;
  875
+        # return $var . '[' . $self->{index_exp}->emit_javascript3() . ']'
  876
+
  877
+        if (  $self->{obj}->isa('Perlito5::AST::Var')
  878
+           && $self->{obj}->sigil eq '$'
  879
+           )
  880
+        {
  881
+            my $v = Perlito5::AST::Var->new( sigil => '%', namespace => $self->{obj}->namespace, name => $self->{obj}->name );
  882
+            return $v->emit_javascript3($level)
  883
+                . '.hset(' . Perlito5::Javascript3::autoquote($self->{index_exp}, $level) . ', '
  884
+                    . Perlito5::Javascript3::to_scalar([$arguments], $level+1)
  885
+                . ')';
  886
+        }
  887
+        if (  $self->{obj}->isa('Perlito5::AST::Apply')
  888
+           && $self->{obj}->{code} eq 'prefix:<$>'
  889
+           )
  890
+        {
  891
+            # $$a{0} ==> $a->{0}
  892
+            return Perlito5::Javascript3::emit_javascript_autovivify( $self->{obj}{arguments}[0], $level, 'hash' )
  893
+                . '.hset(' . Perlito5::Javascript3::autoquote($self->{index_exp}, $level, 'list') . ', '
  894
+                    . Perlito5::Javascript3::to_scalar([$arguments], $level+1)
  895
+                . ')';
  896
+        }
  897
+
  898
+        Perlito5::Javascript3::emit_javascript_autovivify( $self->{obj}, $level, 'hash' )
  899
+            . '.hset(' . Perlito5::Javascript3::autoquote($self->{index_exp}, $level) . ', '
  900
+                   . Perlito5::Javascript3::to_scalar([$arguments], $level+1)
  901
+            . ')';
812 902
     }
813 903
 }
814 904
 
@@ -821,7 +911,7 @@ package Perlito5::AST::Var;
821 911
         '&' => '',
822 912
     };
823 913
 
824  
-    sub emit_javascript {
  914
+    sub emit_javascript3 {
825 915
         my $self = shift;
826 916
         my $level = shift;
827 917
         my $wantarray = shift;
@@ -847,39 +937,40 @@ package Perlito5::AST::Var;
847 937
                     die "Global symbol \"$perl5_name\" requires explicit package name"
848 938
                 }
849 939
                 # no strict - "auto-declare" the var
850  
-                $decl_type = 'our';
  940
+
  941
+                # $decl_type = 'our';
851 942
                 $self->{namespace} = $Perlito5::PKG_NAME;
852 943
 
853  
-                my $sigil = $self->{sigil} eq '$#' ? '@' : $self->{sigil};
854  
-                my $s = 'p5pkg["' . $self->{namespace} . '"]["' . $table->{$sigil} . $str_name . '"]';
  944
+                # my $sigil = $self->{sigil} eq '$#' ? '@' : $self->{sigil};
  945
+                # my $s = 'p5pkg["' . $self->{namespace} . '"]["' . $table->{$sigil} . $str_name . '"]';
855 946
 
856  
-                if ($sigil eq '@') {
857  
-                    $s = $s . ' || (' . $s . ' = [])';  # init
858  
-                    $s = 'p5pkg[' . $s . ', "' . $self->{namespace} . '"]["' . $table->{$sigil} . $str_name . '"]';
859  
-                    if ( $self->{sigil} eq '@' && $wantarray eq 'scalar' ) {
860  
-                        $s .= '.length';
861  
-                    }
862  
-                }
863  
-                elsif ($sigil eq '%') {
864  
-                    $s = $s . ' || (' . $s . ' = {})';  # init
865  
-                    $s = 'p5pkg[' . $s . ', "' . $self->{namespace} . '"]["' . $table->{$sigil} . $str_name . '"]';
866  
-                }
  947
+                # if ($sigil eq '@') {
  948
+                #     $s = $s . ' || (' . $s . ' = new p5Array([]))';  # init
  949
+                #     $s = 'p5pkg[' . $s . ', "' . $self->{namespace} . '"]["' . $table->{$sigil} . $str_name . '"]';
  950
+                #     if ( $self->{sigil} eq '@' && $wantarray eq 'scalar' ) {
  951
+                #         $s .= '._array_.length';
  952
+                #     }
  953
+                # }
  954
+                # elsif ($sigil eq '%') {
  955
+                #     $s = $s . ' || (' . $s . ' = new p5Hash({}))';  # init
  956
+                #     $s = 'p5pkg[' . $s . ', "' . $self->{namespace} . '"]["' . $table->{$sigil} . $str_name . '"]';
  957
+                # }
867 958
 
868  
-                if ($self->{sigil} eq '$#') {
869  
-                    return '(' . $s . '.length - 1)';
870  
-                }
871  
-                return $s;
  959
+                # if ($self->{sigil} eq '$#') {
  960
+                #     return '(' . $s . '._array_.length - 1)';
  961
+                # }
  962
+                # return $s;
872 963
             }
873 964
         }
874 965
 
875 966
         if ( $self->{sigil} eq '@' ) {
876 967
             if ( $wantarray eq 'scalar' ) {
877  
-                return $self->emit_javascript($level, 'list') . '.length';
  968
+                return $self->emit_javascript3($level, 'list') . '._array_.length';
878 969
             }
879 970
             if ( $wantarray eq 'runtime' ) {
880 971
                 return '(p5want'
881  
-                    . ' ? ' . $self->emit_javascript($level, 'list')
882  
-                    . ' : ' . $self->emit_javascript($level, 'list') . '.length'
  972
+                    . ' ? ' . $self->emit_javascript3($level, 'list')
  973
+                    . ' : ' . $self->emit_javascript3($level, 'list') . '._array_.length'
883 974
                     . ')';
884 975
             }
885 976
         }
@@ -896,22 +987,32 @@ package Perlito5::AST::Var;
896 987
             my $s = 'p5pkg["' . ($self->{namespace} || $decl->{namespace}) . '"]["' . $table->{$sigil} . $str_name . '"]';
897 988
 
898 989
             if ($self->{sigil} eq '$#') {
899  
-                return '(' . $s . '.length - 1)';
  990
+                return '(' . $s . '._array_.length - 1)';
900 991
             }
901 992
             return $s;
902 993
         }
903 994
 
904 995
         my $ns = '';
905 996
         if ($self->{namespace}) {
906  
-            $ns = 'p5pkg["' . $self->{namespace} . '"]';
907  
-            if ($self->{sigil} eq '$#') {
908  
-                return '(' . $ns . '["' . $table->{'@'} . $str_name . '"].length - 1)';
  997
+
  998
+            # if (!$decl_type) 
  999
+            {
  1000
+                # this is an undeclared global
  1001
+                if ($self->{sigil} eq '$#') {
  1002
+                    return '(p5global("@", "' . $self->{namespace} . '", "' . $str_name . '")._array_.length - 1)';
  1003
+                }
  1004
+                return 'p5global("' . $self->{sigil} . '", "' . $self->{namespace} . '", "' . $str_name . '")';
909 1005
             }
910  
-            return $ns . '["' . $table->{$self->{sigil}} . $str_name . '"]'
  1006
+
  1007
+            # $ns = 'p5pkg["' . $self->{namespace} . '"]';
  1008
+            # if ($self->{sigil} eq '$#') {
  1009
+            #     return '(' . $ns . '["' . $table->{'@'} . $str_name . '"].length - 1)';
  1010
+            # }
  1011
+            # return $ns . '["' . $table->{$self->{sigil}} . $str_name . '"]'
911 1012
         }
912 1013
 
913 1014
         if ($self->{sigil} eq '$#') {
914  
-            return '(' . $ns . $table->{'@'} . $str_name . '.length - 1)';
  1015
+            return '(' . $ns . $table->{'@'} . $str_name . '._array_.length - 1)';
915 1016
         }
916 1017
 
917 1018
         $ns . $table->{$self->{sigil}} . $str_name
@@ -942,12 +1043,12 @@ package Perlito5::AST::Var;
942 1043
 
943 1044
 package Perlito5::AST::Decl;
944 1045
 {
945  
-    sub emit_javascript {
  1046
+    sub emit_javascript3 {
946 1047
         my $self = shift;
947 1048
         my $level = shift;
948  
-        $self->{var}->emit_javascript( $level );
  1049
+        $self->{var}->emit_javascript3( $level );
949 1050
     }
950  
-    sub emit_javascript_init {
  1051
+    sub emit_javascript3_init {
951 1052
         my $self = shift;
952 1053
 
953 1054
         my $env = { decl => $self->{decl} };
@@ -977,30 +1078,30 @@ package Perlito5::AST::Decl;
977 1078
 
978 1079
         if ($self->{decl} eq 'my') {
979 1080
             my $str = "";
980  
-            $str = $str . 'var ' . $self->{var}->emit_javascript() . ' = ';
  1081
+            $str = $str . 'var ' . $self->{var}->emit_javascript3() . ' = ';
981 1082
             if ($self->{var}->sigil eq '%') {
982  
-                $str = $str . '{};';
  1083
+                $str = $str . 'new p5Hash({});';
983 1084
             }
984 1085
             elsif ($self->{var}->sigil eq '@') {
985  
-                $str = $str . '[];';
  1086
+                $str = $str . 'new p5Array([]);';
986 1087
             }
987 1088
             else {
988  
-                $str = $str . 'null;';
  1089
+                $str = $str . 'new p5Scalar(null);';
989 1090
             }
990 1091
             return $str;
991 1092
         }
992 1093
         elsif ($self->{decl} eq 'our') {
993 1094
             # TODO
994  
-            return '// our ' . $self->{var}->emit_javascript();
  1095
+            return '// our ' . $self->{var}->emit_javascript3();
995 1096
         }
996 1097
         elsif ($self->{decl} eq 'local') {
997 1098
             # TODO - add grammar support
998 1099
             # if ($self->var->isa("Lookup")) {
999 1100
             #     return 
1000  
-            #         'p5set_local(' . $self->var->{obj}->emit_javascript() . ', '
1001  
-            #                      . $self->var->{index_exp}->emit_javascript() . ', '
  1101
+            #         'p5set_local(' . $self->var->{obj}->emit_javascript3() . ', '
  1102
+            #                      . $self->var->{index_exp}->emit_javascript3() . ', '
1002 1103
             #                      . '""); '
1003  
-            #         . $self->{var}->emit_javascript( $level );
  1104
+            #         . $self->{var}->emit_javascript3( $level );
1004 1105
             # }
1005 1106
 
1006 1107
             my $perl5_name = $self->{var}->perl5_name;
@@ -1016,12 +1117,12 @@ package Perlito5::AST::Decl;
1016 1117
 
1017 1118
             return
1018 1119
                   'p5set_local(' . $ns . ','
1019  
-                               . Perlito5::Javascript::escape_string($self->{var}{name}) . ','
1020  
-                               . Perlito5::Javascript::escape_string($self->{var}{sigil}) . '); ' 
  1120
+                               . Perlito5::Javascript3::escape_string($self->{var}{name}) . ','
  1121
+                               . Perlito5::Javascript3::escape_string($self->{var}{sigil}) . '); ' 
1021 1122
         }
1022 1123
         elsif ($self->{decl} eq 'state') {
1023 1124
             # TODO
1024  
-            return '// state ' . $self->{var}->emit_javascript();
  1125
+            return '// state ' . $self->{var}->emit_javascript3();
1025 1126
         }
1026 1127
         else {
1027 1128
             die "not implemented: Perlito5::AST::Decl '" . $self->{decl} . "'";
@@ -1031,10 +1132,10 @@ package Perlito5::AST::Decl;
1031 1132
 
1032 1133
 package Perlito5::AST::Proto;
1033 1134
 {
1034  
-    sub emit_javascript {
  1135
+    sub emit_javascript3 {
1035 1136
         my $self = shift;
1036 1137
         my $level = shift;
1037  
-        return Perlito5::Javascript::pkg()
  1138
+        return Perlito5::Javascript3::pkg()
1038 1139
             if $self->{name} eq '__PACKAGE__';
1039 1140
         'p5pkg["' . $self->{name} . '"]'
1040 1141
     }
@@ -1042,31 +1143,28 @@ package Perlito5::AST::Proto;
1042 1143
 
1043 1144
 package Perlito5::AST::Call;
1044 1145
 {
1045  
-    sub emit_javascript {
1046  
-        my $self = shift;
1047  
-        my $level = shift;
  1146
+    sub emit_javascript3 {
  1147
+        my $self      = shift;
  1148
+        my $level     = shift;
1048 1149
         my $wantarray = shift;
  1150
+        my $type      = shift;  # autovivify to 'array'/'hash'
  1151
+
  1152
+        $type = $type ? '"' . $type . '"' : 'null';
1049 1153
 
1050 1154
         my $meth = $self->{method};
1051 1155
 
1052 1156
         if ( $meth eq 'postcircumfix:<[ ]>' ) {
1053  
-            return Perlito5::Javascript::emit_javascript_autovivify( $self->{invocant}, $level, 'array' ) . '._array_[' 
1054  
-                    . 'p5idx(' 
1055  
-                        . Perlito5::Javascript::emit_javascript_autovivify( $self->{invocant}, $level, 'array' ) . '._array_,'    
1056  
-                        . Perlito5::Javascript::to_num($self->{arguments}) 
1057  
-                    . ')'
1058  
-                . ']';
1059  
-                # TODO - array slice
1060  
-                # . '._array_[' . $self->{arguments}->emit_javascript($level, 'list') . ']';
  1157
+            return Perlito5::Javascript3::emit_javascript_autovivify( $self->{invocant}, $level, 'array' )
  1158
+                . '.aget(' . Perlito5::Javascript3::to_num($self->{arguments}) . ', ' . $type . ')';
1061 1159
         }
1062 1160
         if ( $meth eq 'postcircumfix:<{ }>' ) {
1063  
-            return Perlito5::Javascript::emit_javascript_autovivify( $self->{invocant}, $level, 'hash' )
1064  
-                . '._hash_[' . Perlito5::AST::Lookup->autoquote($self->{arguments})->emit_javascript($level, 'list') . ']';
  1161
+            return Perlito5::Javascript3::emit_javascript_autovivify( $self->{invocant}, $level, 'hash' )
  1162
+                . '.hget(' . Perlito5::Javascript3::autoquote($self->{arguments}, $level, 'list') . ', ' . $type . ')';
1065 1163
         }
1066 1164
 
1067  
-        my $invocant = $self->{invocant}->emit_javascript;
  1165
+        my $invocant = $self->{invocant}->emit_javascript3;
1068 1166
         if  ($meth eq 'postcircumfix:<( )>')  {
1069  
-            return '(' . $invocant . ')(' . Perlito5::Javascript::to_list($self->{arguments}) . ', '
  1167
+            return 'p5code(' . $invocant . ')(' . Perlito5::Javascript3::to_list($self->{arguments}) . ', '
1070 1168
                          .   ($wantarray eq 'list'   ? '1' 
1071 1169
                              :$wantarray eq 'scalar' ? '0' 
1072 1170
                              :$wantarray eq 'void'   ? 'null'
@@ -1075,14 +1173,14 @@ package Perlito5::AST::Call;
1075 1173
                     . ')';
1076 1174
         }